Введение
Я создаю знаменитую игру Flappy bird, используя python и его библиотеку под названием «pygame». Она очень проста в создании и очень увлекательна в игре. Она требует всего 200 строк кода. Существует веб-версия этой игры, которую вы можете найти на сайте flappybird.io.
О Flappy
Flappy Bird — мобильная игра, разработанная вьетнамским художником и программистом Донг Нгуеном (вьетнамский: Nguyễn Hà Đông) под руководством его компании по разработке игр Gears. Игра представляет собой сайд-скроллер, в котором игрок управляет птицей, пытающейся пролететь между колоннами зеленых труб, не задев их. Нгуен создавал игру в течение нескольких дней, используя птицу-протагониста, которую он разработал для отмененной игры в 2012 году.
Pygame
pygame — это обертка Python для библиотеки SDL, которая расшифровывается как Simple DirectMedia Layer. SDL обеспечивает кроссплатформенный доступ к базовым мультимедийным аппаратным компонентам вашей системы, таким как звук, видео, мышь, клавиатура и джойстик. pygame начал свою жизнь как замена заглохшему проекту PySDL. Кроссплатформенность SDL и pygame означает, что вы можете писать игры и насыщенные мультимедийные Python-программы для любой платформы, которая их поддерживает!
Установите pygame с помощью pip, если у вас уже установлен python.
pip install pygame
Импортируйте его в вашу программу на python и инициализируйте.
import pygame
pygame.init()
Проект
Создайте папку проекта с именем flappy
и создайте в ней python файл с именем flappy.py
.
Активы
Для создания этой игры нам понадобятся некоторые спрайты. Три спрайта птиц с анимированными крыльями, зеленые трубы, земля, фон и кнопка перезапуска. Вы можете найти активы здесь
Скачайте активы и сохраните их в папке с именем img
.
Структура файла будет выглядеть следующим образом.
flappy
|
| -- img
|
-- bg.png
-- bird1.png
-- bird2.png
-- bird3.png
-- ground.png
-- pipe.png
-- restart.png
|
| -- flappy.py
Базовая настройка
начните работу над кодом, импортировав необходимые модули.
import pygame
from pygame.locals import *
import random
Модуль pygame.locals
содержит различные константы, используемые pygame. Мы используем random для генерации случайных труб в сайдскроллере.
Инициализация pygame
pygame.init()
Определите высоту и ширину экрана, чтобы мы могли создать окно.
screen_width = 460
screen_height = 500
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Flappy Bird')
И, наконец, нам нужен игровой цикл, который будет выполняться до тех пор, пока игрок не выйдет из игры.
run = True
while run:
pass
Не забудьте выйти из pygame в конце кода
pygame.quit()
Теперь запустите программу python из терминала.
python3 flappy.py
Это откроет новое пустое окно с высотой и шириной, которые мы определили ранее. Но теперь мы не сможем закрыть окно, кроме как прервав терминал. Это происходит потому, что мы не указали циклу прерваться, когда пользователь закроет окно, и это вызовет pygame.quit()
в конце кода.
Мы должны перебрать все события pygame и проверить, является ли это событием закрытия. Затем придать run
значение false
, что прервет цикл.
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Теперь мы сможем закрыть окно после запуска программы.
Фон
Сначала нарисуем фон. Для этого импортируйте спрайт bg
из папки img
и отмасштабируйте его в соответствии с размером экрана.
bg = pygame.image.load('img/bg.png')
bg = pygame.transform.scale(bg, (460, 420))
И внутри цикла перерисуйте bg с помощью функции blit
.
# draw background
screen.blit(bg, (0,0))
также добавьте функцию обновления в конце цикла
pygame.display.update()
Запустите программу, и вы увидите фон.
Земля
Импортируйте изображение земли так же, как мы импортировали фон.
ground_img = pygame.image.load('img/ground.png')
ground_img = pygame.transform.scale(ground_img, (480, 80))
Также объявите некоторые переменные, чтобы сделать землю прокручиваемой.
# game variables
ground_scroll = 0
scroll_speed = 2
Внутри цикла, сразу после рисования земли, нарисуйте землю с ground_scroll
в качестве значения x
. Также обновите ground_scroll
с помощью scroll_speed
.
# draw ground
screen.blit(ground_img, (ground_scroll, 420))
ground_scroll -= scroll_speed
Также нам нужно сбросить значение ground_scroll
на 0 после того, как оно пройдет 20
, чтобы получить непрерывную прокрутку.
if abs(ground_scroll) > 20:
ground_scroll = 0
FPS
Теперь земля прокручивается очень быстро, и мы должны контролировать fps. Иначе fps может отличаться на разных компьютерах. Поэтому в верхней части объявите fps
и pygame clock
.
# fps control
clock = pygame.time.Clock()
fps = 60
Внутри цикла, в верхней части вызовите функцию tick
, используя переменную fps
.
clock.tick(fps)
Попробуйте игру и увидите, что земля прокручивается медленно.
Класс птицы
Теперь давайте создадим класс птицы. В классе птицы у нас есть конструктор, в котором мы получаем значения x, y и метод обновления.
class Bird(pygame.sprite.Sprite):
def __init__(self, x, y):
pass
def update(self):
pass
Видите, мы вывели класс из pygame.sprite.Sprite
. Это простой базовый класс для видимых игровых объектов.
Давайте напишем метод __init__
.
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.images = []
self.index = 0
self.counter = 0
for num in range(1, 4):
img = pygame.image.load(f'img/bird{num}.png')
img = pygame.transform.scale(img, (35, 25))
self.images.append(img)
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.rect.center = [x, y]
self.vel = 0
self.clicked = False
Здесь мы сначала вызвали конструктор pygame.sprite.Sprite
. У нас есть 3 спрайта с изображениями птиц, которые нужно анимировать. Поэтому мы выполняем цикл 3 раза и сохраняем каждое изображение в images[]
. Переменная index
используется для получения n-го изображения в каждом кадре. counter
используется для контроля частоты кадров анимации. Также мы центрируем изображение по x, y
, используя rect
спрайта. vel
задает скорость птицы, когда clicked = true
.
Теперь нам нужно написать метод update
.
def update(self):
# gravity
if flying == True:
self.vel += 0.2
if self.vel > 30:
self.vel = 0
if self.rect.bottom < 420:
self.rect.y += int(self.vel)
Сначала мы закодировали функцию гравитации для птицы. Убедитесь, что мы объявили переменную flying
в верхней части кода.
flying = False
Мы добавим скорость на 0.2, пока птица летит, и зажмем значение до 30, потому что птице не нужно опускаться ниже земли. Переменная vel
будет добавлена к rect.y
, что приведет к перемещению птицы вниз, как будто она падает.
Затем объявите переменную game_over
вверху и добавьте этот код в метод update
.
if game_over == False:
# jump
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
self.vel = -5
if pygame.mouse.get_pressed()[0] == 0:
self.clicked = False
Проверьте, не закончилась ли игра и не должна ли птица прыгнуть при нажатии кнопки мыши. Нам не нужны постоянные нажатия, поэтому мы должны проверить, что self.clicked
равно false
. Пришло время прыгать, мы устанавливаем clicked
в true
и vel
в -5
, что ведет птицу вверх. Мы установим clicked
в false
, когда мышь будет отпущена.
Теперь нам нужно анимировать птицу.
# handle animation
self.counter += 1
flap_cooldown = 5
if self.counter > flap_cooldown:
self.counter = 0
self.index += 1
if self.index >= len(self.images):
self.index = 0
self.image = self.images[self.index]
Мы установим переменную flap_cooldown
равной 5 и проверим, идет ли counter
за ней. Затем изменим переменную index
и обновим изображение спрайта в соответствии с index
. Убедитесь, что index
не больше длины изображений. Если это так, установите значение 0.
Наконец, мы повернем птицу в соответствии со скоростью.
# rotate the bird
self.image = pygame.transform.rotate(self.images[self.index], self.vel * -2)
Убедитесь, что все вышеперечисленные коды отступают внутрь условия game_over == False
. А когда game_over == true
, мы должны направить птицу вниз, как будто она быстро падает. Итак, сразу после вышеупомянутого условия введите следующий код.
else:
self.image = pygame.transform.rotate(self.images[self.index], -90)
Теперь наш класс птицы завершен. Давайте нарисуем птицу внутри цикла. Но перед этим нам нужно создать группу класса птицы прямо над циклом.
bird_group = pygame.sprite.Group()
И добавьте в группу новый объект Bird
.
flappy = Bird(100, int(screen_height/2))
bird_group.add(flappy)
Мы делаем это потому, что класс sprite.Group
класса pygame
легко рисовать, так как он сам имеет метод по умолчанию draw
.
Перейдите в цикл и вызовите метод draw
и update
группы птиц.
# draw bird
bird_group.draw(screen)
bird_group.update()
Убедитесь, что мы поместили этот код после отрисовки bg
и ground
, потому что нам нужна птица в верхней их части.
Также добавьте этот код в цикл for event in pygame.event.get()
, чтобы flying = true
.
if event.type == pygame.MOUSEBUTTONDOWN and flying == False and game_over == False:
flying = True
Это заставит птицу взлететь, когда мы впервые нажмем на кнопку мыши. Но не запустит игру при ее открытии.
Еще одно обновление. Мы должны закрыть обновление ground_scroll
, которое мы написали ранее, внутри условия, потому что нам не нужно прокручивать землю, если игра еще не запущена.
if game_over == False and flying == True:
# scroll ground
ground_scroll -= scroll_speed
if abs(ground_scroll) > 20:
ground_scroll = 0
Теперь все начнет двигаться после первого нажатия на кнопку мыши. Попробуйте поиграть сейчас.
Заключение
Надеюсь, вам понравился этот пост и вы получили удовольствие от совместного создания flappy. Я вернусь к вам в ближайшее время с другим постом, в котором мы добавим больше функциональных возможностей в игру. Комментируйте свои мнения и сомнения.
Вторая часть: Часть-1