
Це фрагмент книги Python з нуля, яка допоможе вам навчитися програмуванню з нуля. Ви можете знайти його на Allegro, Empik та в інтернет-книгарнях.
У цьому розділі ми використаємо реалізовану нами логіку, щоб нарешті можна було зіграти в нашу гру.
game.py. Нам не обійтися без імпорту Position, Direction i GameState.from position import Position from direction import Direction from game_state import GameState
GameState і встановити його початкові значення. Для встановлення цих значень у нас уже є функція set_initial_position. Тож ми можемо заповнити snake, direction і food будь-якими значеннями, після чого викликати set_initial_position, щоб перетворити їх на правильні початкові значення.state = GameState( snake=None, direction=None, food=None, field_size=CUBES_NUM ) state.set_initial_position()
draw.while True: for event in pygame.event.get(): if event.type == pygame.QUIT: quit() state.step() draw(state.snake, state.food)
pygame.time.Clock(). Коли ми викличемо функцію tick у нашому циклі, вона сповільнить тіло "змійки" так, щоб воно викликалося певну кількість разів на секунду. Тож, якщо ми викличемо tick(10) в циклі, "змійка" робитиме 10 кроків за секунду. Для початку це хороша швидкість гри. Для того, щоб спростити або ускладнити гру, можна збільшити або зменшити це значення.clock = pygame.time.Clock() while True: clock.tick(10) for event in pygame.event.get(): if event.type == pygame.QUIT: quit() state.step() draw(state.snake, state.food)
pygame.event.get(), щоб отримати всі події, які відбулися з часу останнього запиту. Вона повертає об’єкт, після якого ми можемо рухатися циклом for. Тому зазвичай, щоб впоратися з усіма подіями, які виникають у ході гри, використовується for event in pygame.event.get(). Зрештою, гравець може, наприклад, майже одночасно натиснути стрілку і закрити гру. Оскільки ми не хочемо пропустити жодну подію, ми обробляємо їх послідовно.type. Якщо він дорівнює pygame.QUIT [^303_2], це означає, що гру було закрито. Подія, яка вказує на натискання кнопки, має тип pygame.KEYDOWN.key, а коди стрілок ліворуч, праворуч, вгору та вниз - це, відповідно, pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP і pygame.K_DOWN [^303_3]. Тож ми використаємо наступний if-elif, щоб визначити, як нам реагувати на кожну зі стрілок, які нас цікавлять.while True: clock.tick(10) for event in pygame.event.get(): if event.type == pygame.QUIT: quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: state.direction = Direction.LEFT elif event.key == pygame.K_RIGHT: state.direction = Direction.RIGHT elif event.key == pygame.K_UP: state.direction = Direction.UP elif event.key == pygame.K_DOWN: state.direction = Direction.DOWN state.step() draw(state.snake, state.food)
turn, яка змінюватиме напрям руху "змійки", але тільки якщо новий напрямок буде дозволено. Почнемо з тесту, який перевірить, чи працює наша функція. Ми поставимо "змійку" в таке ж положення, як перед смертю під час тесту test_snake_dies. Справа в тому, що наша функція перевіряла лише, щоб "змійка" не наступала на своє власне тіло, але дозволяла їй наступати собі на "хвіст". У цій конфігурації "змійка" може повертати вгору (що означало би її смерть), ліворуч і вниз. Однак вона не може повернути праворуч, тому що вона звідти йде.# Новий метод у GameStateTest def test_turn(self): state = GameState( snake=[ Position(1, 2), Position(2, 2), Position(3, 2), Position(3, 3), Position(2, 3) ], direction=Direction.UP, food=Position(3, 1), field_size=25 ) state.turn(Direction.LEFT) self.assertEqual(Direction.LEFT, state.direction) state.turn(Direction.UP) self.assertEqual(Direction.UP, state.direction) state.turn(Direction.DOWN) self.assertEqual(Direction.DOWN, state.direction) state.turn(Direction.RIGHT) # Лишається старе значення, # тому що не можна повертати праворуч self.assertEqual(Direction.DOWN, state.direction)
# Новий метод у класі GameState def turn(self, direction): if self.can_turn(direction): self.direction = direction
can_turn, на якому ми зараз зосередимося. Але почнемо знову з тесту.# Новий метод у класі GameStateTest def test_can_turn(self): state = GameState( snake=[ Position(1, 2), Position(2, 2), Position(3, 2), Position(3, 3), Position(2, 3) ], direction=Direction.UP, food=Position(3, 1), field_size=25 ) self.assertEqual( True, state.can_turn(Direction.LEFT) ) self.assertEqual( True, state.can_turn(Direction.UP) ) self.assertEqual( True, state.can_turn(Direction.DOWN) ) self.assertEqual( False, state.can_turn(Direction.RIGHT) )
snake[-2], нове положення "голови" можна визначити за допомогою next_head, а для порівняння можна використати знак !=.# Новий метод у класі GameState def can_turn(self, direction): new_head = self.next_head(direction) return new_head != self.snake[-2]
direction викликало метод turn. Ось весь наш цикл гри із визначенням стану:state = GameState( snake=None, direction=None, food=None, field_size=CUBES_NUM, ) state.set_initial_position() clock = pygame.time.Clock() while True: clock.tick(10) for event in pygame.event.get(): if event.type == pygame.QUIT: quit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: state.turn(Direction.LEFT) elif event.key == pygame.K_RIGHT: state.turn(Direction.RIGHT) elif event.key == pygame.K_UP: state.turn(Direction.UP) elif event.key == pygame.K_DOWN: state.turn(Direction.DOWN) state.step() draw(state.snake, state.food)
- додати лічильник очок;
- зробити так, щоб зіткнення з кінцем поля вбивало "змійку";
- додати на полі кілька перешкод;
- намалювати "змійці" очі та покращити вигляд "хвоста", поля та "їжі";
- сповільнити "змійку", але додати прискорення з часом;
- додати можливість зупинити гру (наприклад, пробілом);
- додати екран із демонстрацією результату після смерті "змійки";
- додати перелік найкращих результатів (що потребує зберігання результатів на диску).

Замість посилання можна скористатися цим QR-кодом.
[^303_2]: Щоб дізнатися більше про типи подій, переглянь документацію пакета, а також форуми, StackOverflow та інші сайти для обговорень.
[^303_3]: Якщо ти хочеш додати реакції на інші клавіші, усі вони починаються з
K_. Для літер і цифр після цього записується відповідна літера або цифра, напр. K_2, K_a.