В предыдущем уроке мы уже создали первый вариант игры Berd на Python с использованием библиотеки Pygame. В ней птичка прыгает по пирамиде из кубиков, закрашивает клетки и получает очки.
В версии Berd 2.1 мы добавим несколько важных игровых механизмов:
- появляющиеся и исчезающие бонусные яйца
- систему проверки завершения уровня
- сообщение о победе
В этом уроке основной упор сделан на новые части программы, а уже знакомые блоки кода будут рассмотрены кратко.
📝Текст программы
import pygame
import sys
import random
pygame.init()
WIDTH, HEIGHT = 900,700
screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Berd 2.1")
clock = pygame.time.Clock()
ROWS = 7
TILE = 90
BG = (30,30,40)
# загрузка изображений
cube = pygame.image.load("cube_day.png").convert_alpha()
cube_painted = pygame.image.load("cube_day_painted.png").convert_alpha()
bird = pygame.image.load("bird.png").convert_alpha()
bonus_img = pygame.image.load("bonus_ball.png").convert_alpha()
cube = pygame.transform.scale(cube,(TILE,TILE))
cube_painted = pygame.transform.scale(cube_painted,(TILE,TILE))
bird = pygame.transform.scale(bird,(60,60))
bonus_img = pygame.transform.scale(bonus_img,(40,40))
font = pygame.font.SysFont(None,40)
# состояние кубиков
grid = []
for r in range(ROWS):
row = []
for c in range(r+1):
row.append(False)
grid.append(row)
# бонусы (r,c,time)
bonuses = []
# время жизни бонуса
BONUS_LIFE = 180 # 3 секунды при 60 FPS
# очки
score = 0
# позиция птички
bird_r = 0
bird_c = 0
grid[0][0] = True
game_over = False
def cube_position(r,c):
start_x = WIDTH//2
start_y = 120
x = start_x + (c - r/2) * TILE
y = start_y + r * TILE * 0.6
return x,y
def draw_cube(x,y,painted):
if painted:
img = cube_painted
else:
img = cube
screen.blit(img,(x,y))
def draw_bird():
x,y = cube_position(bird_r,bird_c)
bx = x + TILE/2 - 30
by = y - 20
screen.blit(bird,(bx,by))
def draw_bonuses():
for bonus in bonuses:
r,c,timer = bonus
x,y = cube_position(r,c)
bx = x + TILE/2 - 20
by = y + 10
screen.blit(bonus_img,(bx,by))
def spawn_bonus():
if random.randint(0,200) == 1:
r = random.randint(0,ROWS-1)
c = random.randint(0,r)
bonuses.append([r,c,BONUS_LIFE])
def update_bonuses():
for bonus in bonuses[:]:
bonus[2] -= 1
if bonus[2] <= 0:
bonuses.remove(bonus)
def check_win():
for row in grid:
for cell in row:
if not cell:
return False
return True
def move_bird(dr,dc):
global bird_r,bird_c,score,game_over
nr = bird_r + dr
nc = bird_c + dc
if nr < 0 or nr >= ROWS:
return
if nc < 0 or nc > nr:
return
bird_r = nr
bird_c = nc
# закрашивание кубика
if not grid[bird_r][bird_c]:
grid[bird_r][bird_c] = True
score += 10
# проверка бонуса
for bonus in bonuses[:]:
r,c,t = bonus
if r == bird_r and c == bird_c:
bonuses.remove(bonus)
score += 30
# проверка победы
if check_win():
game_over = True
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and not game_over:
# управление цифровым блоком
if event.key == pygame.K_KP1:
move_bird(1,0)
if event.key == pygame.K_KP3:
move_bird(1,1)
if event.key == pygame.K_KP7:
move_bird(-1,-1)
if event.key == pygame.K_KP9:
move_bird(-1,0)
if not game_over:
spawn_bonus()
update_bonuses()
screen.fill(BG)
for r in range(ROWS):
for c in range(r+1):
x,y = cube_position(r,c)
draw_cube(x,y,grid[r][c])
draw_bonuses()
draw_bird()
score_text = font.render("Score: " + str(score),True,(255,255,255))
screen.blit(score_text,(20,20))
if game_over:
text = font.render("LEVEL COMPLETE!",True,(255,220,0))
screen.blit(text,(WIDTH//2-140,50))
pygame.display.flip()
clock.tick(60)
🧱 Основная структура программы (кратко)
В начале программы подключаются модули и запускается игровой движок.
import pygame
import sys
import random
pygame.init()
Создаётся окно игры:
WIDTH, HEIGHT = 900,700
screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Berd 2.1")
Задаётся частота обновления кадров:
clock = pygame.time.Clock()
🧱 Игровое поле
Поле представляет собой пирамиду из кубиков.
Количество рядов:
ROWS = 7
Состояние кубиков хранится в двумерном списке grid.
False — кубик не закрашен
True — кубик закрашен
После прыжка птички клетка становится закрашенной.
🖼 Загрузка графики
Игра использует несколько изображений:
- обычный кубик
- закрашенный кубик
- птичка
- бонусное яйцо
cube = pygame.image.load("cube_day.png").convert_alpha()
cube_painted = pygame.image.load("cube_day_painted.png").convert_alpha()
bird = pygame.image.load("bird.png").convert_alpha()
bonus_img = pygame.image.load("bonus_ball.png").convert_alpha()
После загрузки изображения масштабируются под нужный размер.
🐦 Движение птички
Функция move_bird() отвечает за перемещение персонажа.
Она:
- проверяет границы пирамиды
- перемещает птичку
- закрашивает клетку
- добавляет очки
За каждую новую клетку игрок получает:
+10 очков
🥚 Новая система бонусов
Одно из главных нововведений версии Berd 2.1 — бонусные яйца.
Они появляются случайно на пирамиде.
Для хранения бонусов используется список:
bonuses = []
Каждый бонус хранит три значения:
ряд
колонку
таймер жизни
Пример бонуса:
[3, 1, 180]
где:
3 — ряд
1 — колонка
180 — время жизни
🥚 Появление бонуса
Функция spawn_bonus() отвечает за случайное появление яйца.
def spawn_bonus():
if random.randint(0,200) == 1:
r = random.randint(0,ROWS-1)
c = random.randint(0,r)
bonuses.append([r,c,BONUS_LIFE])
Что происходит в этой функции:
1️⃣ Генерируется случайное число
2️⃣ Иногда создаётся новый бонус
3️⃣ Бонус добавляется в список
Это создаёт эффект непредсказуемого появления награды.
⏳ Таймер жизни бонуса
Новое поведение бонусов — они не остаются на поле бесконечно.
Каждое яйцо имеет таймер жизни:
BONUS_LIFE = 180
Это примерно 3 секунды при 60 FPS.
Функция update_bonuses() уменьшает таймер.
def update_bonuses():
for bonus in bonuses[:]:
bonus[2] -= 1
if bonus[2] <= 0:
bonuses.remove(bonus)
Что делает эта функция:
1️⃣ каждый кадр уменьшает таймер
2️⃣ проверяет, не закончился ли он
3️⃣ удаляет бонус, если время истекло
Таким образом игроку нужно успеть поймать яйцо, иначе оно исчезнет.
⭐ Получение бонуса
Когда птичка попадает на клетку с яйцом:
игрок получает +30 очков
Бонус удаляется из списка:
bonuses.remove(bonus)
Это добавляет игре элемент реакции и скорости.
🏁 Проверка завершения уровня
Вторая важная функция — check_win().
Она проверяет, закрашены ли все клетки пирамиды.
def check_win():
for row in grid:
for cell in row:
if not cell:
return False
return True
Логика работы:
1️⃣ перебираются все ряды
2️⃣ проверяются все клетки
3️⃣ если найдена незакрашенная — игра продолжается
Если все клетки закрашены — игрок победил.
🎉 Завершение игры
Когда функция check_win() возвращает True, игра устанавливает флаг:
game_over = True
После этого:
- управление отключается
- появляется сообщение о завершении уровня
На экране выводится текст:
LEVEL COMPLETE!
Это сигнал игроку, что пирамида полностью закрашена.
🔄 Главный игровой цикл (кратко)
Игровой цикл выполняет несколько действий:
обработка событий
движение птички
появление бонусов
обновление бонусов
рисование поля
рисование персонажа
вывод очков
обновление экрана
Этот цикл повторяется 60 раз в секунду, создавая плавную анимацию игры.
🎮 Что получилось
В версии Berd 2.1 игра стала заметно интереснее:
🐦 управление персонажем
🧱 закрашивание пирамиды
🥚 случайные бонусы
⏳ исчезающие яйца
⭐ система очков
🏁 завершение уровня
Это отличный пример того, как сделать простую игру на python, изучая Pygame.
📚 Итог
В этом уроке мы расширили игру и добавили новые механики:
- систему бонусов
- таймер исчезновения предметов
- проверку завершения уровня
Такие улучшения помогают постепенно создавать более сложные игры на pygame, а уроки с реальными проектами — лучший способ изучать python pygame.