【问题标题】:Why is pygame crashing when trying to restart game? [duplicate]为什么尝试重新启动游戏时pygame会崩溃? [复制]
【发布时间】:2020-02-22 11:42:27
【问题描述】:

我正在尝试构建一个基本的直升机游戏,其目的是避免撞到障碍物。

当我击中一个方块时,我希望游戏冻结,然后按空格键将开始新游戏。

这是我的代码:

main.py

import pygame
from helicopter import Helicopter
from block import Block
import random

pygame.init()

win = pygame.display.set_mode((700,400))
w, h = pygame.display.get_surface().get_size()
clock = pygame.time.Clock()
blocks = []

score = 0


helicopter = Helicopter(100, 200)

def drawGameWindow():
    helicopter.draw(win)
    for block in blocks:
        if block.visible:
            block.draw(win)
        else:
            blocks.pop(blocks.index(block))
    pygame.display.update()



def main():
    run = True
    blockLimiter = 0
    while run:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False


        if blockLimiter > 0:
            blockLimiter +=1
        if blockLimiter > 100:
            blockLimiter = 0

        if blockLimiter == 0:
            blocks.append(Block(random.randint(50, 350)))
            blockLimiter += 1

        for block in blocks:
            if helicopter.hitbox[1] < block.hitbox[1] + block.hitbox[3] and helicopter.hitbox[1] + helicopter.hitbox[3] > block.hitbox[1]:
                if helicopter.hitbox[0] + helicopter.hitbox[2] > block.hitbox[0] and helicopter.hitbox[0] < block.hitbox[0] + block.hitbox[2]:
                    helicopter.hit()


        keys = pygame.key.get_pressed()

        if keys[pygame.K_SPACE]:
            helicopter.y -= abs(helicopter.speed)
        else:
            helicopter.y += helicopter.speed

        drawGameWindow()

    pygame.quit()

main()

block.py

import pygame


class Block(object):
    def __init__(self, y):
        self.x = 700
        self.y = y
        self.height = 70
        self.width = 40
        self.visible = True
        self.hitbox = (self.x -3, self.y -3, self.width + 6, self.height + 6)

    def draw(self, win):
        if self.x + self.width < 0:
            self.visible = False
        self.x -= 5
        self.hitbox = (self.x -3, self.y -3, self.width + 6, self.height + 6)
        pygame.draw.rect(win, (0, 255, 0), (self.x, self.y, self.width, self.height))
        pygame.draw.rect(win, (255,0,0), self.hitbox, 2)

直升机.py

import pygame

class Helicopter(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 70
        self.height = 30
        self.speed = 1 * (self.y - 100)*0.05
        self.hitbox = (self.x - 3, self.y - 3, self.width + 6, self.height + 6)
        self.alive = True

    def draw(self, win):
        win.fill((0,0,0))
        self.hitbox = (self.x - 3, self.y - 3, self.width + 6, self.height + 6)
        pygame.draw.rect(win, (0, 255, 0), (self.x, self.y, 70, 30))
        pygame.draw.rect(win, (255, 0, 0), self.hitbox, 2)

    def hit(self):
        self.alive = False
        while not self.alive:
            keys = pygame.key.get_pressed()
            if keys[pygame.K_SPACE]:
                self.alive = True
                self.x = 100
                self.y = 200

我想要发生的事情:

helicopter hits block -> helicopter.hit() is called -> helicopter.alive is made False -> 游戏正在检查要按下的空格按钮,此时它的直升机.alive 变为 True 的 x,y 坐标直升机重置,游戏重新开始(我还没有执行计分,但计分会重置)。

实际发生的情况是当我撞到障碍物时游戏崩溃。

谁能解释我如何解决这个问题?

谢谢。

【问题讨论】:

    标签: python python-3.x pygame


    【解决方案1】:

    你有一个应用程序循环,所以请使用它。永远不要实现嵌套的游戏循环。您的游戏冻结,因为内部循环不处理事件。
    主应用程序循环必须:

    Helicopter 类需要 2 个函数。 hit 设置self.alive = Falsereset,设置初始游戏状态:

    class Helicopter(object):
        # [...]
    
        def hit(self):
            self.alive = False
            print("hit")
    
        def reset(self):
            self.alive = True
            self.x = 100
            self.y = 200
            print("reset")
    

    游戏循环有两种不同的情况,取决于helicopter.alive 的状态。 helicopter.aliveTrue,游戏运行。如果是False,则游戏等待SPACE被按下并继续:

    def main():
        run = True
        blockLimiter = 0
        while run:
            clock.tick(60)
    
            # handle events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
    
            # update game states
            keys = pygame.key.get_pressed()
            if helicopter.alive:
    
                if blockLimiter > 0:
                    blockLimiter +=1
                if blockLimiter > 100:
                    blockLimiter = 0
    
                if blockLimiter == 0:
                    blocks.append(Block(random.randint(50, 350)))
                    blockLimiter += 1
    
                for block in blocks:
                    if helicopter.hitbox[1] < block.hitbox[1] + block.hitbox[3] and helicopter.hitbox[1] + helicopter.hitbox[3] > block.hitbox[1]:
                        if helicopter.hitbox[0] + helicopter.hitbox[2] > block.hitbox[0] and helicopter.hitbox[0] < block.hitbox[0] + block.hitbox[2]:
                            helicopter.hit()
    
                if keys[pygame.K_SPACE]:
                    helicopter.y -= abs(helicopter.speed)
                else:
                    helicopter.y += helicopter.speed
            else:
                if keys[pygame.K_SPACE]:
                    helicopter.reset()
    
            # clear display, draw scene and update diesplay
            drawGameWindow()
    
        pygame.quit()
    

    我还建议对块的副本进行迭代 (blocks[:])。然后你可以从原始列表中删除一个块而不影响迭代(blocks.remove(block)

    def drawGameWindow():
        helicopter.draw(win)
        for block in blocks[:]:
            if block.visible:
                block.draw(win)
            else:
                blocks.remove(block)
        pygame.display.update()
    

    【讨论】:

    • 感谢您的回答。最后一个后续问题:你知道为什么当我在drawGameWindow()的块列表上调用pop时,屏幕上的所有块都会轻微闪烁吗?我很快就会接受这个答案。
    • @thd123 我已经扩展了答案。请参阅我现在添加的最后一部分。
    • 谢谢 看看添加的位。我现在已经重置了,所以再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多