Как написать игру на языке программирования

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

Чтобы извлечь пользу из этого руководства, нужно уметь программировать на Python, а также знать, как в языке реализуется объектно-ориентированное программирование. Для независимой установки движков мы советуем использовать виртуальные окружения.

Игровые движки для Python обычно являются библиотеками, которые можно установить с помощью менеджера pip или загрузить с площадок распространения кода. В противовес к библиотекам существуют автономные среды, предназначенные исключительно для написания игр:

  • Unreal Engine
  • Unity
  • Godot

Такие программы отличаются от игровых движков Python во многих аспектах:

  • Поддерживаемые языки. Среды программирования игр обычно написаны на C-подобных языках и предлагают использовать соответствующие языки для написания игр: в Unity это C#, в Unreal Engine — C++.
  • Поддержка платформ. Автономные среды позволяют без дополнительных усилий создавать игры для различных платформ, включая мобильные устройства. Напротив, перенос Python-игры на мобильные устройства — задача не из лёгких.
  • Лицензирование. Игры, написанные с использованием автономного игрового движка, имеют особые условия лицензирования и дальнейшего распространения.

Зачем же вообще использовать Python для написания игр? Использование GameDev-сред требует изучения документации и обычно — овладения новым языком программирования. В то же время при работе с игровыми движками на Python питонисты применяют в основном уже имеющиеся знания. Это помогает быстрее двигаться вперед и получить первый результат.

Критерии отбора Python-движков в этой статье:

  • популярность,
  • актуальная поддержка,
  • качественная документация.

Для каждого движка мы рассмотрим способ установки, базовую терминологию и основные возможности для реализации игр.

Pygame

Pygame — первое, что приходит на ум, когда кто-нибудь начинает разговор об играх на Python.

Pygame расширяет собой библиотеку SDL (сокр. от Simple DirectMedia Layer), предназначенную для межплатформенного доступа к мультимедийным аппаратным компонентам системы: мыши, клавиатуре, джойстику, аудио- и видеоустройствам.

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

Установка Pygame

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

        (venv) $ python -m pip install pygame

    

Чтобы проверить результат установки, запустите пример, поставляемый вместе с библиотекой:

        (venv) $ python -m pygame.examples.aliens

    

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

Базовые концепции Pygame

Game loop. Для управления ходом игры используется понятие игрового цикла. Функциональность игрового цикла реализует автор, а Pygame предоставляет необходимые методы и функции. Каждая итерация игрового цикла называется кадром (frame). За один кадр игра выполняет четыре действия:

  1. Обработка пользовательского ввода от мыши, клавиатуры или джойстика с помощью модели событий.
  2. Обновление состояния игровых объектов: спрайтов (образы героев и предметов), изображений, шрифтов и цветов. Объекты описываются подходящими структурами данных или с помощью классов Pygame.
  3. Обновление дисплея и аудиовыхода. Pygame обеспечивает абстрактный доступ к оборудованию для отображения картинки и передачи звука с помощью внутренних модулей display, mixer и music.
  4. Сохранение или изменение скорости игры. Модуль pygame.time позволяет авторам игр контролировать скорость игры. За счёт этого игра работает с одинаковой скоростью на различном оборудовании — библиотека гарантирует завершение каждого кадра в течение заданного периода времени.

Базовый пример Pygame

В трех следующих движках мы будем начинать рассмотрение с базового примера, в котором движок рисует на на экране пару фигур и выводит текст.

🐍🕹️ Как написать игру на Python: 5 игровых движков

        # Импортируем и инициализируем библиотеку
import pygame

pygame.init()

# Устанавливаем ширину и высоту окна в пикселях
WIDTH = 800
HEIGHT = 600

# Настраиваем окно отрисовки
screen = pygame.display.set_mode([WIDTH, HEIGHT])

# Игровой цикл выполняется, пока пользователь не захочет выйти
running = True
while running:

    # Нажал ли пользователь кнопку зыкрытия окна?
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Заполняем фон белым цветом
    screen.fill((255, 255, 255))

    # Рисуем синий круг в центре экрана радиусом 50
    pygame.draw.circle(screen, (0, 0, 255), (WIDTH // 2, HEIGHT // 2), 50)

    # Рисуем красный контурный квадрат в верхнем левом углу экрана
    red_square = pygame.Rect((50, 50), (100, 100))
    pygame.draw.rect(screen, (200, 0, 0), red_square, 1)

    # Рисуем оранжевый текст с кеглем 60
    text_font = pygame.font.SysFont("any_font", 60)
    text_block = text_font.render(
        "Hello, World! From Pygame", False, (200, 100, 0)
    )
    screen.blit(text_block, (50, HEIGHT - 50))

		# Обновляем экран
    pygame.display.flip()

# Цикл завершился! Уходим.
pygame.quit()

    

Для запуска кода используйте команду:

        (venv) $ python pygame/pygame_basic.py

    

Игровой цикл есть даже в такой скромной программе. В примере он управляется переменной running. Её установка в значение False завершает выполнение программы.

Обработка событий. События хранятся в виде очереди, из неё события извлекаются с помощью pygame.event.get(). В рассматриваемом случае обрабатывается только событие pygame.QUIT, генерируемое при закрытии пользователем окна программы. При обработке этого события мы устанавливаем running = False.

Отрисовка фигур и текста. В то время как для отрисовки фигур просто используются специальные методы, отрисовка текста выглядит несколько сложнее. Сначала выбираем шрифт и создаем объект шрифта. Далее вызываем метод .render() и передаем ему текст, шрифт и цвет. В ответ метод создает объект класса Surface. Этот объект мы копируем на экран screen, используя его метод screen.blit().

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

Продвинутый вариант игры на Pygame

Чтобы лучше изучить возможности Pygame, напишем настоящую игру.

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

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

При запуске игра выглядит примерно вот так
        # Импорт и инициализация
import pygame

# Для случайного размещения монет
from random import randint

# Для поиска ресурсов
from pathlib import Path

# Для аннотации типов
from typing import Tuple

# Устанавливаем размеры окна
WIDTH = 800
HEIGHT = 600

# Как часто должны генерироваться монеты (мс)
coin_countdown = 2500
coin_interval = 100

# Сколько монет должно быть на экране, чтобы игра закончилась
COIN_COUNT = 10

# Определяем спрайт для игрока
class Player(pygame.sprite.Sprite):
    def __init__(self):
        """Инициализирует спрайт игрока"""
        super(Player, self).__init__()

        # Получаем изображение персонажа
        player_image = str(
            Path.cwd() / "pygame" / "images" / "alien_green_stand.png"
        )
        # Загружаем изображение, настраиваем альфа канал для прозрачности
        self.surf = pygame.image.load(player_image).convert_alpha()
        # Сохраняем в прямоугольнике, чтобы перемещать объект
        self.rect = self.surf.get_rect()

    def update(self, pos: Tuple):
        """Обновляет позицию персонажа

        Аргументы:
            pos {Tuple} -- (X,Y) позиция для движения персонажа
        """
        self.rect.center = pos

# Определяем спрайт для монет
class Coin(pygame.sprite.Sprite):
    def __init__(self):
        """Инициализирует спрайт монеты"""
        super(Coin, self).__init__()

        # Получаем изображение монеты
        coin_image = str(Path.cwd() / "pygame" / "images" / "coin_gold.png")

        # Загружаем изображение, настраиваем альфа канал для прозрачности
        self.surf = pygame.image.load(coin_image).convert_alpha()

        # Задаем стартовую позицию, сгенерированную случайным образом
        self.rect = self.surf.get_rect(
            center=(
                randint(10, WIDTH - 10),
                randint(10, HEIGHT - 10),
            )
        )

# Инициализируем движок
pygame.init()

# Настраиваем окно
screen = pygame.display.set_mode(size=[WIDTH, HEIGHT])

# Скрываем курсор мыши
pygame.mouse.set_visible(False)

# Запускаем часы для фиксации времени фрейма
clock = pygame.time.Clock()

# Создаем событие для добавления монеты
ADDCOIN = pygame.USEREVENT + 1
pygame.time.set_timer(ADDCOIN, coin_countdown)

# Настраиваем список монет
coin_list = pygame.sprite.Group()

# Инициализируем счет
score = 0

# Определяем звук для столкновения с монетой 
coin_pickup_sound = pygame.mixer.Sound(
    str(Path.cwd() / "pygame" / "sounds" / "coin_pickup.wav")
)

# Создаем спрайт героя и устанавливаем на заданную позицию
player = Player()
player.update(pygame.mouse.get_pos())

# Цикл событий
running = True
while running:

    # Проверяем, нажал ли пользователь кнопку закрытия окна
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # Определяем, нужно ли добавлять новую монету
        elif event.type == ADDCOIN:
            # Добавляем новую монету
            new_coin = Coin()
            coin_list.add(new_coin)

            # Ускоряем игру, если на экранее менее 3 монет
            if len(coin_list) < 3:
                coin_countdown -= coin_interval
            # Ограничиваем скорость
            if coin_countdown < 100:
                coin_countdown = 100

            # Останавливаем предыдущий таймер
            pygame.time.set_timer(ADDCOIN, 0)

            # Запускаем новый таймер
            pygame.time.set_timer(ADDCOIN, coin_countdown)

    # Обновляем позицию персонажа
    player.update(pygame.mouse.get_pos())

    # Проверяем, столкнулся ли игрок с монетой и удаляем, если это так
    coins_collected = pygame.sprite.spritecollide(
        sprite=player, group=coin_list, dokill=True
    )
    for coin in coins_collected:
        # Каждая монета стоит 10 очков
        score += 10
        # Воспроизводим звук для монеты
        coin_pickup_sound.play()

    # Проверяем, не слишком ли много монет
    if len(coin_list) >= COIN_COUNT:
        # Если монет много, останавливаем игру
        running = False

    # Указываем цвет фона
    screen.fill((255, 170, 164))

    # Рисуем следующие монеты
    for coin in coin_list:
        screen.blit(coin.surf, coin.rect)

    # Отрисовываем персонажа
    screen.blit(player.surf, player.rect)

    # Выводим текущий счет
    score_font = pygame.font.SysFont("any_font", 36)
    score_block = score_font.render(f"Score: {score}", False, (0, 0, 0))
    screen.blit(score_block, (50, HEIGHT - 50))

    # Отображаем всё на экране
    pygame.display.flip()

    # Скорость обновления - 30 кадров в секунду
    clock.tick(30)

# Готово! Печатаем итоговый результат
print(f"Game over! Final score: {score}")

# Делаем курсор мыши вновь видимым
pygame.mouse.set_visible(True)

# Выходим из игры
pygame.quit()

    

Спрайты в Pygame предоставляют лишь базовую функциональность — в нашем коде мы их расширяем, создавая подклассы для персонажа (Player) и монет (Coin). Объекты спрайтов сохраняются в self.surf и позиционируются с помощью свойства self.rect.

Вывод монет. Чтобы добавлять монеты на экран через равные промежутки времени, мы используем таймер time.set_timer(), отсчитывающий время до события в миллисекундах (coin_countdown). Добавлению монет соответствует событие ADDCOIN. Событие создает новый объект Coin и добавляет его в coin_list. Далее проверяется количество монет на экране. Если монет меньше трех, то coin_countdown уменьшается. Предыдущий таймер останавливается и запускается новый.

Движение персонажа. При движении игрок сталкивается с монетами и собирает их. При этом мы удаляем соответствующий объект из coin_list, обновляем счёт и воспроизводим звук. Автор игры также должен помнить об очистке экрана, отрисовке спрайтов в правильном порядке и отображении счёта.

Заключение по Pygame

Pygame — мощная и хорошо зарекомендовавшая себя библиотека, но у неё есть недостатки. Автор игры должен самостоятельно оформить базовое поведение спрайтов, реализовать игровые циклы и основные обработчики событий. Как вы увидите далее, более современные игровые движки позволяют достичь аналогичных результатов при меньшем объёме выполняемой работы.

Pygame Zero

С одним задачами Pygame справляется хорошо, в других — сказывается возраст библиотеки. Для новичков в написании игр есть вариант получше — Pygame Zero. Эта библиотека разработана для образовательных задач, поэтому текст документации будет понятен даже для новичков в программировании. Кроме того, есть подробное пошаговое руководство.

Установка Pygame Zero

Pygame Zero можно установить, как и любую другую библиотеку Python:

        (venv) $ python -m pip install pgzero

    

Базовый пример на Pygame Zero

Pygame Zero автоматизирует многие вещи, которые программистам приходится описывать вручную при использовании стандартного движка Pygame. По умолчанию Pygame Zero предоставляет создателю игры:

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

В результате код базовой программы Pygame Zero оказывается более кратким, чем на Pygame.

💡 Чтобы не «раздувать» текст статьи, мы отсылаем читателей посмотреть этот и следующие примеры кода мы в упомянутому выше репозиторию.

Отрисовка окна. Pygame Zero автоматически распознает, что константы WIDTH и HEIGHT относятся к размеру окна. Pygame Zero также предоставляет базовый код для закрытия окна, так что закрытие окна не нужно описывать в обработчике.

Отрисовка фигур и текста. Поскольку Pygame Zero основан на Pygame, он наследует часть кода для отрисовки фигур, но вывод текста выглядит проще и занимает один вызов вместо трех для обычного Pygame.

        screen.draw.text(
        f"Score: {score}",
        (50, HEIGHT - 50),
        fontsize=48,
        color="black",
    )

    

Запуск программ Pygame Zero осуществляется из командной строки с помощью команды:

        (venv) $ python pygame_zero/pygame_zero_basic.py

    

Продвинутый вариант игры на Pygame Zero

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

🐍🕹️ Как написать игру на Python: 5 игровых движков

Спрайты в Pygame Zero называются Actors. Их характеристики требуют некоторых пояснений, так как эти сведения используются в коде примера:

  1. Для каждого Actor задаются, как минимум, изображение и положение.
  2. Все изображения должны располагаться во вложенной папке с именем ./images/. Названия файлов должны содержать лишь строчные буквы, цифры или символы подчеркивания.
  3. При ссылке на изображение используется имя файла без расширения. Например, если изображение называется alien.png, то в программе на него ссылаются строкой "alien" .

Вывод монет через равные промежутки времени производится с помощью метода clock.schedule(). Метод принимает вызываемую функцию (в нашем случае add_coin) и количество секунд перед вызовом самой функции. Запускаемая функция add_coin() создает объект класса Actor и добавляет спрайт в глобальный список видимых монет.

Перемещение персонажа задействует обработчик события on_mouse_move(). В исходном положении спрайт персонажа находится в центре экрана. Положение мыши хранится в глобальной переменной.

Столкновение с монетой приводит к воспроизведению звука и увеличению счёта. Удаляемая монета добавляется в список coin_remove_list. При обработке столкновений мы проверяем, не слишком ли много монет сейчас находится на экране. Если это так, мы заканчиваем игру, прекращаем создавать новые монеты и выводим окончательный счёт игры.

Обновление состояний. Функция update() вызывается Pygame Zero один раз за кадр. Мы используем её, чтобы перемещать объекты класса Actor и обновлять состояния игровых объектов. Также один раз за кадр для отрисовки вызывается функция draw().

Заключение по Pygame Zero

Реализация игры на Pygame Zero заняла 152 строки кода вместо 182 строк на обычном Pygame. Хотя количество строк сопоставимо, версия на Pygame Zero получилась более ясной в плане кода и проще для понимания и дополнения.

Arcade

Arcade — движок Python для создания игр с современными графикой и звуком, разработанный профессором Полом Крэйвеном из Симпсон-колледжа (Айова, США).

Arcade базируется на мультимедийной библиотеке pyglet и выгодно отличается, как от Pygame, так и от Pygame Zero:

  • поддерживает современную OpenGL-графику;
  • поддерживает аннотации типов Python 3;
  • умеет анимировать с анимированными спрайтами;
  • имеет согласованные имена команд, функций и параметров;
  • поощряет отделение игровой логики от кода, обеспечивающего отображение;
  • сокращает использование шаблонного кода;
  • имеет поддерживаемую и актуальную документацию, в том числе несколько учебных пособий и полные примеры игр на Python;
  • имеет встроенные физические движки для игр с видом сверху и игр-платформеров.

Arcade продолжает развиваться и хорошо поддерживается сообществом, а автор быстро реагирует на сообщения об ошибках.

Установка Arcade

Чтобы установить Arcade и его зависимости, используйте соответствующую команду pip:

        (venv) $ python -m pip install arcade

    

Есть также инструкции по установке для Windows, macOS и Linux. При желании можно собрать движок из исходного кода.

Базовый пример на Arcade

🐍🕹️ Как написать игру на Python: 5 игровых движков

Начнем с базового примера с фигурами и текстом. Чтобы запустить код, используйте следующую команду:

        (venv) $ python arcade/arcade_basic.py

    

Начало координат (0, 0) расположено в левом нижнем углу экрана. Это отличает Arcade от большинства игровых движков, в которых начало координат расположено в левом верхнем углу.

Arcade — это объектно-ориентированная библиотека. Для подклассов игр используется класс arcade.Window, для настройки игры вызывается super().__init().

Отрисовка всего что есть на экране производится обработчиком событий .on_draw() . Обработчик стартует с вызова .start_render(), который сообщает Arcade подготовить окно для рисования. Напоминает pygame.flip() для отрисовки в Pygame.

Фигуры и цвета. Каждый из основных методов рисования фигур в Arcade начинается с draw_*. Arcade умеет отрисовывать множество разнообразных фигур и сотни именованных цветов из пакета arcade.color. Также можно использовать кортежи RGB или RGBA.

Продвинутый вариант игры на Arcade

Чтобы показать, чем Arcade отличается от других игровых движков, запрограммируем ту же игру с монетами, что и раньше.

Инициализация. Объектно-ориентированный характер Arcade позволяет отделить инициализацию игры от инициализации отдельного уровня: игра инициализируется методом .__init__(), а уровни настраиваются и перезапускаются с помощью .setup(). Это отличный шаблон для использования даже в играх с одним уровнем, как в нашем случае.

Спрайты создаются в виде объекта класса arcade.Sprite, которому задан путь к изображению — Arcade поддерживает pathlib-пути.

Создание монет планируется с помощью arcade.schedule() и вызова self.add_coin() через равные промежутки времени. Метод .add_coin() создает новый спрайт монеты в случайном месте и добавляет его в список.

Перемещение персонажа мышью реализуется с помощью метода .on_mouse_motion(). Метод arcade.clamp() гарантирует, что координаты центра страйпа не выйдут за пределы экрана.

Столкновение с монетой обрабатывается методом .on_update(). Метод arcade.check_for_collision_with_list() возвращает список всех спрайтов, которые столкнулись с указанным спрайтом. Код проходит по этому списку, увеличивает счет и воспроизводит звук. Метод .on_update() проверяет, не слишком ли много монет сейчас есть на экране.

Заключение по Arcade

Реализация Arcade так же удобна для чтения и хорошо структурирована, как и код для Pygame Zero. Однако программный код занимает больше места — 194 строки. Причина в том, что в Arcade заложены возможности, которые лучше реализуются в более крупных играх:

  • анимированные спрайты;
  • встроенные физические движки;
  • поддержка сторонних игровых карт;
  • системы работы с частицами и шейдирование.

Авторы игр, пришедшие в Arcade из Pygame Zero обнаружат здесь знакомую структуру, но более мощные и продвинутые функции.

adventurelib

Мир игр полон самых различных жанров. Бывают и такие игры, как например, Zork, в которых основой игрового повествования является текст. Такой тип игр ещё называют Interactive Fiction. Для создания текстовых игр на Python существует движок adventurelib. Библиотека отлично подойдет для тех, кто хочет создать текстовую игру без необходимости писать парсер языка.

Установка adventurelib

adventurelib доступен на PyPI и может быть установлен с помощью соответствующей команды pip :

        (venv) $ python -m pip install adventurelib

    

Библиотеку также можно установить из репозитория GitHub, сохранив в той же папке, что и ваша игра, и использовать напрямую.

Базовые концепции adventurelib

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

Чтобы запустить код из примера, используйте следующую команду:

        (venv) $ python adventurelib/adventurelib_basic.py

    

Декоратор @when. Текстовые игры в значительной степени полагаются на синтаксический анализ пользовательского ввода. Библиотека определяет текст, который вводит игрок, как команду (command) **и предоставляет для описания команд декоратор @when(). Например, декоратор @when("look") добавляет команду в список допустимых команд и связывает с ней функцией look(). Всякий раз, когда игрок набирает look, adventurelib вызывает соответствующую функцию. Для удобства игроков и разработчиков команды нечувствительны к регистру.

Несколько команд могут использовать одну и ту же функцию. Функция go() декорирована девятью различными командами, чтобы игрок мог перемещаться по игровому миру. В скриншоте ниже есть три из них: south, east, north.

🐍🕹️ Как написать игру на Python: 5 игровых движков

Предметы. В текстовых играх часто есть предметы, которые необходимо собирать, чтобы открывать новые области игры или решать головоломки. Или это могут быть персонажи, с которыми игрок может взаимодействовать. Движок adventurelib предоставляет класс Item для определения и предметов, и персонажей по их именам и псевдонимам.

Конструктор Item()принимает одну или несколько строк. Первая строка — имя предмета, которое используется при печати. Остальные строки используются в качестве псевдонимов, чтобы игроку не приходилось вводить полное имя объекта.

Взаимодействие с предметами. Часто команды, которые вводит игрок, направлены на конкретный предмет. Разработчик игры может задать дополнительный контекст команды. Для этого в описании декоратора @when() используются слова, написанные заглавными буквами.

💡 Пример контекста команды можно увидеть в функции look_at(), которая принимает строковый параметр с именем item. В декораторах этой функции, определяющих команды look at и inspect, слово ITEM выступает в качестве переменной-заполнителя текста, следующего за командой. Этот текст и передается функции look_at() в качестве входного значения. Например, если игрок введет look at book, то item внутри функции получит строковое значение "book".

Реплики. Для вывода реплик используйте функцию say(), которая отлично справляется с выводом многострочного текста. Пример использования есть в теле функции look() — всякий раз, когда игрок набирает look, функция say() выводит в консоль описание текущей комнаты.

Комнаты. Для определения различных областей игрового мира библиотека adventurelib предоставляет класс Room. При создании комнаты конструктору Room() передается описание комнаты и связь с другими комнатами с помощью свойств .north, .south, .east и .west.

Препятствие. Мы также создаем ограничение, указав, что между гостиной и верандой есть запертая дверь living_room.locked. Чтобы открыть эту дверь, игроку потребуется найти ключ. В исходном состоянии ключ находится в спальне.

Ключ имеет не только имя и псевдонимы, но и метод, с помощью которого используется в игре. Метод key.use_item вызывается, когда игрок пытается использовать предмет, набрав строку use key.

Коллекции предметов, таких как инвентарь игрока или предметы на полу комнаты, хранятся в объекте класса Bag. Эти объекты-коллекции позволяют добавлять, удалять предметы или проверять содержимое.

В нашем коде определены четыре Bag-объекта: три для каждой комнаты и один для инвентаря, собираемого игроком. Для добавления предметов в инвентарь используется функция get(), Чтобы взять какой-либо предмет из имеющегося инвентаря — функция take(). При переносе предмета в инвентарь, он удаляется из Bag-объекта комнаты.

Продвинутый вариант игры с использованием adventurelib

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

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

В игре есть несколько областей:

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

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

Программный код игры разбит на несколько файлов:

  • adventurelib_game_rooms.py описывает комнаты и области;
  • adventurelib_game_items.py определяет предметы и их атрибуты;
  • adventurelib_game_characters.py описывает персонажей, с которыми может взаимодействовать игрок;
  • adventurelib_game.py собирает всё вместе, добавляет команды и запускает игру.

Игру можно запустить с помощью следующей команды:

        (venv) $ python adventurelib/adventurelib_game.py

    

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

🐍🕹️ Как написать игру на Python: 5 игровых движков

Каждая область имеет свои свойства:

  • название, краткое и подробное описания;
  • предметы и персонажи;
  • заблокированные выходы;
  • указание на то, был ли уже игрок в этой области или нет.

Используем ООП. Чтобы быть уверенными, что каждая область имеет собственный экземпляр каждого из этих свойств, мы создадим в файле у подкласс Room с именем GameArea. Предметы в каждой комнате хранятся в объекте класса Bag с именем items, а персонажи — в characters.

Игровые предметы определены в adventurelib_game_items.py как объекты типа Item(). Одни игровые предметы необходимы для завершения игры, в то время как другие разнообразят геймплей. Некоторые элементы имеют определенные свойства, уникальные для данного элемента. Например, у мечей wooden_sword и steel_sword есть свойство, показывающее наносимый ими урон и поддерживаемые магические бонусы.

Взаимодействие с персонажами помогает продвигать игровой сюжет. Персонажи определены в adventurelib_game_characters.py. У каждого героя, как и у каждого предмета, есть связанные с ним универсальные свойства, такие как описание и приветствие, используемое, когда игрок встречает персонажа в первый раз.

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

Примеры контекста. В какой-то момент игрок впервые сталкивается со старейшиной Бэрроном (Elder Barron). Когда игрок набирает talk to elder, контекст устанавливается по свойству elder.context. Приветствие старейшины заканчивается вопросом требующим ответа «да» или «нет». Если игрок вводит yes, то в adventurelib_game.py запускается обработчик команды, заданный декоратором @when("yes", context="elder").

🐍🕹️ Как написать игру на Python: 5 игровых движков

Позже при разговоре игрока с кузнецом добавляется второй уровень контекста, отражающий возможную покупку оружия. За счет этого программа понимает, что одна и ту же команда "yes" приводит к разным последствиям.

Запрет действий в контексте. Вы также можете проверить, как помогает контекст в обработчике команд. Например, игрок не может просто выйти из боя с великаном, закончив разговор. Обработчик команды "goodbye" проверяет, находится ли игрок в контексте "giant", который вводится, когда он начинает сражаться. Если контекст в силе, прекращать разговор нельзя, — это смертельный бой!

Команды, не имеющие совпадений, обрабатываются функцией no_command_matches(). Её можно использовать для диалогов, требующих конкретного ответа. Так, когда волшебник просит игрока разгадать загадку, создается контекст wizard.riddle. Неправильный ответ приводит к прекращению разговора.

Заключение по adventurelib

Создать полноценную текстовую приключенческую игру непросто, но adventurelib берёт на себя основную рутину, связанную с обработкой локаций, предметов, героев, а также их поведением в зависимости от истории взаимодействий.

Ren’Py

Наследником текстовых игр являются современные игры в стиле визуальных романов (новелл). В таких играх наибольшее значение также играют повествование и сюжет, но игровой опыт разнообразнее за счет картинок, визуальных эффектов и звуков. Для создания подобных игр на Python используется Ren’Py. Название движка образовано от японского слова, означающего романтическую любовь.

Строго говоря, Ren’Py не является классической библиотекой Python, которую можно установить посредством pip install. Игры Ren’Py создаются и запускаются с помощью лаунчера, входящего в состав SDK Ren’Py, в котором есть и редактор игр, и собственный язык сценариев. Однако так как Ren’Py основан на Pygame, с ним можно работать и с помощью Python.

Установка Ren’Py

Ren’Py SDK доступен на Windows, Mac и Linux, пакет для соответствующей платформы можно скачать на официальном сайте. После установки перейдите в папку, содержащую SDK, и запустите Ren’Py Launcher.

🐍🕹️ Как написать игру на Python: 5 игровых движков

Базовые концепции Ren’Py

В той же программе можно начать новый проект, это создаст необходимую структуру файлов и папок. Хотя для запуска игр требуется Ren’Py Launcher, для редактирования кода можно использовать любой удобный редактор.

🐍🕹️ Как написать игру на Python: 5 игровых движков

Сценарии игр Ren’Py хранятся в файлах с расширением .rpy , написанных на специальном языке Ren’Py. Файлы хранятся в папке game/ внутри папки проекта.

Для нового проекта Ren’Py создаёт следующие сценарии, которые можно сразу же использовать и редактировать:

  • gui.rpy определяет внешний вид всех элементов пользовательского интерфейса;
  • options.rpy определяет изменяемые параметры для настройки игры;
  • screens.rpy описывает стили диалогов, меню и других элементов вывода информации;
  • script.rpy — место, где вы начинаете писать игру.

Чтобы запустить примеры игры из материалов этого руководства, следуйте инструкции:

  1. Запустите Ren’Py Launcher.
  2. Нажмите Preferences, затем Projects Directory.
  3. Измените Projects Directory на папку renpy из загруженного репозитория с примерами.
  4. Нажмите Return, чтобы вернуться на главную страницу Ren’Py Launcher.

В списке проектов слева вы увидите basic_game и giant_quest_game. Выберите, что хотите запустить и нажмите Launch Project.

Ниже мы рассмотрим script.rpy для basic_game.

Метки (labels) **определяют точки входа в историю, а также используются для запуска новых сцен и альтернативных путей прохождения истории. Все игры Ren’Py начинают работать с метки start:, которая может появляться в любом сценарии.

💡 Вы также можете использовать метки для определения фоновых изображений, настройки переходов между сценами и управления внешним видом персонажей. В примере вторая сцена начинается со строки с меткой check_room:.

Персонажей можно определить просто назвав их в истории или указав в начале сценария. Так мы определили главного персонажа, его маму и брата по имени Кевин. Оператор define инициализирует три переменные класса Characters.

Медиафайлы. Как и Pygame Zero, Ren’Py требует, чтобы все изображения и звуки, используемые в игре, находились в определенных папках — соответственно game/images/ и game/audio/. В сценарии игры к ним можно обращаться по имени файла без расширения.

💡 Пример. Когда ваш персонаж открывает глаза и впервые видит спальню, ключевое слово scene очищает экран, а затем показывает изображение спальни, хранящееся в day.png. Ren’Py поддерживает формы файлов изображений JPG, WEBP и PNG.

Ветвления сюжета. Игра не была бы игрой, если бы в ней нельзя было принимать решения. В Ren’Py возможности для выбора оформляются в виде меню. В ответ на выбор игра переходит к заданной метке, изменяет изображение и воспроизводит заданные звуки. В примере такой выбор возникает, когда главный персонаж понимает, что забыл свой телефон.

Продвинутый пример игры на Ren’Py

Теперь мы немного знакомы с движком. Давайте реализуем продвинутый вариант с тем же сюжетом, что использовали для adventurelib.

Персонажи и локации. В игре есть несколько персонажей: кузнец, волшебник и великан. И несколько локаций: родная деревушка, деревня оружейника, ведущая к волшебнику дорожка и пещера с грабителем-великаном.

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

  • script.rpy, где начинается игра;
  • town.rpy с историей близлежащей деревни;
  • path.rpy , который описывает тропу между деревнями;
  • giant.rpy, содержащий логику битвы с великаном.

Встреча с волшебником оставлена в качестве упражнения.

Описание объектов. Как и в предыдущем примере, в начале script.rpy мы определяем объекты с помощью Character(). Далее мы задаем несколько изображений, на которые ссылаемся позже для использования в качестве фона и отображения объектов. Использование специального синтаксиса позволяет назначать изображениям короткие внутренние имена.

Активный инвентарь. Чтобы показать, какое оружие сейчас активно, мы показываем его изображение в углу экрана. Для этого мы используем команду show с модификатором with moveinleft. Важно помнить, что при смене сцены экран очищается, поэтому нужно запускать команду повторно.

Смена оружия. При входе в город в town.rpy, вы встречаете приветствующего вас кузнеца:

🐍🕹️ Как написать игру на Python: 5 игровых движков

Кузнец предлагает улучшить ваше оружие. Если вы решите это сделать, вы обновите значения для current_weapon и характеристики оружия.

Операторы Python. Строки, начинающиеся с символа $, интерпретируются Ren’Py как операторы Python. Это позволяет прописывать в сценарии произвольный код Python. Обновление current_weapon и статистики оружия выполняется с помощью трех операторов Python, которые изменяют значения переменных по умолчанию, определенных в начале script.rpy.

Вы также можете определить большой блок кода Python, используя слово python:, как показано в файле giant.rpy, начиная со строки 41.

Сцена битвы управляется функцией fight_giant() и игровым циклом с переменной battle_over. Выбор игрока сражаться или бежать отображается с помощью метода renpy.display_menu(). Если игрок сражается, то великану наносится случайное количество урона и корректируются его очки здоровья. Если великан остается в живых, он может атаковать в ответ аналогичным образом. Обратите внимание, что у великана есть шанс промахнуться, в то время как игрок всегда попадает в цель. Бой продолжается до тех пор, пока у игрока или великана не закончится здоровье, либо пока игрок не сбежит.

Используемый код очень похож на тот, который мы использовали для описания битвы в adventurelib. Пример демонстирирует, как вы можете интегрировать код Python в Ren’Py без необходимости переводить его в сценарий Ren’Py.

Если вы заинтересовались движком, обратитесь к документации Ren’Py для получения более подробной информации.

Другие популярные игровые движки на Python

Описанная в статье пятерка библиотек — лишь небольшая выборка из множества доступных игровых движков на Python. Среди десятков доступных мы отметим также следующие:

  • Wasabi 2D разработан командой Pygame Zero. Это современная среда, построенная на moderngl , которая автоматизирует рендеринг, предоставляет готовые решения для анимационных эффектов, имеет встроенные эффекты и использует собственную модель игровых событий.
  • Panda 3D — платформа с открытым исходным кодом для создания 3D-игр и трехмерной визуализации. Panda 3D переносится на разные платформы, поддерживает несколько типов ресурсов, интегрируется с многочисленными сторонними библиотеками и обеспечивает встроенное профилирование.
  • Ursina построена на основе Panda 3D и предоставляет специальный движок для разработки игр, который упрощает многие аспекты Panda 3D. На момент написания статьи Ursina хорошо поддерживается и документируется.
  • PursuedPyBear позиционируется как образовательная библиотека с системой управления сценами, анимированными спрайтами и низким входным барьером.

Если вы знаете о других хороших движках на Python, не стесняйтесь рассказать в комментариях!

Источники контента для игр

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

Разработчики-одиночки могут посчитать этот аспект разработки игр пугающим. Но к счастью, существует множество различных источников игровых ресурсов:

  • OpenGameArt.org предлагает широкий спектр артов, музыки, фонов, значков и других ресурсов для двумерных и трехмерных игр. Большинство файлов находятся в свободном доступе.
  • Kenney.nl содержит набор разнообразных бесплатных и платных ресурсов.
  • Itch.io — торговая площадка для создателей цифровых продуктов, ориентированных на независимую разработку игр. Здесь можно найти ресурсы практически для любых целей: и бесплатные, и платные, и даже готовые игры.

Все ресурсы, используемые в играх из этого туториала, соответствуют лицензионным требованиям создателей.

Заключение

Поздравляем — теперь вы знакомы с основами дизайна игр на Python! Благодаря стараниям GameDev-сообщества писать качественные компьютерные игры на Python сегодня намного проще, чем раньше.

Надеемся, что теперь вы можете выбрать подходящий игровой движок и написать собственную игру.

***

Материалы по теме

  • 🐍 Пишем Тетрис на Python с помощью библиотеки Pygame
  • 9 идей для начинающих программистов по созданию игр-клонов

Прежде чем мы начнём программировать что-то полезное на Python, давайте закодим что-нибудь интересное. Например, свою игру, где нужно не дать шарику упасть, типа Арканоида. Вы, скорее всего, играли в детстве во что-то подобное, поэтому освоиться будет просто.

Логика игры

Есть игровое поле — простой прямоугольник с твёрдыми границами. Когда шарик касается стенки или потолка, он отскакивает в другую сторону. Если он упадёт на пол — вы проиграли. Чтобы этого не случилось, внизу вдоль пола летает платформа, а вы ей управляете с помощью стрелок. Ваша задача — подставлять платформу под шарик как можно дольше. За каждое удачное спасение шарика вы получаете одно очко.

Алгоритм

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

  • игра начинается;
  • шарик начинает двигаться;
  • если нажаты стрелки влево или вправо — двигаем платформу;
  • если шарик коснулся стенок, потолка или платформы — делаем отскок;
  • если шарик коснулся платформы — увеличиваем счёт на единицу;
  • если шарик упал на пол — выводим сообщение и заканчиваем игру.

Хитрость в том, что всё это происходит параллельно и независимо друг от друга. То есть пока шарик летает, мы вполне можем двигать платформу, а можем и оставить её на месте. И когда шарик отскакивает от стен, это тоже не мешает другим объектам двигаться и взаимодействовать между собой.

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

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

По коням, пишем на Python

Для этого проекта вам потребуется установить и запустить среду Python. Как это сделать — читайте в нашей статье.

Начало программы

Чтобы у нас появилась графика в игре, используем библиотеку Tkinter. Она входит в набор стандартных библиотек Python и позволяет рисовать простейшие объекты — линии, прямоугольники, круги и красить их в разные цвета. Такой простой Paint, только для Python.

Чтобы создать окно, где будет видна графика, используют класс Tk(). Он просто делает окно, но без содержимого. Чтобы появилось содержимое, создают холст — видимую часть окна. Именно на нём мы будем рисовать нашу игру. За холст отвечает класс Canvas(), поэтому нам нужно будет создать свой объект из этого класса и дальше уже работать с этим объектом.

Если мы принудительно не ограничим скорость платформы, то она будет перемещаться мгновенно, ведь компьютер считает очень быстро и моментально передвинет её к другому краю. Поэтому мы будем искусственно ограничивать время движения, а для этого нам понадобится модуль Time — он тоже стандартный.

Последнее, что нам глобально нужно, — задавать случайным образом начальное положение шарика и платформы, чтобы было интереснее играть. За это отвечает модуль Random — он помогает генерировать случайные числа и перемешивать данные.

Запишем всё это в виде кода на Python:

# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке 
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable 
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты 
canvas.pack()
# обновляем окно с холстом
tk.update()

Мы подключили все нужные библиотеки, сделали и настроили игровое поле. Теперь займёмся классами.

Шарик

Сначала проговорим словами, что нам нужно от шарика. Он должен уметь:

  • задавать своё начальное положение и направление движение;
  • понимать, когда он коснулся платформы;
  • рисовать сам себя и понимать, когда нужно отрисовать себя в новом положении (например, после отскока от стены).

Этого достаточно, чтобы шарик жил своей жизнью и умел взаимодействовать с окружающей средой. При этом нужно не забыть о том, что каждый класс должен содержать конструктор — код, который отвечает за создание нового объекта. Без этого сделать шарик не получится. Запишем это на Python:

# Описываем класс Ball, который будет отвечать за шарик 
class Ball:
    # конструктор — он вызывается в момент создания нового объекта на основе этого класса
    def __init__(self, canvas, paddle, score, color):
        # задаём параметры объекта, которые нам передают в скобках в момент создания
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        # цвет нужен был для того, чтобы мы им закрасили весь шарик
        # здесь появляется новое свойство id, в котором хранится внутреннее название шарика
        # а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
        self.id = canvas.create_oval(10,10, 25, 25, fill=color)
        # помещаем шарик в точку с координатами 245,100
        self.canvas.move(self.id, 245, 100)
        # задаём список возможных направлений для старта
        starts = [-2, -1, 1, 2]
        # перемешиваем его 
        random.shuffle(starts)
        # выбираем первый из перемешанного — это будет вектор движения шарика
        self.x = starts[0]
        # в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
        self.y = -2
        # шарик узнаёт свою высоту и ширину
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        # свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
        self.hit_bottom = False
    # обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
    def hit_paddle(self, pos):
        # получаем кординаты платформы через объект paddle (платформа)
        paddle_pos = self.canvas.coords(self.paddle.id)
        # если координаты касания совпадают с координатами платформы
        if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
            if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
                # увеличиваем счёт (обработчик этого события будет описан ниже)
                self.score.hit()
                # возвращаем метку о том, что мы успешно коснулись
                return True
        # возвращаем False — касания не было
        return False
    # обрабатываем отрисовку шарика
    def draw(self):
        # передвигаем шарик на заданные координаты x и y
        self.canvas.move(self.id, self.x, self.y)
        # запоминаем новые координаты шарика
        pos = self.canvas.coords(self.id)
        # если шарик падает сверху  
        if pos[1] <= 0:
            # задаём падение на следующем шаге = 2
            self.y = 2
        # если шарик правым нижним углом коснулся дна
        if pos[3] >= self.canvas_height:
            # помечаем это в отдельной переменной
            self.hit_bottom = True
            # выводим сообщение и количество очков
            canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
        # если было касание платформы
        if self.hit_paddle(pos) == True:
            # отправляем шарик наверх
            self.y = -2
        # если коснулись левой стенки
        if pos[0] <= 0:
            # движемся вправо
            self.x = 2
        # если коснулись правой стенки
        if pos[2] >= self.canvas_width:
            # движемся влево
            self.x = -2

Платформа

Сделаем то же самое для платформы — сначала опишем её поведение словами, а потом переведём в код. Итак, вот что должна уметь платформа:

  • двигаться влево или вправо в зависимости от нажатой стрелки;
  • понимать, когда игра началась и можно двигаться.

А вот как это будет в виде кода:

#  Описываем класс Paddle, который отвечает за платформы
class Paddle:
    # конструктор
    def __init__(self, canvas, color):
        # canvas означает, что платформа будет нарисована на нашем изначальном холсте
        self.canvas = canvas
        # создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя 
        self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
        # задаём список возможных стартовых положений платформы
        start_1 = [40, 60, 90, 120, 150, 180, 200]
        # перемешиваем их
        random.shuffle(start_1)
        # выбираем первое из перемешанных
        self.starting_point_x = start_1[0]
        # перемещаем платформу в стартовое положение
        self.canvas.move(self.id, self.starting_point_x, 300)
        # пока платформа никуда не движется, поэтому изменений по оси х нет
        self.x = 0
        # платформа узнаёт свою ширину
        self.canvas_width = self.canvas.winfo_width()
        # задаём обработчик нажатий
        # если нажата стрелка вправо — выполняется метод turn_right()
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        # если стрелка влево — turn_left()
        self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        # пока игра не началась, поэтому ждём
        self.started = False
        # как только игрок нажмёт Enter — всё стартует
        self.canvas.bind_all('<KeyPress-Return>', self.start_game)
    # движемся вправо 
    def turn_right(self, event):
        # будем смещаться правее на 2 пикселя по оси х
        self.x = 2
    # движемся влево
    def turn_left(self, event):
        # будем смещаться левее на 2 пикселя по оси х
        self.x = -2
    # игра начинается
    def start_game(self, event):
        # меняем значение переменной, которая отвечает за старт
        self.started = True
    # метод, который отвечает за движение платформы
    def draw(self):
        # сдвигаем нашу платформу на заданное количество пикселей
        self.canvas.move(self.id, self.x, 0)
        # получаем координаты холста
        pos = self.canvas.coords(self.id)
        # если мы упёрлись в левую границу 
        if pos[0] <= 0:
            # останавливаемся
            self.x = 0
        # если упёрлись в правую границу 
        elif pos[2] >= self.canvas_width:
            # останавливаемся
            self.x = 0

Счёт

Можно было не выделять счёт в отдельный класс и каждый раз обрабатывать вручную. Но здесь реально проще сделать класс, задать нужные методы, чтобы они сами потом разобрались, что и когда делать.

От счёта нам нужно только одно (кроме конструктора) — чтобы он правильно реагировал на касание платформы, увеличивал число очков и выводил их на экран:

#  Описываем класс Score, который отвечает за отображение счетов
class Score:
    # конструктор
    def __init__(self, canvas, color):
        # в самом начале счёт равен нулю
        self.score = 0
        # будем использовать наш холст
        self.canvas = canvas
        # создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
        self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
    # обрабатываем касание платформы
    def hit(self):
        # увеличиваем счёт на единицу
        self.score += 1
        # пишем новое значение счёта 
        self.canvas.itemconfig(self.id, text=self.score)
        

Игра

У нас всё готово для того, чтобы написать саму игру. Мы уже провели необходимую подготовку всех элементов, и нам остаётся только создать конкретные объекты шарика, платформы и счёта и сказать им, в каком порядке мы будем что делать.

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

Посмотрите, как лаконично выглядит код непосредственно самой игры:

# создаём объект — зелёный счёт 
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик 
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна 
while not ball.hit_bottom:
    # если игра началась и платформа может двигаться
    if paddle.started == True:
        # двигаем шарик
        ball.draw()
        # двигаем платформу
        paddle.draw()
    # обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
    tk.update_idletasks()
    # обновляем игровое поле, и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
    tk.update()
    # замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
    time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)
# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке 
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable 
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить. Попробуйте 🙂
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты 
canvas.pack()
# обновляем окно с холстом
tk.update()
# Описываем класс Ball, который будет отвечать за шарик 
class Ball:
    # конструктор — он вызывается в момент создания нового объекта на основе этого класса
    def __init__(self, canvas, paddle, score, color):
        # задаём параметры объекта, которые нам передают в скобках в момент создания
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        # цвет нужен был для того, чтобы мы им закрасили весь шарик
        # здесь появляется новое свойство id, в котором хранится внутреннее название шарика
        # а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
        self.id = canvas.create_oval(10,10, 25, 25, fill=color)
        # помещаем шарик в точку с координатами 245,100
        self.canvas.move(self.id, 245, 100)
        # задаём список возможных направлений для старта
        starts = [-2, -1, 1, 2]
        # перемешиваем его 
        random.shuffle(starts)
        # выбираем первый из перемешанного — это будет вектор движения шарика
        self.x = starts[0]
        # в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
        self.y = -2
        # шарик узнаёт свою высоту и ширину
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        # свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
        self.hit_bottom = False
    # обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
    def hit_paddle(self, pos):
        # получаем кординаты платформы через объект paddle (платформа)
        paddle_pos = self.canvas.coords(self.paddle.id)
        # если координаты касания совпадают с координатами платформы
        if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
            if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
                # увеличиваем счёт (обработчик этого события будет описан ниже)
                self.score.hit()
                # возвращаем метку о том, что мы успешно коснулись
                return True
        # возвращаем False — касания не было
        return False
    # метод, который отвечает за движение шарика
    def draw(self):
        # передвигаем шарик на заданный вектор x и y
        self.canvas.move(self.id, self.x, self.y)
        # запоминаем новые координаты шарика
        pos = self.canvas.coords(self.id)
        # если шарик падает сверху  
        if pos[1] <= 0:
            # задаём падение на следующем шаге = 2
            self.y = 2
        # если шарик правым нижним углом коснулся дна
        if pos[3] >= self.canvas_height:
            # помечаем это в отдельной переменной
            self.hit_bottom = True
            # выводим сообщение и количество очков
            canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
        # если было касание платформы
        if self.hit_paddle(pos) == True:
            # отправляем шарик наверх
            self.y = -2
        # если коснулись левой стенки
        if pos[0] <= 0:
            # движемся вправо
            self.x = 2
        # если коснулись правой стенки
        if pos[2] >= self.canvas_width:
            # движемся влево
            self.x = -2
#  Описываем класс Paddle, который отвечает за платформы
class Paddle:
    # конструктор
    def __init__(self, canvas, color):
        # canvas означает, что платформа будет нарисована на нашем изначальном холсте
        self.canvas = canvas
        # создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя 
        self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
        # задаём список возможных стартовых положений платформы
        start_1 = [40, 60, 90, 120, 150, 180, 200]
        # перемешиваем их
        random.shuffle(start_1)
        # выбираем первое из перемешанных
        self.starting_point_x = start_1[0]
        # перемещаем платформу в стартовое положение
        self.canvas.move(self.id, self.starting_point_x, 300)
        # пока платформа никуда не движется, поэтому изменений по оси х нет
        self.x = 0
        # платформа узнаёт свою ширину
        self.canvas_width = self.canvas.winfo_width()
        # задаём обработчик нажатий
        # если нажата стрелка вправо — выполняется метод turn_right()
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        # если стрелка влево — turn_left()
        self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        # пока платформа не двигается, поэтому ждём
        self.started = False
        # как только игрок нажмёт Enter — всё стартует
        self.canvas.bind_all('<KeyPress-Return>', self.start_game)
    # движемся вправо 
    def turn_right(self, event):
        # будем смещаться правее на 2 пикселя по оси х
        self.x = 2
    # движемся влево
    def turn_left(self, event):
        # будем смещаться левее на 2 пикселя по оси х
        self.x = -2
    # игра начинается
    def start_game(self, event):
        # меняем значение переменной, которая отвечает за старт движения платформы
        self.started = True
    # метод, который отвечает за движение платформы
    def draw(self):
        # сдвигаем нашу платформу на заданное количество пикселей
        self.canvas.move(self.id, self.x, 0)
        # получаем координаты холста
        pos = self.canvas.coords(self.id)
        # если мы упёрлись в левую границу 
        if pos[0] <= 0:
            # останавливаемся
            self.x = 0
        # если упёрлись в правую границу 
        elif pos[2] >= self.canvas_width:
            # останавливаемся
            self.x = 0
#  Описываем класс Score, который отвечает за отображение счетов
class Score:
    # конструктор
    def __init__(self, canvas, color):
        # в самом начале счёт равен нулю
        self.score = 0
        # будем использовать наш холст
        self.canvas = canvas
        # создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
        self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
    # обрабатываем касание платформы
    def hit(self):
        # увеличиваем счёт на единицу
        self.score += 1
        # пишем новое значение счёта 
        self.canvas.itemconfig(self.id, text=self.score)
# создаём объект — зелёный счёт 
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик 
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна 
while not ball.hit_bottom:
    # если игра началась и платформа может двигаться
    if paddle.started == True:
        # двигаем шарик
        ball.draw()
        # двигаем платформу
        paddle.draw()
    # обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
    tk.update_idletasks()
    # обновляем игровое поле и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
    tk.update()
    # замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
    time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)

Пишем игру на Python

Что дальше

На основе этого кода вы можете сделать свою модификацию игры:

  • добавить второй шарик;
  • раскрасить элементы в другой цвет;
  • поменять размеры шарика; поменять скорость платформы;
  • сделать всё это сразу;
  • поменять логику программы на свою.

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

Прежде, чем мы начнем, мы хотим привести вам пример первой игры от автора этой статьи. Это была простая текстовая игра под названием Divine Blood:

01

Это была самая первая игра, причем запрограммированная для калькулятора TI-83 Plus. Позднее она была переписана автором на Java во время обучения в старших классах. Примечательно, что игра так и не была закончена.

Ко всеобщему сожалению, не доводить игры до логического конца — одна из самых распространенных проблем начинающих разработчиков. Соответственно, возникает вопрос: как повысить свою продуктивность и все-таки закончить начатый проект? Ответ прост: прочтите наше «прохождение» разработки игры.

Основные этапы

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

  • планирование;
  • прототипирование;
  • программирование;
  • релиз.

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

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

Уровень 1: Планирование

Помните, сделав 90% игры, вы думаете, что потратили 90% своего времени. А доделывая оставшиеся 10%, вы тратите еще столько же «оставшегося» 90% времени. Составляйте план, учитывая это. — Ян Шрейбер

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

Как только вы задумали что-то разработать, первым делом достаньте блокнотик, ручку и начинайте писать свои идеи. Максимально подробно останавливайтесь на деталях, это поможет вам в будущем. Пишите все, что вы хотели бы увидеть в вашей игре. Вся соль здесь заключается в том, что поначалу это сделать довольно просто: проект пока не разрос, и все у вас находится на виду. Но чем больше вы разрабатываете игру, тем сложнее будет начать писать свои идеи и в дальнейшем учитывать их.

02

Как уже говорилось выше — уделяйте внимание деталям. Записали новую фичу для реализации? Отметьте рядом, как она будет работать, как будет влиять на игрока и непосредственно на игровой процесс. И помните, секрет успешной разработки — решать существующие проблемы, пока они не накопились.

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

Именно поэтому важно спланировать все, иначе на этапе разработки (уровень 3) вы захотите добавить в игру больше возможностей и начнете реализовывать все подряд, что категорически неправильно. Ваш проект рискует быть чрезмерно большим, отчего вам сложнее будет его контролировать, а вскоре вы вовсе бросите его в дальний ящик в надежде, что возьметесь за него позже. Если вы играли в серию игр Halo, представьте себе, как было бы трудно играть в нее, если бы вы столкнулись с парочкой охотников сразу после начала игры. Вы попросту будете умирать снова и снова, пока вам не надоест эта череда смертей. В разработке игры все аналогично.

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

А боссом этого уровня являются вопросы. Просмотрите на все свои заметки и убедитесь в том, что у вас нет каких-либо непонятных пунктов: ни в используемых инструментах, ни в алгоритмах и прочем. Если же у вас действительно все вопросы решены, то вы смело можете считать, что уровень «Планирование» закончен. Но если остались непонятные аспекты — решите их, прежде чем переходить дальше.

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

Уровень 2: Прототипирование

Дизайн это процесс, а не результат. — Кристофер Симмонс

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

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

Если вы получаете удовольствие от какой-либо игры, то вы захотите поиграть в нее снова, независимо от того, сколько очков или денег вы там набрали. — Стэн Яроцки

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

Вы помните секретные телепорты в игре Super Mario Bros? Игрок мог найти хорошо спрятанные трубы, прыгнув в которые можно было пропустить несколько уровней. Так и здесь. Правда, мы не полностью пропускаем прототипирование, а совмещаем его с планированием.

03

Хотим заметить, что первые два этапа взаимозаменяемы. Быть может, вы хотите проверить основную механику вашей игры, прежде чем потратите кучу времени на детали? А может, вы хотите попробовать какую-то возможность в вашей игре? Это основные причины, почему есть смысл в том, чтобы поменять порядок первых двух этапов.

Хорошая игра — это поток интересных задач, решаемых игроком. — Брюс Шелли

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

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

Уровень 3: Программирование

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

Чтобы начать этот этап, вам стоит определиться с целевой платформой вашей игры. Будет эта игра для консолей, а, может быть, мобильная или вовсе браузерная? Определившись с платформой, выберите необходимый инструментарий и язык программирования.

На самом деле эти два шага можно выполнить в обратном порядке. Имея какую-либо среду разработки (или язык программирования), вы можете проанализировать ее возможности и решить, что вы сможете написать.

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

«Я не умею рисовать» — используй клипарт. «Я не умею создавать звуки» — ищи MIDI файлы. «Я не умею программировать» — никого это не волнует, не программируй! — Роб

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

Но вы не должны унывать! Лучшее решение этих проблем — отвлечься от проекта на несколько дней. Вы очистите ваш ум и позволите новым идеям посетить его. Также неоднократно замечено, что «утро вечера мудренее». Застряли? Не знаете как решить проблему? Ложитесь спать, а на завтрашнее утро вы, возможно, сразу поймете причину ваших неудач. Не работайте до изнеможения и не изнуряйте себя: работа над проектом должна быть в удовольствие.

Если вы пытаетесь и не можете решить действительно сложную проблему — остановитесь. Решите более простую проблему, которая выполняет те же действия, что и сложная. — Даниель Кук

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

Уровень 4: Релиз

Никогда не сдавайся. — Элис Тейлор

Наконец-то мы добрались и до релиза. Конечно же, этот уровень не такой сложный, как предыдущий, но и легкомысленно относится к нему не стоит. На этом этапе вы должны убедить людей играть в вашу игру и давать вам обратную связь (вы же хотите улучшить свой проект?). Основываясь на отзывах игроков, внесите в ваше приложение те изменения, которые сделают игру более увлекательной по вашему мнению.

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

Начиная создавать игру, не смотрите на результаты других. Создайте то, что хотите вы. — Роб

А финальным боссом всего нашего путешествия будет являться ваша гордость. Вы сделали полноценную игру от начала и до конца! На самом деле, не все могут похвастаться этим.

Каждый разработчик когда-нибудь напишет «плохую» игру. Если вы еще не написали — напишете. Все мы напишем. — Бренда Ромеро

И помните, дорога к успеху вымощена многократными неудачами. Никогда не сдавайтесь!

Вывод

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

А теперь соберитесь и напишите свою игру!

Перевод статьи «Making Your First Game: A Walkthrough for Game Developers»

Игровая индустрия стремительно развивается. Одним из самых распространенных языков разработки игр и иного развлекательного контента является C++. Он достаточно сложный, особенно на первых порах. Также популярностью пользуется его предшественник – C.

Если верить Google, написать собственную игру может каждый. Для этого предстоит выбрать язык разработки, а затем выучить его. Далее – определиться с типом приложения, реализовать в виде кода.

В данной статье будет рассказано о том, как написать собственную игру на C++. Рассмотрим ключевые моменты процесса, разберемся с мотивацией. Информация пригодится и новичкам, и продвинутым разработчикам.

Мотивационный вопрос

Перед тем, как программировать, нужно задуматься над истинной мотивацией идеи. Google указывает на то, что создать собственную игру «просто так» не получится. Что-то должно двигать человеком.

Игровой код на C++ — это отличный способ потренироваться в разработке, изучить ее азы. А еще – создать проект, который может принести прибыль при грамотной реализации.

Почему C++

Игра – это простой программный код. Но на C++ можно создавать совершенно разные приложения. Игры – лишь начало. Данный язык программирования является универсальным и самым популярным.

Он выбирается разработчиками по нескольким причинам:

  • широкая распространенность;
  • возможность создавать не только простые проекты, но и сложные;
  • кроссплатформенность;
  • функциональность;
  • удобство работы с кодом.

Google указывает на то, что нынешний рынок труда остро нуждается в программистах на C++. Начиная с мелких игр, человек сможет отработать навыки и знания, дорасти до крупных масштабных работ.

Ключевые компоненты проекта

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

  • графику;
  • логику;
  • интерфейс;
  • звук;
  • историю;
  • игровой процесс (физику).

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

Графическая составляющая

Это – картинка на экране. Включает в себя изображения и эффекты. Сюда можно отнести:

  • 3D-компоненты;
  • текстуры;
  • 2D-плитки;
  • 2D-модели;
  • видео с полным движением (FMV).

Над графикой лучше работать дизайнерам. Программистам рекомендуется сконцентрироваться на создании «внутренности» будущей игры. А визуальную составляющую оставить тем, кто занимается этим вопросом профессионально.

Звуковые эффекты

Звук – еще один важный компонент игры. Google подчеркивает, что сюда относят не только музыку, но и эффекты. Они будут воспроизводиться во время работы приложения. Сюда также относят эффекты Фоули («отголоски» окружающей среды) и мод-треки.

История

Предыстория игры, включающая в себя всю информацию, полученную от игрока в процессе работы приложения. Пример – выигрыши и проигрыши. История является игровым элементом. Это – неизменяемая последовательность. Можно охарактеризовать ее «прогрессом».

Физика

То, как будут взаимодействовать объекты на экране. Проработка физической составляющей, согласно Google – это трудный и важный процесс. «С нуля» им занимаются преимущественно опытные разработчики. Остальные предпочитают пользоваться готовыми библиотеками, фреймворками и движками.

Как можно создавать игры

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

  1. Написанием кода через библиотеки и фреймворки, с нуля. Неплохой вариант для небольших проектов.
  2. Собственным движком. Такой подход присущ большинству крупных компаний. Пример – ReEngine от Capcom.
  3. Готовым движком. Наиболее подходящий вариант для быстрого старта. Игровые движки включают в себя «все необходимое» для того, чтобы человек мог написать собственную игру без существенных навыков в программировании.

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

Алгоритм работ

Писать программы, согласно Google, рекомендуется, следуя конкретному алгоритму. В противном случае процесс рискует затянуться на месяцы, а то и годы. Особенно если речь идет о команде новичков.

Программный игровой код лучше составлять так:

  1. Продумать общую концепцию. Составить историю игры.
  2. Собрать команду помощников. Самостоятельно работать над небольшим проектом – это нормально. Но, если на C++ планируется релиз игры не по типу «змейки» или «угадай число», лучше запастись поддержкой. Это поможет ускорить процесс разработки.
  3. Продумать интерфейс, графику и физику. Этот шаг пропускается, если разработчик предпочел пользоваться движками.
  4. Непосредственно создать игровой код. Это – самый сложный и важный этап. Он требует определенных навыков программирования.
  5. Провести тест. Без тестирования и проверок ни один контент не может рассчитывать на успешный релиз.
  6. Исправить обнаруженные ошибки и неполадки. В конце – снова проверить работоспособность кода.

Когда все готово, можно использовать последний шаг – релиз игры. Пример – на своем сайте или в фирменных интернет-магазинчиках.

Данный алгоритм универсален. Он, по Google, подойдет не только для игры на C++, но и для любого другого языка программирования.

Змейка

«Змейка» — популярная и простая игра, которая нравилась всем детям 90-х. Она подходит для любых платформ, включая мобильные операционные системы. Сейчас можно отыскать огромное количество вариантов «Змейки», включая онлайн версии.

За несколько свободных вечеров, обладая минимальными знаниями в C++, удастся написать собственную «Змейку из начала 90-х». Она не выделяется графикой, но общий смысл создания игры на выбранном языке программирования станет понятен. Данный проект назовем Oldschool Snake.

Принцип игры

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

  1. Движение змейки осуществляется за счет курсора мыши.
  2. При нажатии на Esc происходит выход из игры.
  3. Если система спрашивает «Еще раз?», требуется кликнуть по N на клавиатуре. Это приведет к завершению игрового процесса.
  4. На собственных хвост и стенки змея на экране не должна натыкаться. Это приводит к проигрышу. То есть, к смерти змейки.
  5. Движение «хвостом вперед» не поддерживается. Если так попытаться сделать, последует мгновенная смерть.
  6. Для роста змеи необходимо кормить ее. Для этого – собирать доллары на экране. Чем больше съела змейка, тем крупнее (длиннее) она становится.
  7. Каждая «подкормка» приносит определенное количество баллов. Они помогут сформировать ТОП-10 рейтинг.

Рейтинг, получаемый в игре, прямо пропорционален длине змейки, а также обратно пропорционален времени, потраченному на съедение очередной порции «подпитки».

В Google можно отыскать немало других правил и игровых особенностей для «змеек». Только начинать разработку рекомендуется с такого элементарного алгоритма. Он не позволит пользователю запутаться.

Лицензия

Google указывает на то, что любая игрушка или иной компьютерный софт должны обладать лицензией. Рекомендуется на первых порах отдать предпочтение GNU GPL.

Это – вариант для «свободных программистов». Позволяет спокойно распространять контент, изучать исходные коды и корректировать их под собственные нужды. Но только для некоммерческих целей.

Особенности реализации

Играть в такую игру достаточно легко. Она обладает простой логикой и графикой. Можно написать подобное приложение за несколько вечеров. Здесь стоит запомнить следующее:

  1. Изначально приложение создавалось для Windows 2000 Professional и выше.
  2. Для того, чтобы перенести игру на другие ОС, потребуется переписать класс CScreen и иметь порт библиотеки conio.h.
  3. Компиляция происходила через TDM-GCC 4.8.1. на 64-бит. Можно попробовать запуск через иные компиляторы.

Данное приложение проблематично назвать «современной игрой», но на первых порах ее достаточно. Вот архив с исходным кодом.

Виселица

А вот еще один довольно интересный пример – «Виселица». Игра, которая, согласно Google, известная многим. Здесь она представлена своеобразным механизмом, коим является любое приложение. Обладает:

  • основой – каркасом;
  • дополняющими направлениями – теми, что задают границы возможностей;
  • концом.

С данными компонентами в элементарном приложении проблем не возникнет. Особенно если посмотреть в Google правила «Виселицы». Для крупных проектов над каждой составляющей утилиты предстоит немало потрудиться.

Правила и принципы

«Виселица» — это игра в стиле «угадай слово». Предложенный пример реализовывается в пределах одного диалогового поля. Случайным образом программа загадывает слово. Пользователю предлагаются 10 попыток. Если он ошибается – засчитывается проигрыш.

После запуска система предложит сыграть. Для ответа необходимо нажать на клавиатуре «Д» (да) или «Н» (нет). В первом случае происходит запуск операции. Во втором – выход из системы.

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

Ввод данных – с маленькой буквы. При попытке указать заглавную, игра попросит исправится. Если клиент угадал букву, она отобразится в положенных местах вместо «знака вопроса». Повторный ввод ранее указанных букв не отнимает ход. Программа просто просит пользователя заменить ее на другую.

Также стоит обратить внимание на то, что после каждого хода игрока приложение отображает количество попыток, отведенных на угадывание слова. Они снимаются, если допущена ошибка. В противном случае – сохраняются.

Реализация

При написании кода «Виселицы» в приведенном далее примере непосредственный процесс начинается с 84 строки. Тут необходимо запомнить следующее:

  1. Начинает работать бесконечный цикл. Google характеризует его как петлю.
  2. Цикл работает до тех пор, пока игрок не угадает слово или не допустит установленное количество ошибок.
  3. В коде есть проверка на соответствие символов буквам русского алфавита.
  4. В процессе реализации проверяется повторный ввод ранее указанных букв.
  5. При запуске система выдаст сообщение с правилами. Не придется лезть в Google и разбираться с принципами работы «Виселицы».

Выйти можно в любой момент. Здесь – исходный код приложения.

Как быстро научиться программировать

Создание собственной игры – дело не самое трудное, если речь идет о небольших проектах. Когда у пользователя есть заинтересованность в крупных и сложных работах, предстоит многое изучить. Быстрее вникнуть в тему можно, грамотно выбрав концепцию обучения:

  1. Поступление в техникум. Вариант для тех, кто думает развиваться в сфере программирования. В техникумы берут после 9 или 11 классов. Здесь не учат писать игры. Google указывает на то, что в подобных учреждениях дают «базу» для дальнейшего развития. Обучение 3-4 года. В конце выдается диплом о среднем специальном образовании.
  2. ВУЗы. Поступление в университет на «разработку и программирование» – лучшее решение для тех, кто готов полноценно погрузиться в азы соответствующих процессов. ВУЗы изучают различные ЯП, включая C++. Обучение отнимает 4-6 лет. В конце выдается диплом о высшем образовании в выбранном направлении. На 2-3 курс можно зачислиться при предварительном обучении в техникуме «на программиста». Образовательный процесс сопровождается кураторством и практикой.
  3. Самообучение. Неплохой вариант для тех, кто обладает особой усидчивостью. В Google можно отыскать множество туториалов и видео о разработке игр на любом языке, а не только на C++. Скорость обучения контролируется пользователем. Он может сконцентрироваться на более «проблемных» для себя областях и отдать предпочтение практике. Из минусов – отсутствие документального подтверждения навыков. Остается собирать портфолио и участвовать во всевозможных конкурсах.

Если же хочется побыстрее освоить навыки игрового программирования, стоит присмотреться к дистанционным онлайн курсам. Пример – от OTUS. Этот образовательный центр предлагает учиться в режиме онлайн инновационным IT-профессиям. В срок от нескольких месяцев до года пользователя научат с «нуля» не только писать сложные программы, но и создавать собственный развлекательный контент. Образовательный процесс разбит на «блоки» — для новичков и опытных разработчиков. Можно выбрать сразу одно или несколько направлений обучения. Весь процесс сопровождается кураторством, а также многочисленной практикой и интересными домашними заданиями. В конце каждого курса клиенты получают не только собственное портфолио, но и электронный сертификат, подтверждающий знания в выбранной области.

Хотите освоить современную IT-специальность? Огромный выбор курсов по востребованным IT-направлениям есть в Otus! Ниже – один из них:

Это статья для новичков в геймдеве. Для тех, кто хочет сделать игру, но не знает с чего начать.

Я постараюсь, по шагам, объяснить весь процесс от желания до релиза. Погнали!

Кто я такой?

Я гейм-дизайнер с 10-летним стажем. Работал в многих компаниях, например в Playgendary. Делал разное: и казуалки для мобилок, и танковый шутер для PC.

Теперь я инди-разработчик. Живу за счёт продажи своих игр. Выпустили 4 игры для PC и Консолей. Сейчас разрабатываю игру They Are Here: Alien Abduction Horror — хоррор от 1-го лица, про похищение пришельцами.

They Are Here: Alien Abduction Horror

Шаг 1. Запасись энтузиазмом

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

Как пополнять запас энтузиазма? Смотри документалки, читай истории успеха разработчиков. Это мотивирует!

Смотри по сторонам: на другие игры, фильмы, кино, на новые технологии. Желание изучить что-то новое или сделать что-то похожее — это то, что нужно.

Шаг 2. Собери команду или сделай всё сам!

Одному — проще. Проще придумать идею и принимать решения. Не надо спорить и описывать задачи. Сделать игру одному — возможно. Я например сделал 4 игры один.

С командой — лучше. Лучше получается качество. Твои решения критикуются, и результат улучшается. Можно распределить обязанности и сделать игру быстрее. Последнюю игру я делаю в команде со своей женой. Она отвечает за историю, критикует мои решения, помогает с артом, ищет стримеров.

Короче — есть команда, круто! Нет команды — делай всё сам, это не трудно.

Типичный инди-разработчик

Шаг 3. Сформулируй цель разработки

Очень важно понять — для чего тебе всё это?

Ну например:

1. Трудоустройство в геймдев компанию.

Продукт — портфолио. Приоритет — качество исполнения.

Вопросы: На какую должность хотим устроиться? В какую компанию(и)? Какими играми занимается компания(и)? Чему нужно научиться?

2. Научиться делать игры, освоить навык.

Продукт — опытный образец. Приоритет- новые знания.

Вопросы: Какой навык освоить? Как сделать какую-то конкретную штуку?

3. Рассказать о чём то важном.

Продукт — манифест. Приоритет — донести идею до масс.

Вопросы: Поймут ли мою идею? Как сделать продукт более массовым?

4. Сделать игру о которой мечтал.

Продукт — мечта. Приоритет — воплотить своё видение.

Вопросы: Что я хочу видеть? Чем можно пренебречь? Как закончить проект?

5. Построить свой бизнес.

Продукт — актив. Приоритет — получить доход.

Вопросы: Какие игры лучше продаются? Сколько времени займет разработка? Как сократить это время?

Цель может быть не одна. Цели могут меняться от игры к игре.

Короче — ты должен ответить на вопрос — зачем я делаю эту игру?

А рально, зачем?

Шаг 4. Вспомни, что ты умеешь или любишь

Например, я и моя жена — фанаты фильмов ужасов про пришельцев. Типа «Знаки», «Мрачные небеса», «Секретные материалы». Поэтому нам проще работать над идеями и сценарием для They Are Here

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

Тян одобряет отталкиваться от умений и увлечений

Короче — твои умения и увлечения — это твои преимущества. Учитывай их при выборе платформы, движка, жанра игры. А пока, просто подумай над этим.

Шаг 5. Выбери платформу

Если просто, то есть 2 пути: Мобилки или ПК + Консоли.

Исходя из целей и умений нужно будет выбрать что-то одно. Это разные платформы, с разными играми, аудиторией и монетизацией.

Путь 1. Мобики

Аудитория:

  • Массовая аудитория. Дети, пенсионеры, скучающие продавщицы. Это не геймеры. Всё должно быть очень понятно и просто.
  • Играют по 1 — 5 минут. В перерывах, в очередях, на работе. Чтобы «убить время».
  • Ценится простая яркая графика.
  • Упор на простой, но залипательный кор-геймплей.

Плюсы:

  • Некоторые жанры (головоломки, аркады) — наиболее просты в разработке. Можно сделать небольшой прототип (1-5 уровней) и показать его работодателю, например.
  • Не требуется красивая или сложная графика. Главное — чтобы было понятно.
  • Простой геймплей и гейм-дизайн.
  • Будет плюсом, если сам привык к мобильным девайсам и играм.

Минусы:

  • Очень. Высокая. конкуренция. Игр миллионы и почти все они — бесплатные. Игроки приходят только с рекламы. Нет рекламы — нет игроков. Нет денег.
  • Монетизация. Нужно встраивать рекламу или внутри-игровые покупки в игру. Знать куда и как. Тестировать чтобы всё это работало.
  • Аналитика. Нужно понимать что такое LTV. Почему он должен быть > чем CPI. Встраивать аналитику в игру.
  • Будь готов делать по 20 прототипов или улучшать продукт, пока LTV не станет > CPI.
  • Заработать денег небольшой команде, можно только с издателем. Я лично не знаю других путей.

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

Если пофиг на доход — классная, лёгкая платформа.

Если решишься, узнай подробнее про:

  • Гипер-казуальные игры (всё по теме гейм-дизайна и производства).
  • Как найти издателя гипер-казуальных игр.
  • Казуальная графика.
  • Low-poly графика.
  • Казуальные игроки (сложность казуальных игр и туториалы).
  • Аналитика мобильных игр (CPI, LTV, Retention).
  • Монетизация мобильных игр.
  • Оптимизация мобильных игр.
  • Google Play и App Store. Регистрация аккаунта разработчика. Правила и рекомендации. SEO.
  • Рекламные медиаторы и сети (Iron Source, AdMob и т.п.).
  • Сервисы рыночной аналитики мобильных игр (Sensor Tower, App Annie).

Путь 2. ПК + Консоли

Аудитория:

  • Хардкорные геймеры.
  • Играют по несколько часов. Дома. Чтобы погрузиться в игру.
  • Ценится реалистичная или стильная графика.
  • Упор на интересную историю или глубокий геймплей.

Плюсы:

  • Меньше конкуренция, чем на мобилках. Особенно на консолях.
  • Легче получить игроков и отзывы.
  • Можно хорошо заработать портировав игру на консоли, с помощью издателя.
  • Не надо возится с аналитикой и монетизацией.
  • С детства понятная платформа (ПК / Консоль) и аудитория (Геймеры).
  • Аудитория любит авторские, творческие, интересные игры.
  • Будет плюсом, если сам играешь на компе или приставке.

Минусы:

  • Плохо заходят простенькие игры (головоломки, аркады). Геймеры хотят получить опыт, вжиться в роль. Залипнуть надолго. Игра не должна выглядеть как что-то на пару минут.
  • Игры дольше в производстве. Но можно хитрить — делать маленькие игры, которые выглядят как большие, а также использовать готовые ассеты.
  • Нужно поработать над интересной идеей. Найти отличительные черты (USP), которые выделят проект.
  • Нужно продумать интересную историю или геймплей.
  • Более сложный геймдизайн.
  • Большая требовательность к качеству графики.

Короче — ПК, а особенно Консоли это элитный бутик. На полке лежит то, что пользуется спросом. Это конкуренция качества. Если хочешь заработать, то сделай интересную игру, и обязательно портируй её на консоли (через издателя). Подумай как сэкономить на производстве!

Если решишься, узнай подробнее про:

  • Геймдизайн компьютерных игр.
  • Нарратив, сторителлинг.
  • Как питчить игры.
  • Фичи игры / USP.
  • Что такое вертикальный срез.
  • Steam. Регистрация аккаунта разработчика. Оформление страницы. Тэги. Правила и рекомендации.
  • Маркетинг и продвижение инди-игр на Steam (рекомендую http://howtomarketagame.com/) Как сделать крутой постер, трейлер, скриншоты, ГИФки.
  • Портирование игр на консоли.
  • Издатели игр на консолях.
  • Конкурсы и фестивали инди-игр.
  • Работа с инфлюенсерами (ютуберами, стримерами).
  • Реалистичная графика.
  • Стилизованная графика.
  • Сервисы аналитики тэгов и жанров (SteamDB, Steamspy, SteamCharts, Game Data Crunch).
  • Сервисы рассылки ключей (Keymailer, Woovit)

Шаг 6. Узнай про геймдизайн и производство игр

Интересуйся тем Как делают игры (классный подкаст в твои наушники)

Рекомендую погуглить про:

  • Игровые механики, жанры и сеттинги.
  • Геймдизайн. Есть книга Джесси Шелла, она хорошая, но большая. Можешь гуглить про конкретный жанр.
  • Кор-геймплей и Мета-геймплей.
  • Левел-дизайн. Лучше гуглить про отдельный жанр.
  • Пользовательский интерфейс (UI) в играх.
  • Ассеты и маркетплейсы.

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

Шаг 7. Выбери движок и глянь уроки

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

Про выбор движка написано много статей — погугли.

Если ты один, и не знаешь языков программирования, рекомендую Unreal Engine 4.

  • Там есть Blueprints — это визуальное программирование. Это проще чем писать код.
  • Красивый рендер «из коробки».
  • Есть большой маркетплейс с гововыми ассетами
  • Это популярный коммерчесский движок, на котором сделано очень много игр.
  • Можно сделать игру под все платформы. Можно встроить рекламу, инапы, аналитику.
  • Много уровков. Рекомендую Unreal Engine Rus
  • Классный интерфейс.
  • Куча встроенных функций.
  • Бесплатный до ляма баксов дохода.
Unreal Engine 4 Blueprints

Перед началом работы над игрой, сделай пару очень простых подделок «в стол».

Сделай змейку, пинг-понг и т.п. Пофиг на качество, пофиг на геймдизайн. Главное — попрактиковаться «на кошках», пощупать функции движка.

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

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

Шаг 8. Выбери жанр

Жанр — это твоя ниша. Жанр — это очень важно. Есть жанры, в которые никто не играет. А для некоторых нужно изучить много дополнительного материала.

Лучше выбрать жанр который:

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

Как только ты определилися с жанром — гугли всё по производству игр в этом жанре. Геймдизайн, графика, уровни, звуки. На что сделать акцент?

Поиграй в лучшие игры в этом жанре. Посмотри видео об этом жанре.

Короче — выбери жанр и узнай про него всё что можешь!

Шаг 9. Придумай идею, концепцию, USP

Идея — ядро твоей игры. Зерно, из которого вырастет проект.

Какая идея хорошая?

  • Понятная. Должна быть понятна каждому. Например, твоей маме.
  • Интересная. Уже хочется поиграть в это! Люди любят риск и новый опыт, который хотят, но не могут пережить в реальной жизни. Например GTA — это симулятор крутого парня, которым все хотят быть, но не могут.
  • Популярная. Это не артхаус, не что-то странное или специфичное. Идея обращается к понятным образам из жизни или массовой культуры.
  • Выделяющаяся. Такого раньше не было. Или было, но давно. Или в другом жанре. Или в другом стиле. Или плохо сделано.

Что поможет тебе в выборе идеи?

  • Каталог игр на твоей платформе. Смотри что популярно. Думай как это изменить, подать под другим углом. Хмм…игра про постройку железной дороги в топе. А что если, мы играем за машиниста?
  • Сайты-сервисы с аналитикой тэгов и жанров на платформе. Можно отследить популярность жанра, количество игр в нем. Можно скрестить отдельные тэги между собой.
  • Массовая культура. Фильмы, книги, комиксы, короткометражки, гифки, картинки из интернета.

Скорее всего у тебя будет рождаться много идей. Записывай их. Дай полежать. А потом выбери ту, что не даёт тебе покоя и кажется лучшей.

Когда родил идею

Про питч

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

На основе Питча, описываем концепт игры. Более развернутое описание игры на одну страничку. За кого мы играем? В чем цель? Что можно делать? Какие эмоции вызываем?

Про USP

Продумай ключевые фичи — USP, которые будут продавать твой проект. Они вытекают из твоей идеи.

Например, идея Панка — издевательство над массовой культурой и модой.

Ключевые фичи (USP) Панка: вызывающее поведение, агрессивная музыка и странные прически.

Зацени мои USP, чувак!

Показывай свои USP везде — в трейлере, скриншотах, постере, описании игры. Говори про них общении с прессой и издателями.Тычь ими в лицо!

Например, у They Are Here — это пришельцы, кукурузные поля как фильме Знаки, и НЛО.

Кароче — почитай про идею, концепцию, питч, USP игры. Сформулируй чёткое видение твоего проекта и доноси это видение до всех. Без него — всё развалится и поплывет.

Шаг 10. Составь список ассетов и задач

Ассеты — это кирпичики, из которых состоят игры.

Составь список того, что нужно сделать. Хотя-бы крупными мазками. Сделать уровнь, найти музыку, вставить персонажа. А еще надо 20 видов мечей.

Оцени время, а потом умножь его на 2. Даже если тебе кажется это глупым. Умножь его в 2 раза!

Если видишь, что проект большой — отрезай всё ненужное. Ненужное — всё, что не показывает идею. Или редко появляется на экране.

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

Прикинь, что для мобильных гипер-казуалок нужно сделать минимум 30 минут геймплея. А для ПК и Консолей, лучше сделать игру на 2 часа. Если можешь больше — круто!

Настоятельно рекомендую!

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

Шаг 11. Организуй процесс

Записывай, всё что надо сделать. Каждую мелочь. Иначе — забудешь.

Ставь задачи. Себе и команде. Рекомендую Trello (проще) или Asana (функциональнее).

Cобирай инфу по проекту в одном месте. Можно юзать доски типа “Miro” или вики типа Notion.

Если ты один, или у вас небольшая команда, не парься над большой и красивой документацией. Лучше покажи пример, начерти схему, объясни на пальцах ЧЁ НАДО сделать.

Референс — лучшее описание задачи для художника! Например, я сказал жене — хочу обложку как у Слендера, но с пришельцем. Этого — достаточно!

Собирай и храни нужную инфу. Ссылки на классные статьи. Контакты возможных партнёров. Скриншоты багов. И т.п.

Шаг 12. Сделай демку

Демо-версия / Вертикальный срез / MVP — очень близкие по смыслу понятия. Это маленький кусочек игры финального качества.

Маленькая, но качественная демка

Демо-версия решает множество задач:

  • Поможет записать видео, скриншоты, гифки
  • Покажет окупаемость мобильной игры
  • Поможет устроиться на работу
  • Ускорит набор вишлсистов в Steam
  • Получит отзывы от игроков и стримеров
  • Можно участвовать в фестивалях и конкурсах
  • Только с ней можно найти издателя.

Короче — сделай демонстрационную версию игры. Это твоя визитная карточка. Показывай её всем. Говори — я сделаю так-же, только больше.

Шаг 13. Фигачь! Прорывайся к релизу!

Не буду вдаваться в подробности о релизе. Всё зависит от игры и платформы.

Лучше дам рекомендации как дожить до релиза:

  • Не меняй идею на ходу. Сильно. По чуть-чуть можно.
  • Не начинай другие проекты. Не распыляйся. Делай, что запланировал.
  • Составь график работы. Работай над игрой постоянно. Хотя бы по 3 дня в неделю, по 2 часа в день. Больше — быстрее!
  • Надоела разработка? Поиграй в похожие игры. Посмотри похожие фильмы. Найди, что было бы круто сделать.
  • Всё равно надоела? Мечтай о релизе. Представь как это будет здорово и вечно!
  • Показывай свою работу — пиши посты, пости гифки, давай поиграть стримерам. Твоя цель — получить позитивную обратную связь. Ну или отрицательную.
  • Узнавай что-то новое про производство игр. Слушай подкасты, смотри доклады. Это мотивирует, помогает в производстве.
Будь как этот парень

Спасибо, что дочитал!

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

Короче — ты можешь сделать это! Реально!

Главное — желание!

Понравилась статья? Поделить с друзьями:
  • Как написать игру на питоне со своей графикой
  • Как написать игру на питоне для андроид
  • Как написать игру на паскале abc
  • Как написать игру на пайтон
  • Как написать игру на котлин