Создаем гоночную игру на Python: от базового шаблона до финала

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Новички в программировании, интересующиеся созданием игр на Python
  • Студенты и самоучки, желающие улучшить свои навыки программирования через практику
  • Люди заинтересованные в разработке игр, которые хотят ознакомиться с основами использования библиотеки Pygame

    Разработка гоночной игры на Python — отличная возможность превратить теоретические знания программирования в осязаемый проект, который действительно работает и приносит удовольствие. Помню, как я сам впервые запустил свою примитивную гонку: всего пара пикселей, изображающих автомобиль, неуклюжее управление стрелочками — но восторг был неподдельным! 🏎️ В этом руководстве мы пройдём все этапы создания гоночной игры: от базовой настройки игрового окна до финальной полировки геймплея. Неважно, новичок вы или уже имеете опыт — этот проект станет идеальной площадкой для применения навыков Python в реальном проекте.

Мечтаете создавать собственные игры, но не знаете, с чего начать? Обучение Python-разработке от Skypro — ваш билет в мир программирования! Наш курс специально разработан для превращения новичков в профессионалов, способных создавать всё: от простых скриптов до полноценных игр. Вы не просто изучите синтаксис — вы научитесь мыслить как разработчик, решать реальные задачи и воплощать свои идеи в код.

Создание гонок на Python: основы и необходимые инструменты

Прежде чем погрузиться в создание гонок на Python, необходимо подготовить инструментарий. Pygame — это библиотека, которая превращает Python из языка для анализа данных и веб-разработки в полноценный инструмент для создания игр. Она предоставляет функции для работы с графикой, звуком и устройствами ввода, делая разработку игр доступной даже для начинающих программистов. 🛠️

Для начала установим необходимые компоненты. Откройте командную строку или терминал и введите:

pip install pygame

После установки библиотеки, давайте напишем базовый шаблон игры, который послужит фундаментом для нашей гоночной игры:

Python
Скопировать код
import pygame
import sys

# Инициализация Pygame
pygame.init()

# Настройка окна
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Гоночная игра на Python")

# Основной игровой цикл
running = True
while running:
# Обработка событий
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Логика игры

# Отрисовка
screen.fill((0, 0, 0)) # Заливка экрана черным цветом
pygame.display.flip() # Обновление экрана

# Ограничение FPS
pygame.time.Clock().tick(60)

# Завершение работы
pygame.quit()
sys.exit()

Этот код создаёт базовое окно игры с черным фоном, обрабатывает событие закрытия окна и поддерживает стабильную частоту кадров в 60 FPS.

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

  • Спрайты автомобилей (для игрока и, возможно, соперников)
  • Текстуры дороги и окружения
  • Препятствия и бонусы
  • Элементы интерфейса (счетчик скорости, таймер, очки)
Библиотека Назначение Сложность освоения
Pygame Основная библиотека для создания игр Средняя
NumPy Работа с векторами для физики движения Высокая
PIL/Pillow Обработка изображений Низкая
Pygame-GUI Создание пользовательского интерфейса Средняя

Алексей Петров, разработчик игр на Python

Помню свой первый опыт создания гоночной игры на Python. Я был уверен, что справлюсь за выходные — ведь как сложно может быть нарисовать машинку и заставить её двигаться? Спустя месяц кропотливой работы я понял, что недооценил задачу. Самым сложным оказалось не создание графики или написание кода движения, а настройка физики, которая бы ощущалась естественной. Машина либо двигалась как по рельсам, либо становилась неконтролируемой.

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

Пошаговый план для смены профессии

Настройка игрового окна и подготовка графических ресурсов

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

Давайте расширим базовый шаблон, добавив систему загрузки и управления графическими ресурсами:

Python
Скопировать код
import pygame
import os
import sys

# Инициализация и настройки окна (как в предыдущем примере)
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Гоночная игра на Python")

# Создаем класс для управления ресурсами
class ResourceManager:
def __init__(self):
self.images = {}
self.sounds = {}

def load_image(self, name, path, scale=1):
fullpath = os.path.join('assets', 'images', path)
try:
image = pygame.image.load(fullpath).convert_alpha()
if scale != 1:
w, h = image.get_width(), image.get_height()
image = pygame.transform.scale(image, (int(w * scale), int(h * scale)))
self.images[name] = image
return image
except pygame.error as e:
print(f"Не удалось загрузить изображение: {fullpath}")
print(f"Ошибка: {e}")
return None

def get_image(self, name):
return self.images.get(name)

# Создаем экземпляр менеджера ресурсов
resources = ResourceManager()

# Загружаем изображения
car_image = resources.load_image('player_car', 'car.png', scale=0.5)
road_image = resources.load_image('road', 'road.png')
background_image = resources.load_image('background', 'background.png')

# Настройка игровых объектов
car_x = screen_width // 2
car_y = screen_height – 100

# Основной игровой цикл
clock = pygame.time.Clock()
running = True

while running:
# Обработка событий
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Отрисовка
if background_image:
screen.blit(background_image, (0, 0))
if road_image:
screen.blit(road_image, (0, 0))
if car_image:
screen.blit(car_image, (car_x, car_y))

pygame.display.flip()
clock.tick(60) # 60 FPS

pygame.quit()
sys.exit()

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

Для создания качественных графических ресурсов у вас есть несколько вариантов:

  • Нарисовать самостоятельно используя графические редакторы (Photoshop, GIMP, Aseprite)
  • Использовать бесплатные ресурсы с таких сайтов как OpenGameArt, Kenney.nl или Itch.io
  • Создать простые геометрические формы с помощью Pygame (для прототипа)
  • Модифицировать существующие ресурсы с соответствующих лицензией

При подготовке графических ресурсов, учитывайте следующие рекомендации:

  • Используйте PNG-формат с прозрачностью для спрайтов
  • Создавайте ресурсы большего размера, чем требуется — масштабировать вниз всегда легче
  • Поддерживайте одинаковый стиль для всех элементов игры
  • Используйте отдельные слои для различных элементов (дорога, разметка, препятствия)
  • Сохраняйте исходные файлы в высоком разрешении для возможных будущих изменений

Структура папок для вашего проекта может выглядеть так:

racing_game/
├── main.py
├── assets/
│ ├── images/
│ │ ├── cars/
│ │ │ ├── player_car.png
│ │ │ └── enemy_cars/
│ │ ├── background/
│ │ │ ├── road.png
│ │ │ └── scenery.png
│ │ └── ui/
│ │ ├── buttons.png
│ │ └── scoreboard.png
│ └── sounds/
│ ├── engine.wav
│ ├── crash.wav
│ └── music.mp3
├── src/
│ ├── car.py
│ ├── game.py
│ └── utils.py
└── README.md

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

Программирование управления и движения автомобиля

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

Создадим класс Player, который будет отвечать за управление автомобилем игрока:

Python
Скопировать код
class Player:
def __init__(self, x, y, image):
self.x = x
self.y = y
self.image = image
self.speed = 0
self.max_speed = 10
self.acceleration = 0.2
self.deceleration = 0.1
self.turning_speed = 5
self.angle = 0 # Угол поворота в градусах
self.rotated_image = image
self.rect = self.image.get_rect(center=(x, y))

def handle_keys(self):
keys = pygame.key.get_pressed()

# Ускорение и торможение
if keys[pygame.K_UP]:
self.speed = min(self.speed + self.acceleration, self.max_speed)
elif keys[pygame.K_DOWN]:
self.speed = max(self.speed – self.acceleration, -self.max_speed/2)
else:
# Замедление, когда не нажаты клавиши
if self.speed > 0:
self.speed = max(self.speed – self.deceleration, 0)
elif self.speed < 0:
self.speed = min(self.speed + self.deceleration, 0)

# Поворот только когда автомобиль движется
if abs(self.speed) > 0.1:
if keys[pygame.K_LEFT]:
self.angle += self.turning_speed * (self.speed / self.max_speed)
if keys[pygame.K_RIGHT]:
self.angle -= self.turning_speed * (self.speed / self.max_speed)

def update(self):
# Расчет движения на основе скорости и угла
radians = math.radians(self.angle)
dx = -math.sin(radians) * self.speed
dy = -math.cos(radians) * self.speed

self.x += dx
self.y += dy

# Обновление позиции и поворота изображения
self.rotated_image = pygame.transform.rotate(self.image, self.angle)
self.rect = self.rotated_image.get_rect(center=(self.x, self.y))

def draw(self, screen):
screen.blit(self.rotated_image, self.rect.topleft)

Этот класс реализует несколько важных аспектов управления автомобилем:

  • Ускорение и замедление с плавными переходами
  • Поворот автомобиля в зависимости от скорости (быстрее на высоких скоростях)
  • Расчет движения на основе угла и скорости
  • Вращение спрайта автомобиля согласно текущему направлению

Теперь интегрируем наш класс Player в основной игровой цикл:

Python
Скопировать код
# В начале файла добавим:
import math

# После загрузки ресурсов:
player = Player(screen_width // 2, screen_height – 100, car_image)

# В основном игровом цикле:
while running:
# Обработка событий
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

# Обновление игровой логики
player.handle_keys()
player.update()

# Отрисовка
if background_image:
screen.blit(background_image, (0, 0))
if road_image:
screen.blit(road_image, (0, 0))

player.draw(screen)

pygame.display.flip()
clock.tick(60)

Параметр Эффект на управление Рекомендуемые значения
acceleration Скорость набора скорости 0.1 – 0.3
deceleration Скорость замедления 0.05 – 0.2
max_speed Максимальная скорость 5 – 15
turning_speed Скорость поворота 3 – 8

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

Для добавления реализма можно также реализовать:

  • Дрифт при резких поворотах на высокой скорости
  • Различные типы поверхностей с разным сцеплением
  • Физику ускорения, которая зависит от текущей скорости (труднее ускоряться на высоких скоростях)
  • Визуальные эффекты, такие как следы от шин или дым при дрифте

Создание трассы и реализация физики столкновений

Хорошо разработанная трасса — сердце гоночной игры. Она должна быть интересной, иметь разнообразные повороты и препятствия, а также корректно обрабатывать столкновения с автомобилем игрока. 🛣️

Существует несколько подходов к созданию трассы:

  1. Использование готового изображения трассы с определенными маркерами границ
  2. Программное создание трассы из отдельных сегментов
  3. Использование системы тайлов для построения различных конфигураций
  4. Процедурная генерация трассы на основе определенных параметров

Для простоты начнем с первого подхода и создадим класс для обработки трассы и столкновений:

Python
Скопировать код
class Track:
def __init__(self, image, boundary_color=(255, 0, 0)):
self.image = image
self.boundary_color = boundary_color
# Создаем маску для обнаружения столкновений с границами
self.mask = pygame.mask.from_surface(self.image)

def draw(self, screen):
screen.blit(self.image, (0, 0))

def check_collision(self, player):
# Получаем позицию игрока относительно трассы
player_x = int(player.x)
player_y = int(player.y)

# Проверяем, находится ли точка на границе трассы
try:
color = self.image.get_at((player_x, player_y))
if color[0:3] == self.boundary_color:
return True
except IndexError:
# Если игрок вышел за пределы изображения
return True

return False

def handle_collision(self, player):
# Упрощенная обработка столкновения – просто остановка и небольшой откат
if self.check_collision(player):
# Уменьшаем скорость и немного отбрасываем назад
player.speed = -player.speed * 0.5

# Откатываем позицию на один шаг назад
radians = math.radians(player.angle)
player.x += math.sin(radians) * player.speed * 2
player.y += math.cos(radians) * player.speed * 2
return True
return False

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

Интегрируем класс Track в основной код:

Python
Скопировать код
# После загрузки ресурсов:
track_image = resources.load_image('track', 'track.png')
track = Track(track_image, boundary_color=(255, 0, 0))

# В основном игровом цикле, перед отрисовкой игрока:
track.draw(screen)

# После обновления игрока, но до отрисовки:
track.handle_collision(player)

Для более сложной и реалистичной обработки столкновений можно использовать систему на основе маски или многоугольников. Вот улучшенная версия метода check_collision с использованием масок:

Python
Скопировать код
def check_collision(self, player):
# Создаем маску для спрайта игрока
player_mask = pygame.mask.from_surface(player.rotated_image)

# Смещение для проверки коллизии
offset_x = int(player.rect.x)
offset_y = int(player.rect.y)

# Проверка перекрытия масок
overlap = self.mask.overlap(player_mask, (offset_x, offset_y))

return overlap is not None

Михаил Соколов, преподаватель программирования

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

Решение пришло неожиданно, когда мы изменили сам подход к трассе. Вместо работы с единым изображением Никита создал две версии трассы: визуальную, которую видит игрок, и "маску столкновений" — невидимое изображение, где каждая область имела свой цвет, соответствующий определенному типу поверхности. Черный для асфальта, красный для границ, зеленый для травы (с пониженным сцеплением) и т.д.

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

Добавление игровой механики и финальная доработка проекта

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

Начнем с создания класса для компьютерных соперников:

Python
Скопировать код
class AIOpponent:
def __init__(self, x, y, image, track, waypoints):
self.x = x
self.y = y
self.image = image
self.track = track
self.waypoints = waypoints # Список точек, по которым будет двигаться ИИ
self.current_waypoint = 0
self.speed = 3
self.angle = 0
self.rotated_image = image
self.rect = self.image.get_rect(center=(x, y))

def update(self):
# Получаем текущую целевую точку
target_x, target_y = self.waypoints[self.current_waypoint]

# Рассчитываем направление к целевой точке
dx = target_x – self.x
dy = target_y – self.y

# Рассчитываем угол к целевой точке
target_angle = math.degrees(math.atan2(-dx, -dy))

# Плавно поворачиваем к целевой точке
angle_diff = (target_angle – self.angle + 180) % 360 – 180
if abs(angle_diff) > 2:
self.angle += min(2, max(-2, angle_diff * 0.1))

# Двигаемся вперед
radians = math.radians(self.angle)
self.x -= math.sin(radians) * self.speed
self.y -= math.cos(radians) * self.speed

# Обновляем изображение и прямоугольник
self.rotated_image = pygame.transform.rotate(self.image, self.angle)
self.rect = self.rotated_image.get_rect(center=(self.x, self.y))

# Проверяем, достигли ли мы текущей точки
if math.hypot(dx, dy) < 30:
self.current_waypoint = (self.current_waypoint + 1) % len(self.waypoints)

def draw(self, screen):
screen.blit(self.rotated_image, self.rect.topleft)

Теперь добавим систему подсчета времени и очков:

Python
Скопировать код
class GameHUD:
def __init__(self, screen_width, screen_height):
self.screen_width = screen_width
self.screen_height = screen_height
self.font = pygame.font.SysFont('Arial', 24)
self.start_time = pygame.time.get_ticks()
self.score = 0
self.lap = 0

def update(self, player_speed, lap_completed=False):
if lap_completed:
self.lap += 1
self.score += 1000 # Бонус за круг

# Дополнительные очки за скорость
self.score += abs(int(player_speed * 0.1))

def draw(self, screen):
# Рассчитываем прошедшее время
elapsed_time = (pygame.time.get_ticks() – self.start_time) // 1000
minutes = elapsed_time // 60
seconds = elapsed_time % 60

# Отрисовываем информацию
time_text = self.font.render(f'Время: {minutes:02d}:{seconds:02d}', True, (255, 255, 255))
score_text = self.font.render(f'Очки: {self.score}', True, (255, 255, 255))
lap_text = self.font.render(f'Круг: {self.lap}', True, (255, 255, 255))

screen.blit(time_text, (10, 10))
screen.blit(score_text, (10, 40))
screen.blit(lap_text, (10, 70))

Добавим систему контрольных точек для отслеживания прогресса на трассе:

Python
Скопировать код
class Checkpoint:
def __init__(self, x, y, width, height, checkpoint_id):
self.rect = pygame.Rect(x, y, width, height)
self.id = checkpoint_id
self.passed = False

def check_passed(self, player_rect):
if not self.passed and self.rect.colliderect(player_rect):
self.passed = True
return True
return False

def reset(self):
self.passed = False

def draw(self, screen, debug=False):
if debug:
pygame.draw.rect(screen, (0, 255, 0) if self.passed else (255, 0, 0), self.rect, 2)

Интеграция всех этих элементов в основной игровой цикл:

Python
Скопировать код
# Создаем контрольные точки
checkpoints = [
Checkpoint(400, 200, 50, 100, 0),
Checkpoint(600, 400, 100, 50, 1),
Checkpoint(200, 500, 100, 50, 2),
]

# Создаем путевые точки для ИИ соперников
ai_waypoints = [
(400, 200), (500, 300), (600, 400), 
(500, 500), (300, 500), (200, 400), 
(200, 200), (300, 150)
]

# Создаем ИИ соперника
opponent_image = resources.load_image('opponent_car', 'opponent_car.png', scale=0.5)
opponent = AIOpponent(300, 200, opponent_image, track, ai_waypoints)

# Создаем игровой HUD
hud = GameHUD(screen_width, screen_height)

# Переменные для отслеживания кругов
current_checkpoint = 0
total_checkpoints = len(checkpoints)
lap_completed = False

# В основном игровом цикле
while running:
# ... (обработка событий)

# Обновление
player.handle_keys()
player.update()
opponent.update()

# Проверка контрольных точек
if checkpoints[current_checkpoint].check_passed(player.rect):
current_checkpoint = (current_checkpoint + 1) % total_checkpoints
if current_checkpoint == 0:
lap_completed = True

# Обновление HUD
hud.update(player.speed, lap_completed)
lap_completed = False # Сбрасываем флаг круга

# Проверка столкновений
track.handle_collision(player)

# Отрисовка
track.draw(screen)

# Отрисовка контрольных точек в режиме отладки
for cp in checkpoints:
cp.draw(screen, debug=True)

player.draw(screen)
opponent.draw(screen)
hud.draw(screen)

pygame.display.flip()
clock.tick(60)

Для финальной доработки проекта рекомендую добавить следующие элементы:

  • Меню с возможностью выбора трасс и автомобилей
  • Звуковые эффекты для двигателя, столкновений, прохождения контрольных точек
  • Систему повреждений автомобиля
  • Бонусы и улучшения, которые можно подобрать на трассе
  • Таблицу лидеров для отслеживания лучших результатов
  • Различные режимы игры (гонка на время, заезд с соперниками, дрифт-режим)

Вот таблица возможных игровых режимов и их особенностей:

Режим игры Описание Особенности реализации
Гонка на время Прохождение трассы за минимальное время Точный таймер, контрольные точки, штрафы за столкновения
Гонка с соперниками Финиширование раньше ИИ-противников Несколько ИИ-машин, система обгона, позиции в гонке
Режим дрифта Набор очков за дрифт на поворотах Система подсчета длительности и угла дрифта, множители очков
Выживание Избегание препятствий максимально долго Процедурная генерация препятствий, прогрессивная сложность

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

Создание гоночной игры на Python — это гораздо больше, чем просто кодирование. Это творческий процесс, который соединяет математику, физику, графику и игровой дизайн в единое целое. Начав с простой модели движения и базовой трассы, вы можете постепенно расширять проект, добавляя всё более сложные механики и визуальные эффекты. Не бойтесь экспериментировать с параметрами физики и дизайном уровней — именно эти эксперименты помогут вашей игре обрести уникальный характер. И помните: самое ценное в разработке игр — это не конечный продукт, а опыт и знания, которые вы получаете в процессе создания.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какую библиотеку используется для создания игры в этой статье?
1 / 5

Загрузка...