制作简单的太空入侵者克隆 - pygame.time.delay导致崩溃

时间:2015-05-07 19:46:06

标签: python python-2.7 time syntax

我刚开始使用Python开发一个非常简单的太空入侵者版本,我编写了玩家宇宙飞船精灵,敌人精灵和子弹精灵。

我有它,以便船只用鼠标光标水平移动,每按一下鼠标就会发射一颗子弹。子弹与敌人相撞,移除两个精灵并将分数提高1点。

在所有敌人死亡之后,它会打印出“你赢了!”在顶部。一切都很好。

然后我决定添加关卡并让入侵者每隔几秒向下移动一定量。我扔了一些time.sleep命令(是的,我记得在代码的开头导入时间),但是当我运行代码时,它导致了崩溃。
我很困惑,因为Python shell没有错误。

我认为在尝试让其他人运行时睡眠代码的一部分可能会导致我不知道的一些全局错误,所以我决定使用pygame的集成时间延迟命令来创建我想要的暂停,但我得到了相同的黑屏系统崩溃,外壳没有错误。我找不到任何类似的问题,所以我想我会在这里询问我的代码的一些帮助。很抱歉包含这么多代码 -

如果我只选择我认为有问题的部分,我只会包括那些,但我不知道问题出在哪里。我使用了太空船和入侵者精灵的图形,那就是“invadersprite.jpeg”和“player.png”。

提前致谢!

import pygame
import random

#Defining Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
PURPLE = (255, 0, 255)

level = 1

#---Defining the Space Invaders
class Block(pygame.sprite.Sprite):
    def __init__(self):
        super(Block, self).__init__()
        self.image = pygame.image.load("invadersprite.jpeg").convert()
        self.image.set_colorkey(WHITE)
        self.rect = self.image.get_rect()


    def update(self):
        #This makes the 'invaders' advance every so often.
        #The exact time should be 20 times 2^(-level), so that
        #the wait time can never be negative and so that it decreases
        #with each level up.
        waittime = (1000.00 * (20.00*(2.00**(-1.00 * level))))//1
        if level == 0:
            self.rect.y = self.rect.y
        else:
            pygame.time.wait(waittime)
            self.rect.y = self.rect.y - 40



#---Defining the player
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.image = pygame.image.load("player.png").convert()
        self.image.set_colorkey(BLACK)
        self.rect = self.image.get_rect()
    def update(self):
        pos = pygame.mouse.get_pos()
        self.rect.x = (pos[0] - 50)
        self.rect.y = 650

#---Defining the bullets
class Bullet(pygame.sprite.Sprite):
    def __init__(self):
        super(Bullet, self).__init__()
        self.image = pygame.Surface([4, 15])
        self.image.fill(RED)
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.y -= 12

#function used later to increment the level by one
def Levelup():
    level+=1

#function used later to regenerate the invaders without running through
#the entire while loop
def BlockGenerator():
    for i in range(25):
        block = Block()
        block.rect.x = random.randrange(screen_width)
        block.rect.y = random.randrange(500)
        block_list.add(block)
        all_sprites_list.add(block)

#--Initializing the game
pygame.init()

pygame.mouse.set_visible(1)

#Setting the width and height of the screen [width, height]
screen_width = 700
screen_height = 700
screen = pygame.display.set_mode([screen_width, screen_height])

pygame.display.set_caption("Spaceship")

all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()

for i in range(25):
    block = Block()
    block.rect.x = random.randrange(screen_width)
    block.rect.y = random.randrange(500)
    block_list.add(block)
    all_sprites_list.add(block)

player = Player()
all_sprites_list.add(player)

#Loop until user clicks the close button
done = False

#Score
score = 0

#formatting, to make the entire spaceship visible
player.rect.y = 370

#Manages how fast the screen updates
clock = pygame.time.Clock()

#-----Main Program Loop------
while not done:
    #---Main event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        #---Processing other user actions

        #This handles the "Game Over" instance    
        elif event.type == pygame.MOUSEBUTTONDOWN and level == 0:
            done = True

        #This handles all other instances
        elif event.type == pygame.MOUSEBUTTONDOWN:
            bullet = Bullet()
            bullet.rect.x = player.rect.x + 47
            bullet.rect.y = player.rect.y
            all_sprites_list.add(bullet)
            bullet_list.add(bullet)

    all_sprites_list.update()

    for bullet in bullet_list:
        block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)

        for block in block_hit_list:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)
            score += 1


        if bullet.rect.y < -10:
            bullet_list.remove(bullet)
            all_sprites_list.remove(bullet)


    #---Drawing the screen

    #Screen clear & fill        
    screen.fill(WHITE)

    #drawing the sprites
    all_sprites_list.draw(screen)

    #Outputting the score and level onto the game
    font = pygame.font.SysFont('Calibri', 20, True, False)
    text = font.render("Score: %s" % (score), True, BLUE)
    screen.blit(text, [312, 30])
    text3 = font.render("Level %s" % (level), True, BLUE)
    screen.blit(text3, [450, 30])

    #Once the player kills all 25 invaders, this is executed
    if score == 25:
        font1 = pygame.font.SysFont('Calibri', 40, True, False)
        text2 = font1.render("You Win!", True, GREEN)
        screen.blit(text2, [285, 150])

        #The "You Win!" message shows for roughly 5 seconds,
        #then the player advances to the next level.
        pygame.time.wait(5000)
        Levelup()

    #"Game Over" instance
    #Once a block advances to the same y coordinate as the player,
    #The game ends
    for block in block_list:
        if block.rect.y > 600:
            level = 0
            font2 = pygame.font.SysFont('Calibri', 40, True, False)
            text4 = font.render["You Lose!", 40, True, RED]
            screen.blit(text4, [285, 150])
            #After this, the game loop runs through again, but this time
            #Level is set to 0, making the invaders stationary
            #The "You Lose" message should show
            #Once the player clicks, the game terminates


    pygame.display.flip()

    clock.tick(40)

pygame.quit()

1 个答案:

答案 0 :(得分:1)

你正在接近这个错误,调用pygame.time.wait(同样适用于time.sleep)停止一切,你甚至无法更新显示,一切都停止,而其他进程使用CPU,然后从它停止的地方继续。

如果你坚持使用pygame.time.wait,那么从一个等待一定时间的线程调用它,然后立即更新所有内容,允许主线程进行业务处理事件,什么不是,这个方法还允许您在短时间内调用pygame.time.wait CPU发送到其他线程,以便他们有机会进行处理。

注意: python有一个 全局解释器锁 ,这使得同一进程中的任何两个python代码无法在同一时间。因此,在使用线程时,您必须确保经常产生 全局解释器锁 ,以便其他线程有机会运行。只需拨打time.sleeppygame.time.wait即可完成此操作。

另一个选择是设置一个时钟,并且自从某个精灵向下移动5秒后,向下移动它并在精灵的本地字段中记录当前时间。这样,你就不必处理凌乱的线程/让步动态。