Видеоуроки по созданию игры на C++
Нашли для вас серию видео, в которой автор по шагам рассказывает, как написать свою игру на C++. Эти уроки не требуют каких-то продвинутых знаний, но базовые представления о программировании приветствуются.
Урок 0 — Введение и подготовка
В этом уроке автор расскажет, как пишутся игры. Также вы загрузите компилятор и напишите простой helloworld в Visual Studio, чтобы всё было готово для разработки игры.
Урок 1 — Окна и указатели
Здесь вы перейдёте к первому шагу на пути к игре: созданию окон. К концу урока у вас всё будет готово для отображения графики в окне.
Урок 2 — Графика
В этом уроке вы узнаете, как написать программу для отрисовки фигур на экране. Также по ходу дела автор объяснит некоторые важные вещи вроде того, что такое буфер и зачем он нужен, что есть куча и стек, как запросить у Windows больше памяти и не только.
Урок 3 — Ввод, движение и время
Этот урок про то, как создать систему ввода. Вы узнаете, как сохранять состояния кнопки, чтобы легко определять, нажата она или нет. Также речь зайдёт о том, как можно заставить игрока двигаться пока нажата клавиша и как сделать этот процесс независимым от частоты кадров.
Урок 4 — Геймплей, столкновения, улучшение передвижения
В этом уроке вы займётесь геймплеем игры. Вы добавите элементы вроде игроков, мяча и арены, а затем разберётесь, как заставить объекты двигаться и как обрабатывать их столкновения.
Урок 5 — Вражеский ИИ, подсчёт очков, завершаем геймплей
Из этого урока вы узнаете, как создать систему подсчёта очков. Также вы создадите ИИ противника и узнаете некоторые важные вещи об ИИ в играх.
Урок 6 — Завершаем игру
В последнем уроке вы завершите игру. Вы реализуете меню, систему отрисовки текста и немного отполируете результат.
Урок №1: Введение в создание игры «SameGame» на C++/MFC
Обновл. 28 Дек 2020 |
В этой серии обучающих уроков мы, используя библиотеку MFC (сокр. от «Microsoft Foundation Classes»), с нуля создадим свой вариант всем известной игры-пазла SameGame. Мы добавим несколько дополнительных фич к этой игре, помимо простого удаления блоков, а также реализуем подсистему отмены/повтора действия и диалоговые окна конфигурации. Рассмотрим примеры не только «голого» исходного кода, но и поэтапную разработку вместе со скриншотами.
Правила игры SameGame
Правила SameGame предельно простые. Ваша задача — удалить все цветные блоки с игрового поля. Для того чтобы удалить блок, игрок должен кликнуть по любому блоку, который стоит рядом (вертикально или горизонтально) с другим блоком того же цвета. Таким образом уничтожится целая цепочка блоков одного цвета. Блоки, которые при этом находились сверху, упадут вниз, заполняя освободившееся пространство. При удалении всего столбца, стоящие справа столбцы сдвигаются влево, занимая пустое место. Игра заканчивается тогда, когда у игрока не остается больше возможных ходов. Цель игры состоит в том, чтобы как можно быстрее очистить доску от цветных блоков.
Стоит заметить, что некоторые реализации игры SameGame также могут дополняться использованием алгоритмов для подсчета очков игрока. Реализацию подобного функционала можно рассмотреть в качестве дополнительного урока.
Перед началом работы
Вам потребуются базовые знания в таких разделах языка C++ как функции, рекурсия, классы и наследование классов. В качестве среды разработки была выбрана бесплатная версия Microsoft Visual Studio 2017 Community Edition в операционной системе Windows 7 (детально об установке IDE). Если версии вашей операционной системы или среды разработки не совпадают с вышеуказанными версиями, то некоторые детали или внешний вид отдельных компонентов могут отличаться от тех, которые вы будете видеть на скриншотах данного туториала. Также не советую использовать Express-версии пакета Visual Studiо, т.к. в них не входит компонент MFC.
Чему вы научитесь?
В первую очередь, вы научитесь основным принципам создания своей собственной игры, узнаете о библиотеке MFC и о некоторых базовых методах её использования, а также познакомитесь с построением своего приложения с использованием архитектуры «Document/View».
Почему именно MFC?
MFC — это легкая в использовании библиотека, особенно для такой простой игры как наша. С её помощью не составит труда создать приложение с, так называемым «Windows look-and-feel», внешним видом. Стиль «Windows look-and-feel» имитирует особенности конкретной системы, на которой он используется: «Look» определяет внешний вид компонентов, а «Feel» — их поведение.
Создание проекта
Создавать нашу игру мы будем в Microsoft Visual Studio 2017. Все инструкции и описания, приведенные ниже, могут быть с легкостью адаптированы и для других версий Visual Studio. Итак, для начала запустите Visual Studio и создайте новый проект. Тип проекта «Visual C++» > «MFC/ATL» > «Приложение MFC» :
На следующем шаге вы увидите окно с большим набором различных опций, влияющих на итоговый исходный код, который будет автоматически сгенерирован по завершению работы мастера настройки. На следующем скриншоте показано, какие параметры необходимо выбрать, чтобы получить то, что нам нужно:
Затем в следующих окнах оставляйте всё как есть, пока не доберетесь до окна:
Далее мы переходим на страницу «Дополнительные функции» :
Далее рассмотрим последнюю страницу мастера настройки MFC-приложений, на которой можно увидеть список созданных классов:
В результате будут автоматически сгенерированы 4 класса, которые станут основными классами в нашей игре.
Сейчас быстренько пройдемся по списку и поговорим, для чего используется каждый тип представления:
CEditView — это общее представление, которое состоит из простого текстового поля.
CFormView — позволяет разработчику вставлять в него другие основные элементы управления, т.е. поля редактирования, поля со списком, кнопки и т.д.
CHtmlEditView — имеет HTML-редактор, встроенный в представление.
CHtmlView — вставляет элемент управления — браузер Internet Explorer.
CListView — имеет область, похожую на окно Проводника со списками и значками.
CRichEditView — похож на редактор WordPad; позволяет не только вводить текст, но и форматировать его, изменять цвет и тому подобное.
CTreeView — вставляет элемент управления древовидной структурой.
Завершение работы мастера приложений MFC приведет к созданию и запуску приложения MFC. Поскольку мы еще не написали никакого кода, то увидим окно, в котором ничего нет, но все равно это полностью функционирующее приложение. Ниже приведен скриншот того, как должно выглядеть ваше базовое приложение (чтобы скомпилировать программу, нужно перейти в меню Visual Studio «Отладка» > «Запуск без отладки» ):
Пишем игры на C++, Часть 1/3 — Написание мини-фреймворка
На хабре не очень много уроков по созданию игр, почему бы не поддержать отечественных девелоперов?
Представляю вам свои уроки, которые учат создавать игры на C++ с использованием SDL!
Что нужно знать
О чем эта часть?
В следующих постах будет больше экшена, это лишь подготовка 🙂
Почему SDL?
Я выбрал эту библиотеку как наиболее легкую и быструю в освоении. Действительно, от первой прочитанной статьи по OpenGL или DirectX до стотысячного переиздания змейки пройдет немало времени.
Теперь можно стартовать.
1.1. Начало начал
Скачиваем SDL с официального сайта.
Создаем проект Win32 в Visual Studio, подключаем lib’ы и includ’ы SDL (если вы не умеете этого делать, то гугл вам в помощь!)
Также необходимо использовать многобайтную кодировку символов. Для этого идем в Проект->Свойства->Свойства конфигурации->Набор символов->Использовать многобайтную кодировку.
Создаем файл main.cpp
Пока что он ничего не делает.
Царь и бог каркаса — класс Game
Game.h
Создаем файл Project.h, он нам очень пригодится в будущем
Уже чуточку получше, но все равно как-то не густо.
1.2. Графика
Создаем аж 2 класса — Graphics для отрисовки графики и Image для отрисовки картинок
SDL_Surface — класс из SDL для хранения информации об картинке
Рассмотрим Graphics
NewImage — есть 2 варианта загрузки картинки. Первый вариант просто грузит картинку, а второй после этого еще и дает прозрачность картинке. Если у нас красный фон в картинке, то вводим r=255,g=0,b=0
DrawImage — тоже 2 варианта отрисовки картинки. Первый рисует всю картинку целиком, второй только часть картинки. startX, startY — координаты начала части картинки. endX, endY — конечные координаты части картинки. Этот метод рисования применяется, если используются атласы картинок. Вот пример атласа:
(изображение взято из веб-ресурса interesnoe.info)
Рассмотрим Image
Он просто держит свой сурфейс и дает право доступа к своим закрытым членам классу Graphics, а он изменяет сурфейс.
По сути, это обертка над SDL_Surface. Также он дает размер картинки
В конструкторе инициализируется SDL и создается экран.
Функция Flip должна вызываться каждый раз после отрисовки картинок, она представляет получившееся на экран и чистит экран в черный цвет для дальнешней отрисовки.
Остальные функции малоинтересны, рекомендую разобраться в них самому
Нет, вы все правильно делаете, этот файл и должен быть таким 🙂
Надо изменить Game.h, Game.cpp и main.cpp
Game.h
Тут мы добавляем указатель на Graphics и в Execute добавляем размер экрана
Ничего особенного, разве что не пропустите функцию SDL_Quit для очистки SDL
Тут мы создаем экран размером 500 на 350.
1.3. Ввод
Надо поработать со вводом с клавиатуры
SDL_Event — класс какого-нибудь события, его мы держим в Input’е для того, чтобы не создавать объект этого класса каждый цикл
Ниже расположены методы, не представляющие особого интереса. Примечание: методы с окончанием Down вызываются, когда клавиша была нажата, а с окончанием Up — когда опущена.
Здесь мы обрабатываем наш объект событий в функции Update, а остальные функции просто проверяют тип события и его значения.
Изменяем теперь Game.h и Game.cpp
Как видно, мы добавили указатель на Input и создали методы-возвращатели Graphics и Input
1.4. Итоги
Это был первый урок. Если вы дошли до этого места, я вас поздравляю! У вас есть воля, присущая программисту 🙂 Смотрите ссылки в начале статьи на последующие уроки для того, чтобы узнать еще много нового!
Введение в программирование: простой 3D-шутер с нуля за выходные, часть 1
Этот текст предназначен для тех, кто только осваивает программирование. Основная идея в том, чтобы показать этап за этапом, как можно самостоятельно сделать игру à la Wolfenstein 3D. Внимание, я совершенно не собираюсь соревноваться с Кармаком, он гений и его код прекрасен. Я же целюсь совсем в другое место: я использую огромную вычислительную мощность современных компьютеров для того, чтобы студенты могли создавать забавные проекты за несколько дней, не погрязая в дебрях оптимизации. Я специально пишу медленный код, так как он существенно короче и просто понятнее. Кармак пишет 0x5f3759df, я же пишу 1/sqrt(x). Мы преследуем разные цели.
Я убеждён, что хороший программист получается только из того, кто кодит дома в своё удовольствие, а не только просиживает штаны на парах в университете. В нашем университете программистов учат на бесконечной череде всяких библиотечных каталогов и прочей скукоте. Брр. Моя цель — показать примеры проектов, которые интересно программировать. Это замкнутый круг: если интересно делать проект, то человек проводит над ним немало времени, набирается опыта, и видит вокруг ещё больше интересного (оно же стало доступнее!), и снова погружается в новый проект. Это называется проектное обучение, вокруг сплошной профит.
Простыня получилась длинная, поэтому я разбил текст на две части:
Это не законченная игра, но только заготовка для студентов. Пример законченной игры, написанной двумя первокурсниками, смотрите во второй части.
Получается, я совсем чуточку вас обманул, я не расскажу как сделать полную игру за одни выходные. Я сделал только 3Д движок. Монстры у меня не бегают, да и главный персонаж не стреляет. Но, по крайней мере, этот движок я написал за одну субботу, можете проверить историю коммитов. В принципе, воскресенья вполне достаточно, чтобы сделать нечто играбельное, то есть, в одни выходные можно уложиться.
На момент написания этого текста репозиторий содержит 486 строк кода:
Проект зависит от SDL2, но вообще оконный интерфейс и обработка событий от клавиатуры появляются довольно поздно, в полночь субботы :), когда весь код рендеринга уже сделан.
Итак, я разбиваю весь код на этапы, стартуя с голого компилятора C++. Как и в предыдущих моих статьях по графике (тыц, тыц, тыц), я придерживаюсь правила «один этап = один коммит», так как github позволяет очень удобно просматривать историю изменений кода.
Этап 1: сохранение картинки на диск
Итак, поехали. До оконного интерфейса нам ещё очень далеко, для начала мы будем просто сохранять картинки на диск. Итого, нам нужно уметь хранить картинку в памяти компьютера и сохранять её на диск в формате, который поймёт какая-нибудь сторонняя программа. Я хочу получить вот такой файл:
Вот так выглядит полный C++ код, который рисует то, что нам нужно:
Если у вас под рукой нет компилятора, то это не беда, при наличии учётной записи на гитхабе этот код можно посмотреть, отредактировать и запустить (sic!) в один клик прямо из браузера.
По этой ссылке gitpod создаст для вас виртуальную машину, запустит VS Code, и откроет терминал на удалённой машине. В истории команд терминала (ткните в консоль и нажмите стрелку вверх) уже полный набор команд, который позволяют скомпилировать код, его запустить и открыть результирующую картинку.
Итак, что нужно понять из этого кода. Первое, цвета я храню в четырёхбайтном целочисленном типе uint32_t. Каждый байт — это компонента R, G, B или A. функции pack_color() и unpack_color() позволяют добираться до индивидуальных компонент каждого цвета.
Этап 2: рисуем карту уровня
Нам нужна карта нашего мира. На этом этапе я хочу всего лишь определить структуру данных и нарисовать карту на экране. Примерно так оно должно выглядеть:
Внесённые изменения можно посмотреть тут. Там всё просто: я захардкодил карту в одномерный массив символов, определил функцию отрисовки прямоугольника, да прошёлся по карте, отрисовав каждую клеточку.
Напоминаю, что вот эта кнопка даст запустить код прямо на этом этапе:
Этап 3: добавляем игрока
Что нам нужно, чтобы уметь нарисовать игрока на карте? GPS координат достаточно 🙂
Добавляем две переменные x и y, и отрисовываем игрока в соответствующем месте:
Внесённые изменения можно посмотреть тут. Про гитпод больше напоминать не буду 🙂
Этап 4: виртуальный дальномер aka трассировка первого луча
Помимо координат игрока нам неплохо было бы ещё знать, в каком направлении он смотрит. Потому добавим ещё одну переменную player_a, которая даёт направление взгляда игрока (угол между направлением взгляда и осью абсцисс):
А теперь я хочу иметь возможность скользить вдоль оранжевого луча. Как это делать? Предельно просто. Давайте рассмотрим зелёный прямоугольный треугольник. Мы знаем, что cos(player_a) = a/c, и что sin(player_a) = b/c.
Что будет, если я произвольно возьму значение c (положительное) и посчитаю x = player_x + c*cos(player_a) и y = player_y + c*sin(player_a)? Мы окажемся в фиолетовой точке; варьируя параметр c от нуля до бесконечности, мы можем заставить скользить эту фиолетовую точку вдоль нашего оранжевого луча, причём c — это расстояние от (x,y) до (player_x, player_y)!
Сердце нашего графического движка — это вот такой цикл:
Мы двигаем точку (x,y) вдоль луча, если она натыкается на препятствие на карте, то прерываем цикл, и переменная c даёт расстояние до препятствия! Чем не лазерный дальномер?
Этап 5: сектор обзора
Один луч это прекрасно, но всё же наши глаза видят целый сектор. Давайте назовём угол обзора fov (field of view):
И выпустим 512 лучей (кстати, почему 512?), плавно заметая весь сектор обзора:
Внесённые изменения можно посмотреть тут.
Этап 6: 3Д!
А теперь ключевой момент. Для каждого из 512 лучей мы получили расстояние до ближайшего препятствия, так? А теперь давайте сделаем вторую картинку шириной (спойлер) 512 пикселей; в которой мы для каждого луча будем рисовать один вертикальный отрезок, причём высота отрезка обратно пропорциональна расстоянию до препятствия:
Ещё раз, это ключевой момент создания иллюзии 3Д, убедитесь, что вы понимаете, о чём идёт речь. Рисуя вертикальные отрезки, по факту, мы рисуем частокол, где высота каждого кола тем меньше, чем дальше он от нас находится:
Этап 7: первая анимация
На этом этапе мы впервые рисуем что-то динамическое (я просто скидываю на диск 360 картинок). Всё тривиально: я изменяю player_a, отрисовываю картинку, сохраняю, изменяю player_a, отрисовываю, сохраняю. Чтобы было чуть веселее, я каждому типу клетки в нашей карте присвоил случайное значение цвета.
Внесённые изменения можно посмотреть тут.
Этап 8: коррекция «рыбьего глаза»
Вы обратили внимание, какой отличный эффект «рыбьего глаза» у нас получается, когда мы смотрим на стенку вблизи? Примерно вот так оно выглядит:
Почему? Да очень просто. Вот мы смотрим на стенку:
Для отрисовки нашей стены мы заметаем фиолетовым лучом наш синий сектор обзора. Возьмём конкретное значение направления луча, как на этой картинке. Длина оранжевого отрезка явно меньше длины фиолетового. Поскольку для определения высоты каждого вертикального отрезка, что мы рисуем на экране, мы делим на расстояние до преграды, рыбий глаз вполне закономерен.
Скорректировать это искажение совсем несложно, посмотрите, как это делается. Пожалуйста, убедитесь, что вы понимаете, откуда там взялся косинус. Нарисовать схему на листочке сильно помогает.
Этап 9: загрузка файла текстур
Настало время разбираться с текстурами. Мне лениво самостоятельно писать загрузчик изображений, поэтому я взял прекрасную библиотеку stb. Я подготовил файл с текстурами для стен, все текстуры квадратные и упакованы в изображение по горизонтали:
На этом этапе я просто гружу текстуры в память. Чтобы проверить работоспособность написанного кода, просто рисую как есть текстуру с индексом 5 в левом верхнем углу экрана:
Внесённые изменения можно посмотреть тут.
Этап 10: рудиментарное использование текстур
Теперь я выкидываю случайно сгенерированные цвета и подкрашиваю мои стены, взяв левый верхний пиксель из соответствующей текстуры:
Внесённые изменения можно посмотреть тут.
Этап 11: текстурируем стены по-настоящему
А вот теперь настал долгожданный момент, когда мы наконец-то увидим кирпичные стены:
Основная идея очень простая: вот мы скользим вдоль текущего луча и останавливаемся в точке x,y. Давайте предположим, что мы остановились на «горизонтальной» стене, тогда y почти целочисленнен (не совсем, т.к. наш способ движения вдоль луча вносит небольшую ошибку). Давайте возьмём дробную часть от x и назовём её hitx. Дробная часть меньше единицы, следовательно, если мы умножим hitx на размер текстуры (у меня 64), то это нам даст столбец текстуры, который нужно нарисовать в этом месте. Осталось его растянуть до нужного размера и дело в шляпе:
В общем, идея крайне примитивная, но требует аккуратного исполнения, так как у нас есть ещё и «вертикальные» стены (те, у которых hitx будет близок к нулю [x целочисленный]). Для них столбец текстуры определяется hity, дробной частью от y. Внесённые изменения можно посмотреть тут.
Этап 12: время рефакторить!
На этом этапе я ничего нового не стал делать, просто занялся генеральной уборкой. До сего момента у меня был один гигантский (185 строк!) файл, и в нём стало трудно работать. Поэтому я его разбил на тучу мелких, к сожалению, попутно почти удвоив размер кода (319 строк), не добавив никакой функциональности. Но зато стало гораздо удобнее пользоваться, например, чтобы сгенерировать анимацию, достаточно сделать вот такой цикл:
Ну а вот результат:
Внесённые изменения можно посмотреть тут.
Пишем игровую логику на C#. Часть 1/2
Всем привет. В связи с выходом моей игры SpaceLab на GreenLight я решил начать серию статей о разработке игры на C#/Unity. Она будет основываться на реальном опыте её разработки и немного отличаться от стандартных гайдов для новичков:
Во-первых, я не буду повторять документацию иными словами.
Во-вторых, необходимо знание программирования, чтобы понять о чем я пишу.
К сожалению, эта статья не сможет вам помочь, если вы хотите создать свою казуальную игру используя лишь мышь.
Зато я шаг за шагом расскажу о создании движка, на котором будет работать игровая логика нашей экономической стратегии.
Для тех, кто любит спойлеры или просто хочет почитать код — в конце есть ссылка не репозиторий, где каждый пункт добавлен отдельным коммитом.
Кого заинтересовало узнать, что за игра — внизу есть видео и ссылка на бесплатное скачивание.
Сразу предупрежу — у меня нету цели идеально применить огромное количество паттернов или описать подход к методологии TTD. В статье я стараюсь писать читабельный, поддерживаемый и безбажный код, как он писался бы в жизни. Возможно, людям имеющим огромный скилл в C# и написании игр данная статья покажется очевидной. Тем не менее, вопрос о том, как писать гейм-логику я слышал довольно часто и эта статья прекрасно подойдет и тем, кому интересно написание сервера и тем, кому интересно написание клиента на Unity.
Краткое описание GD, которого мы хотим достичь
1. Игрок управляет кораблем. В корабле можно выстраивать комнаты, в комнатах можно добавлять в слоты модули.
2. Для постройки чего-либо необходимо потратить ресурсы и подождать время.
Через полгода разработки результат должен выглядеть как-то так)
План работы
1. Настраиваем проекты
2. Создаем ядро — базовые сооружения
3. Добавляем и тестируем первые команды — построить строение и модуль
4. Выносим настройки строений и модулей в отдельный файл
5. Добавляем течение времени
6. Добавляем Constructible, строения теперь строятся некоторое время
7. Добавляем ресурсы, для постройки необходимы ресурсы
8. Добавляем цикл производства — модуль потребляет и выдает ресурсы
Статья получилась очень объемной, потому пришлось разделить ее на две части. В данной части мы сделаем первые пять пунктов, а во второй части закончим
1. Настраиваем проекты
На первых порах Unity Editor нам не понадобится — мы пишем ГеймЛогику. Открываем VS и создаем два проекта: GаameLogic и LogicTests (Unit Tests Project). В первом мы будем писать собственно логику игры на чистом C# не используя namespace Unity, второй будет тестить нашу логику встроенной тест-тулзой. Добавим в GameLogic первый класс Core и напишем первый тест, чтобы проверить нашу связку:
2. Создаем ядро — базовые сооружения
Что ж, это указывает, что настроили мы корректно и можно переходить к программированию логики.
Итак, разберемся с нашим гейм-дизайном. У нас есть корабль (Ship), в нем комнаты (Room), в каждую комнату может быть построено строение (Building), а в каждом строении могут быть модули (Module). Конечно, Room и Building можно было бы объединить в одну сущность, но далее такое разделение нам только поможет.
Для всех этих сооружений я создам отдельный namespace Architecture и базовые классы. А так же enum для индексов комнат. Многие вещи, которые мы сейчас делаем — временные и необходимы, чтобы запустить первый тест гейм-логики.
3. Добавляем и тестируем первые команды — построить строение и модуль
Теперь мы сможем написать первую «фичу» — постройка строения и постройка модуля в нем. Все подобные действия я буду описывать отдельным классом, который будет наследоваться от класса Command:
И хотя сейчас даже такая маленькая структура излишня — чуть позже благодаря ей мы прикрутим необходимые нам события. А существование каждого атомарного действия в отдельной команде позволит нам их комбинировать. Напишем наши первые два действия:
Пришло время посмотреть, работает ли наш движок. В тестах создаем ядро, пробуем построить комнату, а в нее пытаемся построить модуль. Кроме этого стоит добавить проверку, что нельзя построить то, чего гейм-логика не должна позволять строить:
4. Выносим настройки строений и модулей в отдельный файл
К счастью, наши тесты прекрасно проходятся. Теперь нам необходима возможность линейно расширять количество строений и модулей — для этого необходимо сделать следующее:
Как можно понять, теперь наш код нерабочий. Для того, чтобы не таскать каждый раз с собой конфиги создадим фабрику, которая будет выпускать наши сооружения зная только их тип. Я знаю, что название пока слишком общее, но мы всегда с легкостью можем его переименовать благодаря IDE, так же, как и разделить на две фабрики:
Я сразу добавил несколько строений и модулей, чтобы можно было покрыть тестами. И сразу скажу — да, хранить все эти настройки в фабрике нету никакого смысла. Они будут лежать отдельно в JSON файлах, по одному на структуру, парсится и передаваться в фабрику. К счастью, у нас движок даже не заметит этого изменения. Ну а пока нам не так критично вынести их в ЖСОНы, как запустить тесты и проверить все ли корректно работает. К счастью, да. Заодно допишем тесты, что нельзя построить модуль не в той комнате, например, Furnace в PowerPlant.
Увы, как вы можете догадаться, никто логику проверки не писал. Добавим условие валидации в команду постройки модуля и после этого успешно пройдем тест:
Что ж, теперь все корректно. Заодно добавим тесты на корректную работу лимитов и пойдем дальше.
5. Добавляем течение времени
Компьютеры дискретны. И все игры дискретны. Если говорить просто, то представим, что все игры — пошаговые. У большинства игр шаги пропускаются автоматически и 60 раз в секунду. Такие игры называются риалтайм. Я понимаю, что это очень грубо, но для реализации гейм-логики довольно удобно представлять, что ваша игра — пошаговая и мыслить такими категориями. А потом уже на клиенте можно запустить tween между двумя состояниями и юзеру будет красиво и игра будет работать быстро. Для начала введем понятие хода:
А также введем команду, которая позволяет переключать хода. Я сразу добавил команду, которая позволяет переключить несколько ходов — будет довольно удобно во время тестирования. В тестах одним выстрелом покроем сразу двух зайцев.
Забегая далеко вперед напишу, как сделать переключалку скоростей в игру, которая позволит нам запускаться с разной скоростью:
Теперь в Unity достаточно будет подвесится на любой Update и передавать дельта время в наш TimeWarp:
Продолжение следует.
В следующей статье мы закончим создание работоспособной основы для нашего движка, реализовав следующие пункты:
6. Добавляем Constructible, строения теперь строятся некоторое время
7. Добавляем ресурсы, для постройки необходимы ресурсы
8. Добавляем цикл производства — модуль потребляет и выдает ресурсы
Для тех, кто просто любит код — есть отдельный репозиторий на ГитХаб
Кроме этого, если вас интересуют вопросы по разработке SpaceLab — задавайте, отвечу на них в комментариях или в отдельной статье
Скачать для Windows, Linux, Mac бесплатно и без СМС можно со страницы SpaceLab на GreenLight