Разработка игры в стиле Mario с нуля на Python

Создание собственной игры в духе легендарного Super Mario Bros — это отличный способ прокачать навыки программирования, погрузиться в основы геймдева и просто повеселиться. В этой статье разберем, как разработать простую платформенную игру с нуля на языке Python, используя библиотеку Pygame.
http://t.me/pythonl – в нашем тг канале еще больше уроков и проектов для python разработчиков.
Предварительная подготовка
Перед тем как приступить к разработке, убедитесь, что у вас установлен Python и Pygame:
pip install pygame
Создадим структуру проекта:
/mario_game
|-- main.py
|-- player.py
|-- level.py
|-- config.py
|-- assets/
|-- images/
|-- sounds/
1. Окно игры
Начнем с создания игрового окна:
# main.py
import pygame
from config import *
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Mini Mario")
clock = pygame.time.Clock()
🔍 Построчное объяснение:
import pygame
Импортируем библиотеку Pygame, которая используется для разработки 2D-игр в Python. Она предоставляет удобный интерфейс для работы с графикой, звуком, управлением и т.д.
from config import *
Импортируются все переменные из модуля config.py
. Обычно в этом файле мы задаём глобальные настройки, такие как размеры окна, цвета, FPS и прочее.
Пример содержимого config.py
:
pythonКопироватьРедактироватьSCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
pygame.init()
Инициализирует все встроенные модули Pygame (видео, звук, таймеры и т.д.). Это обязательный вызов перед использованием остальных функций библиотеки.
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
Создаёт главное игровое окно с заданной шириной и высотой. Возвращает объект Surface
, на который мы будем рисовать всё: фон, персонажей, платформы и т.д.
pygame.display.set_caption("Mini Mario")
Устанавливает заголовок окна (то, что отображается в верхней части окна игры или на панели задач).
clock = pygame.time.Clock()
Создаёт объект Clock
, с помощью которого можно контролировать частоту кадров (FPS) в игровом цикле. Это помогает сделать игру более стабильной и плавной.
📌 Итог:
Этот блок создаёт окно и подготавливает всё необходимое для запуска игры: графику, заголовок, и таймер для контроля скорости игры. Это фундамент, с которого начинается практически любое приложение на Pygame.
2. Создание игрока
Создадим класс Player
, который отвечает за героя:
# player.py
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load("assets/images/mario.png").convert_alpha()
self.rect = self.image.get_rect(topleft=(x, y))
self.velocity_y = 0
self.on_ground = False
def update(self, keys):
dx = 0
if keys[pygame.K_LEFT]:
dx = -5
if keys[pygame.K_RIGHT]:
dx = 5
self.velocity_y += 0.5 # gravity
if self.velocity_y > 10:
self.velocity_y = 10
dy = self.velocity_y
if keys[pygame.K_SPACE] and self.on_ground:
self.velocity_y = -10
self.on_ground = False
self.rect.x += dx
self.rect.y += dy
# ground check (simplified)
if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
self.velocity_y = 0
self.on_ground = True
Давайте разберём следующий блок кода — класс Player
из файла player.py
, который отвечает за управление игровым персонажем:
🔍 Объяснение построчно:
class Player(pygame.sprite.Sprite):
Создаём класс игрока, который наследуется от pygame.sprite.Sprite
— это позволяет удобно управлять группами спрайтов (например, отрисовкой и столкновениями).
def __init__(self, x, y):
Конструктор, принимает начальные координаты x
и y
для размещения игрока на экране.
super().__init__()
Вызываем конструктор родительского класса (Sprite
), чтобы всё работало правильно в рамках pygame.sprite
.
self.image = pygame.image.load("assets/images/mario.png").convert_alpha()
Загружаем картинку персонажа (Mario), используем convert_alpha()
для поддержки прозрачности.
self.rect = self.image.get_rect(topleft=(x, y))
Создаём прямоугольник (rect
) — это объект, описывающий позицию и размеры спрайта. Мы используем его для движения и столкновений.
self.velocity_y = 0
Скорость по вертикали (нужна для прыжков и гравитации).
self.on_ground = False
Флаг, указывающий, стоит ли игрок на земле. Это нужно, чтобы не позволить прыгать в воздухе.
👇 Метод update(self, keys)
— вызывается каждый кадр
dx = 0
Смещение по горизонтали.
if keys[pygame.K_LEFT]: dx = -5
Если нажата стрелка влево — двигаемся влево на 5 пикселей.
if keys[pygame.K_RIGHT]: dx = 5
Если нажата стрелка вправо — двигаемся вправо.
self.velocity_y += 0.5
Добавляем гравитацию. Чем дольше падаем — тем быстрее.
if self.velocity_y > 10: self.velocity_y = 10
Ограничиваем максимальную скорость падения.
dy = self.velocity_y
Сохраняем вертикальное смещение.
if keys[pygame.K_SPACE] and self.on_ground:
Если нажата клавиша пробел и игрок стоит на земле — делаем прыжок:
pythonКопироватьРедактироватьself.velocity_y = -10
self.on_ground = False
self.rect.x += dx
Перемещаем игрока по горизонтали.
self.rect.y += dy
Перемещаем по вертикали (с учётом гравитации и прыжков).
if self.rect.bottom >= SCREEN_HEIGHT:
Если игрок опускается ниже экрана (например, упал) — ставим его обратно на землю:
pythonКопироватьРедактироватьself.rect.bottom = SCREEN_HEIGHT
self.velocity_y = 0
self.on_ground = True
📌 Вывод
Класс Player
реализует базовое движение игрока:
• Влево/вправо
• Прыжок
• Гравитация
• Простая проверка, стоит ли он на земле
Это фундамент платформера.
3. Уровень и платфоры
Создадим платформы, по которым может ходить игрок:
# level.py
import pygame
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill((100, 100, 100))
self.rect = self.image.get_rect(topleft=(x, y))
🔍 Объяснение построчно
import pygame
Импортируем Pygame — для работы со спрайтами и отрисовкой.
class Platform(pygame.sprite.Sprite):
Определяем класс Platform
, представляющий собой простую платформу. Как и Player
, он наследует pygame.sprite.Sprite
, что позволяет использовать его в группах спрайтов, например Group.draw()
.
def __init__(self, x, y, width, height):
Конструктор, принимает:
x
,y
— координаты верхнего левого угла платформыwidth
,height
— размеры платформы
super().__init__()
Вызываем конструктор родительского класса Sprite
.
self.image = pygame.Surface((width, height))
Создаём пустую поверхность (Surface
) — прямоугольник нужного размера. Это будет изображение платформы.
self.image.fill((100, 100, 100))
Закрашиваем платформу серым цветом. Можно заменить на любую картинку — например, кирпичи, траву и т.д.
self.rect = self.image.get_rect(topleft=(x, y))
Создаём прямоугольную область (rect
), описывающую положение платформы на экране.
🧱 Что делает этот класс?
Он создаёт прямоугольную платформу, по которой может ходить игрок. Позже мы добавляем такие платформы в Group
и рисуем их, как обычные спрайты.
🧩 Как используется?
Вот часть из main.py
, где мы добавляем платформу на экран:
pythonКопироватьРедактироватьfrom level import Platform
platforms = pygame.sprite.Group()
platforms.add(Platform(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40)) # земля
Тут создаётся платформа-земля — она тянется на всю ширину экрана, располагается внизу и имеет высоту 40 пикселей.
4. Главный цикл игры
Соберем все воедино:
# main.py (продолжение)
from player import Player
from level import Platform
player = Player(100, 300)
player_group = pygame.sprite.Group()
player_group.add(player)
platforms = pygame.sprite.Group()
platforms.add(Platform(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40))
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
player.update(keys)
screen.fill((135, 206, 235)) # sky blue
platforms.draw(screen)
player_group.draw(screen)
pygame.display.flip()
pygame.quit()
5.
- Сделать уровни из массива/тайлов
- Добавить столкновения игрока с платформами
🧱 1. Уровень из массива (tile map)
Идея простая: задаём уровень как список строк, где каждый символ означает элемент карты. Пример:
level_map = [
" ",
" ",
" XX XX ",
" ",
" XXXX XXXX XX ",
"XXXXXXXX XXXXXXXXX XXXX ",
]
"X"
— платформа" "
— пустота
🔄 Построение карты
Создаём функцию, которая будет проходить по level_map
и размещать платформы на нужных позициях:
TILE_SIZE = 40 # размер одного тайла
def build_level(level_data):
platforms = pygame.sprite.Group()
for row_index, row in enumerate(level_data):
for col_index, tile in enumerate(row):
if tile == "X":
x = col_index * TILE_SIZE
y = row_index * TILE_SIZE
platform = Platform(x, y, TILE_SIZE, TILE_SIZE)
platforms.add(platform)
return platforms
📌 Теперь можно создать платформы так:
pythonКопироватьРедактироватьplatforms = build_level(level_map)
🧱 2. Столкновения с платформами
Добавим в Player.update()
логику проверки столкновений с платформами. Например:
def update(self, keys, platforms):
dx = 0
dy = 0
# движение влево/вправо
if keys[pygame.K_LEFT]:
dx = -5
if keys[pygame.K_RIGHT]:
dx = 5
# гравитация
self.velocity_y += 0.5
if self.velocity_y > 10:
self.velocity_y = 10
dy += self.velocity_y
# прыжок
if keys[pygame.K_SPACE] and self.on_ground:
self.velocity_y = -10
self.on_ground = False
# горизонтальные столкновения
self.rect.x += dx
for platform in platforms:
if self.rect.colliderect(platform.rect):
if dx > 0: # вправо
self.rect.right = platform.rect.left
if dx < 0: # влево
self.rect.left = platform.rect.right
# вертикальные столкновения
self.rect.y += dy
self.on_ground = False
for platform in platforms:
if self.rect.colliderect(platform.rect):
if self.velocity_y > 0: # падение
self.rect.bottom = platform.rect.top
self.velocity_y = 0
self.on_ground = True
elif self.velocity_y < 0: # прыжок вверх
self.rect.top = platform.rect.bottom
self.velocity_y = 0
👾 Использование:
В main.py
теперь передаём платформы в update()
:
pythonКопироватьРедактироватьplayer.update(keys, platforms)
6. Развитие
Что можно добавить дальше:
- Враги и ИИ
- Монетки и система очков
- Таймер, жизни, уровни
- Фоновая музыка и звуки прыжков
- Анимации бега и прыжков
- Камера, следящая за игроком
Если статья наберет 100 лайков, мы продолжим делать игру и добавим фичи выше.
Вывод
Создание своей Mario-подобной игры на Python — это увлекательный проект, который помогает понять принципы гейм-логики, работы с графикой и анимацией. Начав с простого, вы легко сможете наращивать функциональность и делать свою игру всё более продвинутой.