Python 当失去生命时,pygame摇窗

Python 当失去生命时,pygame摇窗,python,pygame,game-engine,Python,Pygame,Game Engine,我一直在尝试开发一款小型射击游戏,我希望每当英雄被击中或失去生命时,窗口都会震动,我想可能会在一个非常短的时间内重新定位窗口3次,但我不确定如何实现这一点,并保持游戏运行 以下是我的主要游戏循环代码: def game(): #set screen width = 800 height = 600 pygame.init() screen = pygame.display.set_mode((w

我一直在尝试开发一款小型射击游戏,我希望每当英雄被击中或失去生命时,窗口都会震动,我想可能会在一个非常短的时间内重新定位窗口3次,但我不确定如何实现这一点,并保持游戏运行

以下是我的主要游戏循环代码:

    def game():      
        #set screen
        width = 800
        height = 600

        pygame.init()
        screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption('UoN Invaders: Game')

        background = pygame.Surface(screen.get_size())
        background = background.convert()
        background.fill((000, 000, 000))
        screen.blit(background, (0, 0))

        pygame.display.flip()

        #load music with help of helpers.py
        music = pygame.mixer.music.load ("data/spacequest.mp3")
        pygame.mixer.music.play(-1)

        global clock, player, playerSprite, enemySprites, enemiestocreat
        global enemiesset, lvl2, laserSprites, enemyExplosion, playerExplosion, explosionSprites
        clock = pygame.time.Clock()

        i = 0  #setting i that define if the game is just starting of in the middle of the game

        space1 = Space1(i)
        space2 = Space2()
        player = Player()

        space1 = pygame.sprite.RenderPlain((space1))
        space2 = pygame.sprite.RenderPlain((space2))


        playerSprite = pygame.sprite.RenderPlain((player))


        enemySprites = pygame.sprite.RenderPlain(())

        if lvl2 == False:
            enemiestocreat = int(float(enemiesset))
            while enemiestocreat != 0:
                enemySprites.add(Enemy(enemiestocreat*50))
                enemiestocreat -= 1
        elif lvl2 == True:
            enemiesset = int(float(enemiesset)) * 2
            enemiestocreat = enemiesset
            while enemiestocreat != 0:
                enemySprites.add(Enemy(enemiestocreat*50))
                enemiestocreat -= 1            

        laserSprites = pygame.sprite.RenderPlain(())   

        enemyExplosion = pygame.sprite.RenderPlain(())

        playerExplosion = pygame.sprite.RenderPlain(())

        explosionSprites = pygame.sprite.RenderPlain(())

    # Main Loop

        global gameover, enemydead

        while gameover == False:
            clock.tick(60)
            global lives
            font = pygame.font.Font(None,36)
            text1 = font.render("Lives:" + str(lives + 1), 1, (250,250,250))
            textpos1 = text1.get_rect()
            textpos1.centerx = 750
            textpos1.centery = 590

            global enemieskilled
            text2 = font.render("Score: " + str(enemieskilled), 1, (250,250,250))
            textpos2 = text2.get_rect()
            textpos2.centerx = 55
            textpos2.centery = 590


            if int(float(enemiesset)) == enemydead: 
                    lvl2 = True
                    enemydead = 0
                    lvl2src()
            for event in pygame.event.get():
                if event.type == KEYDOWN and event.key == K_ESCAPE:
                   main()

            # Update
            i += 1        
            space1.update(i)
            space2.update()
            player.update()
            enemySprites.update()
            laserSprites.update()
            enemyExplosion.update()
            playerExplosion.update()
            explosionSprites.update()        
            screen.blit(background, (0, 0))

            # Draw
            space1.draw(screen) 
            space2.draw(screen)        
            playerSprite.draw(screen)
            enemySprites.draw(screen)
            laserSprites.draw(screen)
            enemyExplosion.draw(screen)
            playerExplosion.draw(screen)
            explosionSprites.draw(screen)   

            screen.blit(text1, textpos1)
            screen.blit(text2, textpos2)          

            pygame.display.flip()

        while gameover == True:
                gameoversrc() 
这是我的功能,我可以检测英雄是否被击中:

class Enemy(pygame.sprite.Sprite):
    def __init__(self, centerx):
        global level
        if level%2:                                                 #choosing which lecturer depending on the modulus of the level
            pygame.sprite.Sprite.__init__(self)
            self.image, self.rect = load_image("fse.png", -1)
            self.rect = self.image.get_rect()
            self.dy = 8
            self.reset()
        elif level%3:
            pygame.sprite.Sprite.__init__(self)
            self.image, self.rect = load_image("aps.png", -1)
            self.rect = self.image.get_rect()
            self.dy = 8
            self.reset()
        else:
            pygame.sprite.Sprite.__init__(self)
            self.image, self.rect = load_image("ust.png", -1)
            self.rect = self.image.get_rect()
            self.dy = 8
            self.reset()

    def update(self):
        self.rect.centerx += self.dx
        self.rect.centery += self.dy
        #checking if enemies are outside scrren
        if self.rect.top > 600:
            self.reset()

        # Laser Collisions    
        if pygame.sprite.groupcollide(enemySprites, laserSprites, 1, 1):
           explosionSprites.add(EnemyExplosion(self.rect.center))

        # Ship Collisions
        if pygame.sprite.groupcollide(playerSprite, enemySprites, 0, 1):
            global lives
            if lives == 0: 
               explosionSprites.add(PlayerExplosion(self.rect.center))
            elif lives != 0:

                explosionSprites.add(EnemyExplosion(self.rect.center))
                lives -= 1

    #randome movement of enemies
    def reset(self):
        self.rect.bottom = 0
        self.rect.centerx = random.randrange(0, 800)
        self.dy = random.randrange(5, 10)
        self.dx = random.randrange(-2, 2)

一个简单的解决方案是不直接绘制到屏幕
表面
,而是绘制到临时的
表面
。然后将该临时
曲面
点击到屏幕
曲面

如果您想摇动屏幕,只需在闪烁时对临时
曲面的位置应用偏移即可

要生成该偏移,可以使用

这里有一个完整的例子。请注意,如果玩家被落下的岩石击中,屏幕会如何晃动

import pygame
from random import randint
from itertools import repeat

pygame.init()
org_screen = pygame.display.set_mode((400, 400))
screen = org_screen.copy()
screen_rect = screen.get_rect()
player = pygame.Rect(180, 180, 20, 20)

def get_rock():
    return pygame.Rect(randint(0, 340), 0, 60, 60)

falling = get_rock()
clock = pygame.time.Clock()

# 'offset' will be our generator that produces the offset
# in the beginning, we start with a generator that 
# yields (0, 0) forever
offset = repeat((0, 0))

# this function creates our shake-generator
# it "moves" the screen to the left and right
# three times by yielding (-5, 0), (-10, 0),
# ... (-20, 0), (-15, 0) ... (20, 0) three times,
# then keeps yieling (0, 0)
def shake():
    s = -1
    for _ in xrange(0, 3):
        for x in range(0, 20, 5):
            yield (x*s, 0)
        for x in range(20, 0, 5):
            yield (x*s, 0)
        s *= -1
    while True:
        yield (0, 0)

while True:
    if pygame.event.get(pygame.QUIT): break
    pygame.event.pump()

    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]: player.move_ip(0, -2)
    if keys[pygame.K_a]: player.move_ip(-2, 0)
    if keys[pygame.K_s]: player.move_ip(0, 2)
    if keys[pygame.K_d]: player.move_ip(2, 0)
    player.clamp_ip(screen_rect) 

    falling.move_ip(0, 4)
    org_screen.fill((0, 0, 0))
    screen.fill((255,255,255))
    pygame.draw.rect(screen, (0,0,0), player)
    pygame.draw.rect(screen, (255,0,0), falling)

    if player.colliderect(falling):
        # if the player is hit by the rock,
        # we create a new shake-generator
        offset = shake()
        falling = get_rock()

    if not screen_rect.contains(falling):
        falling = get_rock()

    clock.tick(100)
    # here we draw our temporary surface to the
    # screen using the offsets created by the 
    # generators.
    org_screen.blit(screen, next(offset))
    pygame.display.flip()

对于任何正在使用Pyscroll库(它支持滚动地图和其他一些东西)的人,您可以通过调用
BufferedRenderer
上的
scroll
并选择偏移量来实现这一点

例如:

map_layer.scroll(
    (
        random.randint(0, your_offset),
        random.randint(0, your_offset)
    )
)