python - 制作一个简单的《太空侵略者》克隆——pygame.time.delay 导致崩溃

标签 python python-2.7 time syntax

我刚刚开始使用 Python 开发一个非常简单的太空入侵者版本,并编写了玩家 spaceship Sprite 、敌人 Sprite 和子弹 Sprite 的代码。

我让飞船随着鼠标光标水平移动,每次点击鼠标都会发射一颗子弹。子弹与敌人相撞,消除两个 Sprite 并增加 1 分。

当所有敌人都死掉后,它会打印“你赢了!”在顶部。一切都工作正常。

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

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

如果我只能选择我认为有问题的部分,我只会包含这些部分,但我不知道问题出在哪里。我使用了宇宙飞船和入侵者 Sprite 的图形,这就是“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()

最佳答案

您的处理方式不正确,请调用 pygame.time.wait (这同样适用于 time.sleep)停止一切,您甚至无法更新显示,一切都停止,而其他进程开始使用 CPU,然后从停止的地方继续。

如果您坚持使用pygame.time.wait,则从等待一定时间的线程中调用它,然后立即更新所有内容,从而允许主线程进行业务处理事件等等,此方法还允许您在短时间内调用 pygame.time.wait 来将 CPU 交给其他线程,以便它们有机会进行处理。

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

另一种替代方法是设置一个时钟,每当某个 Sprite 向下移动 5 秒后,将其向下移动并在 Sprite 本地字段中记录当前时间。这样,您就不必处理困惑的线程/屈服动态。

关于python - 制作一个简单的《太空侵略者》克隆——pygame.time.delay 导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30110322/

相关文章:

java - 将当前时间(以毫秒为单位)与共享首选项中保存的时间进行比较

java - 使用 Python 将 json 作为字节数组发送到 kafka

python - 没有名为 admin.sites.urls 的模块

python - 更改 Python 语音识别中的语言

c++ - 递归函数的运行时间T(n)

php - 倒数计时器无法正常工作

python - 如何接收子小部件的悬停事件?

Python:使用另一个列表中的索引汇总列表中的数据

python - 当字符串列表交换为文本文件时程序停止工作

python - 使用 lxml 和 xpath 从网页获取文本