Создание flappy bird с помощью pygame. Часть — 1


Введение

В предыдущем посте мы сделали небольшую часть нашей игры flappy. Мы могли летать на нашей птичке и рисовать землю, bg и т.д. Теперь мы продолжаем разработку, создавая трубы в качестве препятствий, и нам нужно создать событие завершения игры и все остальное, чтобы закончить игру. Итак, давайте начнем.
Прочитайте первую часть, если вы еще не читали: Часть-0

Трубы

Давайте создадим трубу, которая будет генерироваться случайным образом из конца экрана и прокручиваться в сторону птицы. Нам нужно управлять птицей, чтобы она не врезалась в трубы. Поэтому сначала создадим класс Pipe.

# pipe class
class Pipe(pygame.sprite.Sprite):
    def __init__(self, x, y, position):
        pass

    def update(self):
        pass
Вход в полноэкранный режим Выход из полноэкранного режима

Как мы создали класс птицы, класс трубы имеет метод __init__, который является конструктором, и метод update. Мы получаем x, y и position, чтобы определить, находится ли труба на возвышении или на земле. Нам нужно объявить переменную pipe_gap в верхней части кода и установить ее в значение 100.

pipe_gap = 100
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь давайте завершим метод __init__.

def __init__(self, x, y, position):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('img/pipe.png')
        self.image = pygame.transform.scale(self.image, (35, 250))
        self.rect = self.image.get_rect()
        # position 1 is from the top and -1 is from bottom
        if position == 1:
            self.image = pygame.transform.flip(self.image, False, True)
            self.rect.bottomleft = [x, y - int(pipe_gap / 2)]
        elif position == -1:
            self.rect.topleft = [x, y + int(pipe_gap / 2)]
Вход в полноэкранный режим Выход из полноэкранного режима

Сначала мы загружаем изображение трубы, а затем позиционируем ее в соответствии с аргументом position. Если position = 1, труба должна быть перевернута, как будто она выходит из неба. А если -1, то труба должна быть расположена на земле. Убедитесь, что мы учитываем pipe_gap, когда задаем y положение труб.
Теперь перейдем к методу обновления.

def update(self):
        self.rect.x -= scroll_speed
        if self.rect.right < 0:
            self.kill()
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы вычли scroll_speed из положения x прямоугольника изображения, чтобы переместить трубу влево. Если труба выйдет за пределы экрана в левую сторону, мы ее уничтожим. Таким образом, мы можем сэкономить немного места. Теперь класс трубы завершен.

Нам нужно создать pipe_group, как мы создали bird_group.

pipe_group = pygame.sprite.Group()
Вход в полноэкранный режим Выйдите из полноэкранного режима

Перейдите в цикл и нарисуйте pipe_group на экране. убедитесь, что она находится прямо над кодом для рисования земли.

    # draw pipes
    pipe_group.draw(screen)
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы рисуем pipe_group на экране, но в pipe_group нет трубы. Она пуста. Нам нужно добавить ее. Для этого объявите переменную в верхней части кода с именем pipe_frequency. Установите ее на 1500. Также объявите переменную last_pipe.

pipe_frequency = 1500
last_pipe = pygame.time.get_ticks() - pipe_frequency
Войдите в полноэкранный режим Выйти из полноэкранного режима

Мы делаем это для того, чтобы каждый раз генерировать трубу после определенной частоты кадров.

Внутри цикла перейдите к позиции, где мы установили код для обновления ground_scroll, внутри условия, проверяющего game_over == False и flying == True. Прямо внутри условия добавьте следующее.

time_now = pygame.time.get_ticks()
if time_now - last_pipe > pipe_frequency:
    pipe_height = random.randint(-50, 50)
    btm_pipe = Pipe(screen_width, int(screen_height/2) + pipe_height, -1)
    top_pipe = Pipe(screen_width, int(screen_height/2) + pipe_height, 1)
    pipe_group.add(btm_pipe)
    pipe_group.add(top_pipe)
    last_pipe = time_now

pipe_group.update()
Войти в полноэкранный режим Выйти из полноэкранного режима

Мы проверяем, пришло ли время генерировать новую трубу в соответствии с параметром pipe_frequency. Когда мы увеличиваем pipe_frequency, труба будет генерироваться на большем расстоянии.
Мы генерируем случайную высоту для трубы и генерируем нижнюю и верхнюю трубы. Затем добавим их в pipe_group. Установите last_pipe в time_now, чтобы сгенерировать другую трубу в соответствии с этим. В заключение, нам нужно генерировать две трубы (одну сверху, а другую снизу) после каждого pipe_frequency раза кадров. Итак, мы должны проверить, что time_nowlast_pipe's время больше, чем pipe_frequency. Вот и все.
Наконец, мы вызываем функцию обновления pipe_group вне условия.

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

Столкновение и конец игры

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

# look for collision
    if pygame.sprite.groupcollide(bird_group, pipe_group, False, False) or flappy.rect.top < 0:
        game_over = True
Войти в полноэкранный режим Выйти из полноэкранного режима

В Pygame уже есть метод groupcollide для проверки столкновения двух групп спрайтов. Мы проверяем условие и устанавливаем game_over в true.
Нам нужно остановить игру, если птица тоже ударится о землю. Это просто.

# check if bird hit the ground
if flappy.rect.bottom >= 420:
   game_over = True
   flying = False
Войти в полноэкранный режим Выйти из полноэкранного режима

Добавьте этот код в цикл, в котором мы проверяем, что спрайт flappy поднимается выше 420, где находится земля, и установите game_over = true и flying = false.

Запустите игру, и вы увидите, что птица падает вниз, когда мы сталкиваемся с трубами. Это потому, что мы уже закодировали коды падения птицы в ее классе.

Оценка

Далее мы можем создать функцию оценки. Сначала объявите переменную в верхней части. Также булевую переменную с именем pass_pipe.

score = 0
pass_pipe = False
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы должны проверить, прошла ли птица каждый набор труб, и увеличить переменную на единицу. Вот код, который нужно поместить внутрь цикла.

# check the score
    if len(pipe_group) > 0:
        if bird_group.sprites()[0].rect.left > pipe_group.sprites()[0].rect.left
                and bird_group.sprites()[0].rect.left < pipe_group.sprites()[0].rect.right
                and pass_pipe == False:
            pass_pipe = True
        if pass_pipe == True:
            if bird_group.sprites()[0].rect.left > pipe_group.sprites()[0].rect.right:
                score += 1
                pass_pipe = False
Войти в полноэкранный режим Выйти из полноэкранного режима

Мы проверяем координаты pipe_group и bird_group и увеличиваем счет в соответствии с этим.
Попробуйте вывести счет в консоль, вы увидите, что он меняется, когда птица пролетает мимо трубы.

print(score);
Вход в полноэкранный режим Выход из полноэкранного режима

Текст

Нам не нужно, чтобы счет выводился на консоль или терминал. Нам нужно, чтобы он был внутри игры, внутри графики. Здесь нам нужен рендеринг текста. Давайте создадим функцию draw_text в верхней части кода.

def draw_text(text, font, text_col, x, y):
    img = font.render(text, True, text_col)
    screen.blit(img, (x, y))
Вход в полноэкранный режим Выход из полноэкранного режима

Мы получаем текст, шрифт, цвет текста и положение x, y в функцию и рендерим шрифт в изображение. Затем рисуем его на экране.
Теперь нам нужно вызвать эту функцию из цикла.

    # draw score
    draw_text(str(score), font, white, int(screen_width / 2), 20)
Войти в полноэкранный режим Выйти из полноэкранного режима

В качестве текста здесь используется переменная score, преобразованная в sting. Позиция должна быть в центре сверху. Поэтому мы разделили screen_width на 2 и установили y равным 20. Мы вызываем переменные font и white, которые нужно было объявить раньше, вне цикла.

# define font
font = pygame.font.SysFont('Bauhaus 93', 50)

# define colours
white = (255, 255, 255)
Вход в полноэкранный режим Выход из полноэкранного режима

Мы используем шрифт Bauhaus для рендеринга текста. Запустите игру, и вы увидите счет вверху.

Перезапуск

Нам нужно отобразить кнопку перезапуска, если игра закончилась и при нажатии на нее игра должна быть перезапущена. Поэтому объявите класс Button с методом __init__ и update.


class Button():
    def __init__(self, x, y, image):
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)

    def draw(self):
        action = False
        pos = pygame.mouse.get_pos()
        if self.rect.collidepoint(pos):
            if pygame.mouse.get_pressed()[0] == 1:
                action = True

        screen.blit(self.image, (self.rect.x, self.rect.y))

        return action
Вход в полноэкранный режим Выйти из полноэкранного режима

Нужно получить image и x, y в качестве аргументов и установить изображение в соответствии с x, y.
В методе update мы возвращаем, если мышь щелкнула по кнопке. А также рисуем кнопку на экране.
Теперь инициализируем кнопку,

button = Button(screen_width // 2 - 50, screen_height // 2 - 50, button_img)
Вход в полноэкранный режим Выход из полноэкранного режима

Убедитесь, что изображение загружено в переменную button_img вверху.

button_img = pygame.image.load('img/restart.png')
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь нарисуйте кнопку внутри цикла после проверки, что это game_over.

# check for game over and reset
if game_over:
   if button.draw():
       game_over = False
       score = reset_game()
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы вызываем функцию reset_game, которая возвращает начальный счет (0). Объявите эту функцию в самом верху.

def reset_game():
    pipe_group.empty()
    flappy.rect.x = 100
    flappy.rect.y = int(screen_height / 2)
    score = 0
    return score
Вход в полноэкранный режим Выход из полноэкранного режима

Попробуйте поиграть в игру, намеренно нажимайте на трубы, и вы увидите кнопку перезапуска в центре экрана. Нажмите на нее, и игра перезапустится.

Заключение

Надеюсь, вам понравилось разрабатывать Flappy bird. Скоро я вернусь с другим учебником. Оставляйте свои комментарии.

Вот репозиторий Github: Flappy

Оцените статью
devanswers.ru
Добавить комментарий