Почему происходит сбой Pygame при попытке перезапустить игру? - PullRequest
3 голосов
/ 22 февраля 2020

Я пытаюсь построить базовую c игру на вертолете, цель которой состоит в том, чтобы избежать удара по блокам.

Когда я попадаю в блок, я хочу, чтобы игра зависла, а затем начнется нажатие клавиши пробела. игра fre sh.

Вот мой код:

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.hit() вызвано -> helicopter.alive выполнено False -> Игра проверяет наличие кнопки пробела нажать в какой момент он helicopter.alive становится True координаты x, y вертолета сбрасываются, и игра начинается заново (мне еще предстоит реализовать подсчет очков, но подсчет очков будет сброшен).

Что на самом деле происходит происходит сбой игры при попадании в блок.

Кто-нибудь может объяснить, как я могу это исправить?

Спасибо.

1 Ответ

4 голосов
/ 22 февраля 2020

У вас есть приложение l oop, поэтому, пожалуйста, используйте его. Никогда не используйте вложенные игровые циклы. Ваша игра зависает, потому что внутренний l oop не обрабатывает события.
Основное приложение l oop должно:

  • обрабатывать события, либо pygame.event.pump() или pygame.event.get().
  • изменение состояний игры в зависимости от входных событий и времени
  • очистка дисплея
  • перерисовка сцена
  • обновление дисплея

Классу Helicopter необходимо 2 функции. hit устанавливает self.alive = False и reset, устанавливает начальные игровые состояния:

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")

Игра l oop имеет 2 разных случая, в зависимости от состояния helicopter.alive. Это helicopter.alive, это True, пока игра не запускается. Если это 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...