Структура небольшой игры: класс Game
Три фазы игрового цикла становятся тремя методами одного класса — тем же каркасом, что и у финального проекта этой главы и у следующей.
До сих пор весь код жил в глобальных переменных и одном плоском цикле — нормально для учебного мини-проекта, но неудобно, как только игра обрастает состояниями (раздел 20.25), несколькими объектами и хоть какой-то паузой. Соберём всё, что вы узнали в этой главе, в один класс — тот самый архитектурный каркас, на котором построен финальный проект раздела 20.33 и космический шутер главы 21.
Это набросок каркаса, а не полный файл: он опускает импорт pygame
, определение SHIRINA/VYSOTA,
класс SostoyanieIgry из раздела 20.25 и тело метода
toggle_pause() — всё это в реальном проекте, конечно, должно быть
определено. Полный, действительно запускаемый пример такого класса — финальный проект
раздела 20.33.
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((SHIRINA, VYSOTA))
self.clock = pygame.time.Clock()
self.state = SostoyanieIgry.MENU
self.running = True
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_p:
self.toggle_pause()
def update(self, dt):
if self.state is not SostoyanieIgry.IGRA:
return # на паузе или в меню ничего не двигаем
# здесь — обновление позиций, столкновений, счёта
def render(self):
self.screen.fill((20, 20, 40))
# здесь — отрисовка всех объектов текущего состояния
pygame.display.flip()
def run(self):
while self.running:
dt = self.clock.tick(60) / 1000
self.handle_events()
self.update(dt)
self.render()
pygame.quit()
run() — единственное место, где виден весь цикл целиком, и
он дословно повторяет три фазы из раздела 20.14: handle_events()
это Input, update(dt) это Update, render()
это Render. Именно так организован финальный bouncing_ball.py
(раздел 20.33) — и в этом же стиле в главе 21 написан космический шутер.
self.state is not SostoyanieIgry.IGRA поставить только в render(), а не в update(), экран во время паузы визуально замрёт правильно — но объекты продолжат двигаться в памяти, и после снятия паузы игра "телепортируется" туда, куда они успели дойти незаметно для игрока. Проверка состояния должна стоять именно в update(), а не только в отрисовке.