Игра на Python: как устранить буквы, нажимая соответствующие клавиши?

#pygame

#pygame

Вопрос:

  1. Введение: Разные буквы выпадают из верхней части экрана через определенный промежуток времени, и буква исчезнет, когда вы нажмете соответствующую клавишу на клавиатуре. Позиция x каждой буквы случайна, и скорость падения будет ускоряться по мере прохождения игры. Игра закончится при определенном условии (например, более 10 букв упадут на дно).

  2. Прогресс: я реализовал некоторые функции, такие как генерация случайных падающих букв.

  3. Проблема: я в недоумении, как устранить каждую падающую букву, нажав соответствующую клавишу?

Ниже приведены мои коды:

  1. alphabet_zoo.py
 import pygame
import time
from pygame.locals import *
from settings import Settings
import game_functions as gf

def run_game():
    pygame.init()
    az_settings =Settings()
    screen = pygame.display.set_mode((0,0), RESIZABLE)
    pygame.display.set_caption("Alphabet Zoo")
    letters = pygame.sprite.Group()
    start = time.time()
    sleepTime = 3


    while True:
        now = time.time()
        gf.check_events(letters)
        letters.update()
        gf.update_screen(az_settings, screen, letters)
        if now - start >sleepTime:
            gf.letter_generator(az_settings ,screen, letters)
            start = now


run_game()

  
  1. settings.py
 class Settings():
    def __init__(self):
        self.bg_color = (0, 0, 0)
        self.letter_speed_factor = 10
  
  1. game_functions.py
 import sys
import pygame
from letter import Letter

def letter_generator(az_settings, screen, letters):
    new_letter = Letter(az_settings, screen)
    letters.add(new_letter)

def check_events(letters):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                # Here is my question:
                # How could I eliminate each falling letter by striking the corresponding key?
                letters.empty()

def update_screen(az_settings, screen, letters):
    screen.fill(az_settings.bg_color)
    letters.draw(screen)
    letters.update()
    pygame.display.flip()
  
  1. letter.py
 import pygame
import random
from pygame.sprite import Sprite


class Letter(Sprite):

    def __init__(self, az_settings, screen):
        super().__init__()
        self.screen = screen
        self.az_settings = az_settings
        a = random.randint(97, 123)
        c = chr(a)
        if c == 'a':
            self.image = pygame.image.load('images/A.png')
        elif c == 'b':
            self.image = pygame.image.load('images/B.png')
        elif c == 'c':
            self.image = pygame.image.load('images/C.png')
        elif c == 'd':
            self.image = pygame.image.load('images/D.png')
        elif c == 'e':
            self.image = pygame.image.load('images/E.png')
        elif c == 'f':
            self.image = pygame.image.load('images/F.png')
        elif c == 'g':
            self.image = pygame.image.load('images/G.png')
        elif c == 'h':
            self.image = pygame.image.load('images/H.png')
        elif c == 'i':
            self.image = pygame.image.load('images/I.png')
        elif c == 'j':
            self.image = pygame.image.load('images/J.png')
        elif c == 'k':
            self.image = pygame.image.load('images/K.png')
        elif c == 'l':
            self.image = pygame.image.load('images/L.png')
        elif c == 'm':
            self.image = pygame.image.load('images/M.png')
        elif c == 'n':
            self.image = pygame.image.load('images/N.png')
        elif c == 'o':
            self.image = pygame.image.load('images/O.png')
        elif c == 'p':
            self.image = pygame.image.load('images/P.png')
        elif c == 'q':
            self.image = pygame.image.load('images/Q.png')
        elif c == 'r':
            self.image = pygame.image.load('images/R.png')
        elif c == 's':
            self.image = pygame.image.load('images/S.png')
        elif c == 't':
            self.image = pygame.image.load('images/T.png')
        elif c == 'u':
            self.image = pygame.image.load('images/U.png')
        elif c == 'v':
            self.image = pygame.image.load('images/V.png')
        elif c == 'w':
            self.image = pygame.image.load('images/W.png')
        elif c == 'x':
            self.image = pygame.image.load('images/X.png')
        elif c == 'y':
            self.image = pygame.image.load('images/Y.png')
        else:
            self.image = pygame.image.load('images/Z.png')

        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()

        self.rect.centerx = random.randint(0, self.screen_rect.right)
        self.rect.top = self.screen_rect.top
        self.center = float(self.rect.centerx)


    def update(self):
        if self.rect.bottom < self.screen_rect.bottom:
            self.rect.centery  = self.az_settings.letter_speed_factor

  

скриншот

Ответ №1:

Событие keydown возвращает значение ascii ключа. вы можете удалить падающую клавишу с помощью пары изменений.

  • В классе letter сделайте значение ascii общедоступным
  • В игровом цикле обновляйте список букв при каждом нажатии клавиши

Вот обновленный код

letter.py

 class Letter(Sprite):

    def __init__(self, az_settings, screen):
        super().__init__()
        self.screen = screen
        self.az_settings = az_settings
        a = random.randint(97, 123) #lowercase a-z
        c = chr(a)
        self.image = pygame.image.load('images/' c.upper() '.png')   # letter image file
        self.ascii = a  # make ascii value public

        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()

        self.rect.centerx = random.randint(0, self.screen_rect.right)
        self.rect.top = self.screen_rect.top
        self.center = float(self.rect.centerx)


    def update(self):
        if self.rect.bottom < self.screen_rect.bottom:
            self.rect.centery  = self.az_settings.letter_speed_factor
  

game_functions.py

 import sys
import pygame
from letter import Letter

def letter_generator(az_settings, screen, letters):
    new_letter = Letter(az_settings, screen)
    letters.add(new_letter)

def check_events(letters):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            letters = [ltr for ltr in letters if ltr.ascii != event.key]  # remove key ascii from letter list

def update_screen(az_settings, screen, letters):
    screen.fill(az_settings.bg_color)
    letters.draw(screen)
    letters.update()
    pygame.display.flip()
  

Комментарии:

1. Добавленный код `letters = [ltr для ltr в буквах, если ltr.ascii != event.key]` в game_functions.py не работает. Я изменил его на «для ltr буквами: если ltr.ascii == event.key: letters.remove (ltr)`. Теперь он работает отлично.

2. Еще одна вещь, на которую я должен обратить внимание, это то, что иногда pygame.image.load() работает хорошо, в то время как иногда система подсказывает ‘pygame.error: не удалось открыть images/{.png’. Я не знаю, как получается ‘{‘.

3. Я наконец нашел ошибку. a = random.randint(97, 123) должно быть изменено на ` a = random.randint(97, 122)`