Как сделать игру тетрис на Python

Показываем и рассказываем, как написать тетрис на Python с помощью модуля Pygame.

Как сделать игру тетрис на Python

Классический тетрис появился в 1984 году — но до сих пор будоражит умы людей со всего мира. В тетрис и по сей день играют миллионы, используя различные гаджеты и вычислительные машины.

Игру любят за четкость, достижимость цели и наглядную «обратную связь». В то же время тетрис полезен: развивает скорость реакции и пространственное мышление, учит концентрироваться на задаче и абстрагироваться от внешних раздражителей, успокаивает нервы и повышает производительность работы мозга.

Знать, как устроена любимая игра — захватывающе. Конструирование тетриса на языке Пайтон — способ испытать себя и усовершенствовать навыки программирования для начинающего кодера.

В конце инструкции — ссылка на тематический видеоурок: просмотр закрепит знания.

Начинаем воплощать тетрис на Пайтоне

Сразу напомним: модуль Pygame изначально не встроен в Python. Если он не установлен, проще это сделать в консоли командой pip install pygame.

Первым делом импортируем нужные библиотеки: pygame, random, copy. Copy понадобится, чтобы разобраться с одной особенностью хранения в Python.

После чего активируем модули Pygame и зададим 2 параметра сетки — I_max и J_max. Сетка строится по такому принципу: число ячеек равно числу точек -1. Можете убедиться в этом, посчитав на рисунке или нарисовав сами:

Как сделать игру тетрис на Python

Задав число точек I_max и J_max 11 и 21, получим 11 и 20 ячеек соответственно.

Добавляем переменные

Зададим 2 переменные с параметрами экрана 300 на 600. После сделаем экран, туда запишем переменные, а также создадим класс Clock(). Он понадобится для работы со временем — с частотой обновления экрана.

Сосчитаем шаг по x и по y для сетки — ширину и высоту ячейки. Делим на I_max -1, J_max -1: область необходимо разделить на число ячеек, а оно как раз на 1 меньше числа точек. Создаем переменную для частоты обновления кадров.

Как сделать тетрис на Python: применяем списки и циклы

Как сделать игру тетрис на Python

Делаем список, который будет хранить внутри себя параметры сетки, отображенные в окне. Добавим по списку на каждом элементе по ширине и на каждом элементе по высоте. Сразу занесем туда 1 — позднее станет понятно, зачем это сделано.

Кроме 1, заполним списки сущностями прямоугольников — rect, а также цветом для каждого из них. В координатах прямоугольников пишем координаты, где они должны находиться. Это можно сосчитать, умножив номер точки на шаг — ширину или высоту ячейки.

Пора запустить бесконечный цикл, заполнить экран для его обновления и нарисовать сетку. Для этого снова пройдемся по элементам сетки и нарисуем каждый квадратик. Третий элемент списка — 2: это цвет. Второй — 1: сущность прямоугольника, созданного ранее. Тип заполнения — 0: когда стоит 1, у прямоугольника нарисована граница шириной 1. Если бы поставили 0, он бы заполнился полностью.

Не забудьте добавить событие нажатия на крестик в игре.

Переходим к деталям

Тетрис — игра про детали. Потому рекомендуем посмотреть на 7 оригинальных фигур тетриса:

Как сделать игру тетрис на Python

Распишем их координаты в списке. Будем придерживаться того, что каждый третий — 0,0 элемент, который в будущем примем за ось вращения.

Создадим список уже не с координатами, а с самими деталями. Для этого делаем список det: каждый элемент будем заполнять 4 прямоугольниками. Координаты берем из списка с координатами и создаем детали в центре экрана сверху.

Посмотрим, чем заполняется список, выведем это в консоль. Видим, что в нем 7 списков, по 4 прямоугольника в каждом — что и хотели получить.

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

Как создать тетрис на Python: проектируем движения

Как сделать игру тетрис на Python

Для создания движения будем брать рандомно выбранную деталь det_choice и менять координаты у 4 прямоугольников на шаг dx и dy.

Для примера напишем 1*dx и посмотрим, что будет. Деталь быстро улетела вправо. Если поменяем на -1 — быстро улетит влево. Будем менять данные параметры с 0 на 1 и -1 при взаимодействии с клавишами стрелки вправо или стрелки влево. Создадим event нажатия на клавишу: если нажата стрелка влево, меняем переменную delta_x на -1. Для правой стрелки аналогично, только +1.

Теперь нужно настроить границы, чтобы за них нельзя было выходить. Для этого зададим условие: если хотя бы одна из деталей на следующей клетке (на следующем шаге) за пределами границ экрана, то delta_x зануляем, движения не произойдет.

Таким же образом сделаем перемещение по y. Для замедления включаем передвижение только каждые 30 обновлений. Для этого будем сохранять число обновлений в переменной.

Добавим вариант ускорения передвижения по y, если хотим резко уронить деталь и не ждать ее медленного падения. Чтобы зажимать клавишу, а не нажимать по кнопке много раз, используем функцию get_pressed(). Если ключ, который нажмет человек, совпадает с pygame.K_DOWN, т.е. стрелкой вниз, число обновлений сразу зададим равным 31.

Настроим границы для y: если на следующем шаге по y хотя бы одна деталь выйдет за нижнюю границу, остановим движение.

Остановили движение — зареспавним еще одну деталь. Для этого закрасим клетки сетки, где осталась фигура, белым цветом — зададим параметр заливки равным 0, а цвет изменим с серого на белый и сделаем новый выбор детали.

Исправляем ошибки

Как сделать игру тетрис на Python

После проверки в игре обнаружен баг — деталь появляется только 7 раз, после этого ничего не происходит. Это связано с хранением информации в Python: меняя координаты деталей, меняем и список — фигуры сразу возникают в самом низу. Чтобы такого не происходило, будем делать копию детали из списка и менять уже координаты копии, а не фигуры.

Теперь их появляется уже больше 7 штук, но они не ставятся друг на друга. Это следует исправить: пропишем условие в границы: если следующая снизу ячейка сетки закрашена, останавливаем движение.

Доделываем игру тетрис на Python

Основные механики готовы, осталось только внедрить пару вещей из оригинальной игры: поворот деталей и снос заполненного ряда.

Начнем с поворота. Его сделаем по стандартной математической формуле поворота на 90 градусов в декартовой системе координат — относительно центра в (0,0). Центр записан в третьей ячейке, поэтому обозначаем как центр второй индекс det_choice[2].

Создадим проверку на контакт с клавишей стрелки вверх — при ее нажатии переменная rotate становится равной True, выполняется условие. Проходимся по элементам квадратика и смещаем их относительно центра вращения, после чего переписываем rotate на False.

Последний штрих — снос заполненного ряда. Для этого запустим цикл, проверяющий, насколько заполнен каждый ряд. Идти будем снизу вверх и слева направо, считая число заполненных ячеек: в этом случае параметр заполнения равен 0. Если же хотя бы одна ячейка не равна 0, можем сказать, что полоска не заполнена — а затем завершить цикл на этом ряду и перейти к проверке следующего.

Если число заполненных ячеек равно числу ячеек в целом, запускаем еще 2 цикла. Сначала ячейки верхнего ряда делаем незакрашенными, а после все ячейки рядов смещаем на ряд вниз, начиная с заполненного.

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

Что дальше

Как и обещали, делимся YouTube-видеороликом о том, как сделать игру тетрис на Пайтоне: он поможет пройтись по изученному материалу. Также на канале находится плейлист с бесплатными роликами, посвященными реализации игр на Python. Стоит посмотреть, чтобы вдохновиться на конструирование игр.

Как сделать игру Тетрис на Python. Python создание игр с нуля

Отточить мастерство геймдева и программирования на Питоне также можно на специальных курсах под присмотром опытного преподавателя.

  • Ребятам 10–14 лет подойдет курс изучения языка Пайтон. Проштудировав азы разработки, подросток напишет квест или викторину, запустит чат-бота для мессенджера или игру с функцией стрельбы, бонусами и подсчетом очков.
  • Любителям Майнкрафта 9–13 лет понравится курс по кодингу на Python в Minecraft. Ребенок применит знания в любимой вселенной, написав внутриигровые программы или придумав персонажа с искусственным интеллектом.

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

Полный код программы:

import pygame

import random

import copy

pygame.init()

I_max = 11

J_max = 21

screen_x = 300

screen_y = 600

screen = pygame.display.set_mode((screen_x, screen_y))

clock = pygame.time.Clock()

pygame.display.set_caption("Tetris Pixel Game")

dx = screen_x/(I_max - 1)

dy = screen_y/(J_max - 1)

fps = 60

grid = []

for i in range(0, I_max):

grid.append([])

for j in range(0, J_max):

grid[i].append([1])

for i in range(0, I_max):

for j in range(0, J_max):

grid[i][j].append(pygame.Rect(i*dx, j*dy, dx, dy))

grid[i][j].append(pygame.Color("Gray"))

details = [

[[-2, 0], [-1, 0], [0, 0], [1, 0]],

[[-1, 1], [-1, 0], [0, 0], [1, 0]],

[[1, 1], [-1, 0], [0, 0], [1, 0]],

[[-1, 1], [0, 1], [0, 0], [-1, 0]],

[[1, 0], [1, 1], [0, 0], [-1, 0]],

[[0, 1], [-1, 0], [0, 0], [1, 0]],

[[-1, 1], [0, 1], [0, 0], [1, 0]],

]

det = [[],[],[],[],[],[],[]]

for i in range(0, len(details)):

for j in range(0, 4):

det[i].append(pygame.Rect(details[i][j][0]*dx + dx*(I_max//2), details[i][j][1]*dy, dx, dy))

detail = pygame.Rect(0, 0, dx, dy)

det_choice = copy.deepcopy(random.choice(det))

count = 0

game = True

rotate = False

while game:

delta_x = 0

delta_y = 1

for event in pygame.event.get():

if event.type == pygame.QUIT:

exit()

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_LEFT:

delta_x = -1

elif event.key == pygame.K_RIGHT:

delta_x = 1

elif event.key == pygame.K_UP:

rotate = True

key = pygame.key.get_pressed()

if key[pygame.K_DOWN]:

count = 31 * fps

screen.fill(pygame.Color("Black"))

for i in range(0, I_max):

for j in range(0, J_max):

pygame.draw.rect(screen, grid[i][j][2], grid[i][j][1], grid[i][j][0])

#границы

for i in range(4):

if ((det_choice[i].x + delta_x * dx < 0) or (det_choice[i].x + delta_x * dx >= screen_x)):

delta_x = 0

if ((det_choice[i].y + dy >= screen_y) or (grid[int(det_choice[i].x//dx)][int(det_choice[i].y//dy) + 1][0] == 0)):

delta_y = 0

for i in range(4):

x = int(det_choice[i].x // dx)

y = int(det_choice[i].y // dy)

grid[x][y][0] = 0 #закрашиваем квадратик

grid[x][y][2] = pygame.Color("White")

detail.x = 0

detail.y = 0

det_choice = copy.deepcopy(random.choice(det))

#передвижение по x

for i in range(4):

det_choice[i].x += delta_x*dx

count += fps

#передвижение по y

if count > 30 * fps:

for i in range(4):

det_choice[i].y += delta_y*dy

count = 0

for i in range(4):

detail.x = det_choice[i].x

detail.y = det_choice[i].y

pygame.draw.rect(screen, pygame.Color("White"), detail)

C = det_choice[2] #центр СК

if rotate == True:

for i in range(4):

x = det_choice[i].y - C.y

y = det_choice[i].x - C.x

det_choice[i].x = C.x - x

det_choice[i].y = C.y + y

rotate = False

for j in range(J_max - 1, -1, -1): #цикл по рядам снизу вверх

count_cells = 0

for i in range(0, I_max): #цикл по столбцам справа налево

if grid[i][j][0] == 0:

count_cells += 1

elif grid[i][j][0] == 1:

break

if count_cells == (I_max - 1):

for l in range(0, I_max):

grid[l][0][0] = 1 #все ячейки первого ряда

for k in range(j, -1, -1):

for l in range(0, I_max):

grid[l][k][0] = grid[l][k-1][0]

pygame.display.flip()

clock.tick(fps)

7
Начать дискуссию