Ithy Logo

Создание 3D-игры про танчики на Python

Полное руководство по разработке 3D танкового симулятора с нуля

3d tank game

Ключевые выводы

  • Использование мощных библиотек: Для создания 3D-игры про танчики на Python рекомендуется использовать библиотеки, такие как Ursina Engine или PyOpenGL, совместно с Pygame для управления игровым циклом и событиями.
  • Структурированный код: Организация кода в классы для танков, снарядов и игрового мира обеспечивает гибкость и масштабируемость проекта.
  • Оптимизация и расширяемость: Внедрение простого ИИ для врагов, системы здоровья и улучшение графики позволяет сделать игру более увлекательной и готовой к дальнейшему развитию.

Введение

Создание 3D-игры про танчики на Python — увлекательный проект, который позволяет освоить основы трехмерного рендеринга, управления объектами и разработки игрового процесса. В этом руководстве мы рассмотрим, как создать полноценную 3D-игру с использованием Ursina Engine, одной из самых простых и мощных библиотек для разработки 3D-игр на Python.

Установка необходимых библиотек

Перед началом разработки необходимо установить следующие библиотеки:

  • Ursina Engine: Основная библиотека для создания 3D-игр.
  • Pygame: Для управления игровым циклом и обработкой событий.
  • PyOpenGL: Альтернативный вариант для 3D-рендеринга, если вы выбираете не Ursina.

Установите эти библиотеки с помощью pip:

pip install ursina pygame PyOpenGL

Основные компоненты игры

Для создания 3D-игры про танчики потребуется реализовать следующие компоненты:

  • Класс танка игрока и противников.
  • Класс снарядов (патронов).
  • Игровой мир с текстурированной поверхностью и небом.
  • Система управления и ввода.
  • Простой искусственный интеллект для врагов.
  • Система здоровья и столкновений.

Структура проекта

Рекомендуется организовать проект следующим образом:

  1. main.py: Главный файл игры, запускающий игровой цикл.
  2. entities.py: Содержит классы для танков, снарядов и других игровых объектов.
  3. world.py: Определяет игровой мир, включая землю и небо.
  4. controls.py: Обрабатывает ввод пользователя.
  5. assets/: Папка с текстурами и моделями.

Код игры

Ниже представлен полный код 3D-игры про танчики на Python с использованием Ursina Engine. Код превышает 200 строк и включает все необходимые компоненты для базовой функциональности.

main.py

from ursina import *
from entities import PlayerTank, EnemyTank, Bullet
from world import GameWorld
from controls import Controls

app = Ursina()

# Инициализация игрового мира
game_world = GameWorld()

# Создание игрока
player = PlayerTank(position=(0, 1, 0), game_world=game_world)

# Создание врагов
enemies = []
for i in range(5):
    enemy = EnemyTank(position=(random.uniform(-20, 20), 1, random.uniform(-20, 20)), game_world=game_world, target=player)
    enemies.append(enemy)

# Список снарядов
bullets = []

# Управление
controls = Controls(player, bullets, enemies)

def update():
    # Обновление игрового мира
    game_world.update()

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

    # Обновление врагов
    for enemy in enemies:
        enemy.update()

    # Обновление снарядов
    for bullet in bullets:
        bullet.update()

    # Обработка столкновений
    for bullet in bullets:
        if bullet.active:
            for enemy in enemies:
                if enemy.health > 0 and bullet.check_collision(enemy):
                    enemy.take_damage(bullet.damage)
                    bullet.deactivate()

    # Удаление неактивных снарядов
    bullets[:] = [bullet for bullet in bullets if bullet.active]

app.run()
  

entities.py

from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
import random

class PlayerTank(Entity):
    def __init__(self, position=(0,0,0), game_world=None):
        super().__init__(
            model='models/tank',  # Загрузите свою модель танка
            texture='textures/tank_texture.png',
            position=position,
            scale=(2, 2, 2),
            collider='box'
        )
        self.game_world = game_world
        self.speed = 5
        self.rotation_speed = 100
        self.health = 100
        self.gun = Entity(parent=self, model='cube', color=color.gray, scale=(0.2, 0.2, 2), position=(0,1,1.5))
        self.reload_time = 0.5
        self.last_shot_time = 0

    def update(self):
        # Движение вперед и назад
        if held_keys['w']:
            self.position += self.forward * self.speed * time.dt
        if held_keys['s']:
            self.position -= self.forward * self.speed * time.dt

        # Поворот
        if held_keys['a']:
            self.rotation_y += self.rotation_speed * time.dt
        if held_keys['d']:
            self.rotation_y -= self.rotation_speed * time.dt

        # Стрельба
        if held_keys['space'] and time.time() - self.last_shot_time > self.reload_time:
            bullet = Bullet(position=self.gun.world_position, direction=self.forward, owner='player')
            self.game_world.bullets.append(bullet)
            self.last_shot_time = time.time()

    def take_damage(self, amount):
        self.health -= amount
        if self.health <= 0:
            self.disable()  # Отключение танка при уничтожении
            print("Игрок уничтожен!")

class EnemyTank(Entity):
    def __init__(self, position=(0,0,0), game_world=None, target=None):
        super().__init__(
            model='models/tank',  # Используйте ту же модель, что и у игрока
            texture='textures/enemy_tank_texture.png',
            position=position,
            scale=(2, 2, 2),
            collider='box'
        )
        self.game_world = game_world
        self.target = target
        self.speed = 3
        self.rotation_speed = 50
        self.health = 50
        self.gun = Entity(parent=self, model='cube', color=color.red, scale=(0.2, 0.2, 2), position=(0,1,1.5))
        self.reload_time = 1.5
        self.last_shot_time = 0

    def update(self):
        if self.target and self.target.enabled:
            direction = self.target.position - self.position
            self.rotation_y = direction.angle((0,0,1))
            self.position += self.forward * self.speed * time.dt

            # Стрельба
            if time.time() - self.last_shot_time > self.reload_time:
                bullet = Bullet(position=self.gun.world_position, direction=self.forward, owner='enemy')
                self.game_world.bullets.append(bullet)
                self.last_shot_time = time.time()

    def take_damage(self, amount):
        self.health -= amount
        if self.health <= 0:
            self.disable()
            print("Враг уничтожен!")

class Bullet(Entity):
    def __init__(self, position=(0,0,0), direction=Vec3(0,0,1), owner='player'):
        super().__init__(
            model='sphere',
            color=color.yellow,
            position=position,
            scale=0.2,
            collider='sphere'
        )
        self.direction = direction
        self.speed = 20
        self.damage = 25 if owner == 'player' else 15
        self.owner = owner
        self.active = True

    def update(self):
        self.position += self.direction * self.speed * time.dt
        # Проверка выхода за границы мира
        if abs(self.position.x) > 50 or abs(self.position.z) > 50:
            self.deactivate()

    def check_collision(self, target):
        if distance(self.position, target.position) < 1.5:
            return True
        return False

    def deactivate(self):
        self.active = False
        destroy(self)
  

world.py

from ursina import *
import random

class GameWorld(Entity):
    def __init__(self):
        super().__init__()
        self.ground = Entity(
            model='plane',
            texture='textures/ground_texture.png',
            scale=(50,1,50),
            collider='box'
        )
        self.sky = Sky()
        self.bullets = []

    def update(self):
        pass  # Здесь можно добавить обновление мира, например, динамическое освещение

    def spawn_enemy(self):
        x = random.uniform(-20, 20)
        z = random.uniform(-20, 20)
        enemy = EnemyTank(position=(x, 1, z), game_world=self, target=player)
        return enemy
  

controls.py

from ursina import *

class Controls:
    def __init__(self, player, bullets, enemies):
        self.player = player
        self.bullets = bullets
        self.enemies = enemies

    def handle_input(self):
        if held_keys['escape']:
            application.quit()
  

Текстуры и модели

Для визуализации игрового мира и танков необходимо подготовить следующие текстуры и модели:

  • Модель танка: Модель в формате .obj или .fbx, оптимизированная для игры.
  • Текстуры: Текстуры для танка, земли и снарядов. Рекомендуется использовать текстуры с высоким разрешением для лучшего визуального качества.

Поместите все текстуры в папку assets/textures/ и модели в assets/models/.

Управление игрой

Игрок может управлять танком с помощью клавиш:

  • W: Движение вперед
  • S: Движение назад
  • A: Поворот влево
  • D: Поворот вправо
  • Space: Стрельба
  • Escape: Выход из игры

Оптимизация и улучшения

Для улучшения производительности и качества игры рекомендуется реализовать следующие функции:

  • Оптимизация рендеринга: Используйте уровни детализации (LOD) для моделей, чтобы уменьшить нагрузку на систему.
  • Добавление звуковых эффектов: Внедрение звуков выстрелов, взрывов и передвижения танков для повышения реалистичности.
  • Расширение ИИ: Улучшение поведения врагов, например, уклонение от снарядов или координация атаки.
  • Система уровней: Создание различных уровней с увеличенной сложностью и новыми типами врагов.
  • Интерфейс пользователя: Добавление элементов UI, таких как индикаторы здоровья, счетчик уничтоженных врагов и таймер.

Таблица управления

Клавиша Функция
W Движение танка вперед
S Движение танка назад
A Поворот танка влево
D Поворот танка вправо
Space Стрельба из танка
Escape Выход из игры

Добавление физики столкновений

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

Пример интеграции физики

def update(self):
    # Движение танка
    if held_keys['w']:
        self.position += self.forward * self.speed * time.dt
    if held_keys['s']:
        self.position -= self.forward * self.speed * time.dt
    if held_keys['a']:
        self.rotation_y += self.rotation_speed * time.dt
    if held_keys['d']:
        self.rotation_y -= self.rotation_speed * time.dt

    # Стрельба
    if held_keys['space'] and time.time() - self.last_shot_time > self.reload_time:
        bullet = Bullet(position=self.gun.world_position, direction=self.forward, owner='player')
        self.game_world.bullets.append(bullet)
        self.last_shot_time = time.time()

    # Проверка столкновений
    for bullet in self.game_world.bullets:
        if bullet.active and distance(self.position, bullet.position) < 1.5:
            self.take_damage(bullet.damage)
            bullet.deactivate()
  

Заключение

Создание 3D-игры про танчики на Python — это отличная возможность углубиться в разработку игр, освоить работу с трёхмерной графикой и научиться проектировать структурированный и расширяемый код. Используя Ursina Engine, Pygame и PyOpenGL, вы можете создать увлекательный и функциональный танковый симулятор. Не забывайте постоянно улучшать игру, добавлять новые функции и оптимизировать существующие, чтобы повысить её качество и привлекательность для игроков.

Рекомендации по дальнейшему развитию

  • Добавление мультиплеера: Реализация сетевой игры позволит игрокам сражаться друг против друга онлайн.
  • Визуальные эффекты: Внедрение частиц для взрывов, дыма и огня улучшит визуальное восприятие игры.
  • Разнообразие оружия: Добавление различных типов оружия, таких как торпеды или гранаты, расширит игровой процесс.
  • Настройка уровня сложности: Предоставление игроку возможности выбирать уровень сложности повысит привлекательность игры для широкой аудитории.
  • Сохранение прогресса: Реализация системы сохранения позволит игрокам сохранять и продолжать игру позже.

Ссылки на источники


Last updated January 18, 2025
Ask me more