Как сделать свой движок для игры

Написать игровой движок на первом курсе: легко! (ну почти)

Привет! Меня зовут Глеб Марьин, я учусь на первом курсе бакалавриата «Прикладная математика и информатика» в Питерской Вышке. Во втором семестре все первокурсники нашей программы делают командные проекты по С++. Мы с моими партнерами по команде решили написать игровой движок.

О том, что у нас получается, читайте под катом.

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Всего нас в команде трое: я, Алексей Лучинин и Илья Онофрийчук. Никто из нас не является экспертом в разработке игр, а тем более в создании игровых движков. Для нас это первый большой проект: до него мы выполняли только домашние задания и лабораторные работы, так что едва ли профессионалы в области компьютерной графики найдут здесь новую для себя информацию. Мы будем рады, если наши идеи помогут тем, кто тоже хочет создать свой движок. Но тема эта сложна и многогранна, и статья ни в коем случае не претендует на полноту специализированной литературы.

Всем остальным, кому интересно узнать о нашей реализации, — приятного чтения!

Графика

Первое окно, мышь и клавиатура

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

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

Тут появился главный игровой цикл:

Hello World

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Камера

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

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

Начнем с получения координат объекта в базисе мира. С объектом можно делать три преобразования: масштабировать, поворачивать и перемещать. Все эти операции задаются домножением исходного вектора (координат в базисе объекта) на соответствующие матрицы. Тогда матрица Model будет выглядеть так:

Чтобы получить координаты вершины на экране, нужно перемножить вектор на матрицу по крайней мере пять раз. Все матрицы имеют размер 4 на 4, так что придется проделать довольно много операций умножения. Мы не хотим нагружать ядра процессора большим количеством простых задач. Для этого лучше подойдет видеокарта, у которой есть необходимые ресурсы. Значит, нужно написать шейдер: небольшую инструкцию для видеокарты. В OpenGL есть специальный шейдерный язык GLSL, похожий на C, который поможет нам это сделать. Не будем вдаваться в подробности написания шейдера, лучше наконец-то посмотрим на то, что вышло:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

Физика

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Текстуры

Для загрузки изображений мы использовали библиотеку DevIL. Каждому GraphicalObject2d стал соответствовать один экземпляр класса GraphicalPolygon — лицевая часть объекта — и GraphicalEdge — боковая часть. На каждую можно натянуть свою текстуру. Первый результат:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Все основное, что требуется от графики, уже готово: отрисовка, один источник освещения и текстуры. Графика — на данном этапе все.

Машина состояний, задание поведений объектов

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

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

И так далее, для каждой функции.

У состояния есть три стадии: оно началось, оно тикает, оно остановлено. К каждой из стадий можно добавлять какие-то действия, например, прикрепить к объекту текстуру, применить к нему импульс, установить скорость и так далее.

Сохранения

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

На самом деле, игра и редактор — это почти один и тот же класс, только в игре уровень загружается в режиме чтения, а в редакторе — в режиме записи. Для записи и чтения объектов из json-а движок использует библиотеку rapidjson.

Графический интерфейс

В какой-то момент перед нами встал вопрос: пусть уже написана графика, машина состояний и все прочее. Как пользователь сможет написать игру, используя это?

В графическом интерфейсе количество действий, которые можно произвести с объектом, будет ограничено: перелистнуть слайд анимации, применить силу, установить определенную скорость и так далее. Та же ситуация с переходами в машине состояний. В больших движках проблему ограниченного количества действий решают связыванием текущей программы с другой — например, в Unity и Godot используется связывание с C#. Уже из этого скрипта можно будет сделать что угодно: и посмотреть, в каком созвездии Уран, и какой сейчас курс евро. У нас такой функциональности на данный момент нет, но в наши планы входит связать движок с Python 3.

Для реализации графического интерфейса мы решили использовать Dear ImGui, потому что она очень маленькая (по сравнению с широко известным Qt) и писать на ней очень просто. ImGui — парадигма создания графического интерфейса. В ней каждую итерацию главного цикла все виджеты и окна отрисовываются заново только если это нужно. С одной стороны, это уменьшает объем потребляемой памяти, но с другой, скорее всего, занимает больше времени, чем одно выполнение сложной функции создания и сохранение нужной информации для последующего рисования. Тут уже осталось только реализовать интерфейсы для создания и редактирования.

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Редактор машины состояний

Заключение

Мы создали только основу, на которую можно вешать что-то более интересное. Иными словами, есть куда расти: можно реализовать отрисовку теней, возможность создания более чем одного источника освещения, можно связать движок с интерпретатором Python 3, чтобы писать скрипты для игры. Хотелось бы доработать интерфейс: сделать его красивее, добавить больше различных объектов, поддержку горячих клавиш…

Работы еще предстоит много, но мы довольны тем, что имеем на данный момент.

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

Источник

Пишем собственный игровой движок с помощью C++

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

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Подготовка Visual Studio

Создадим новый проект в Visual Studio. Обратите внимание, что проект требует библиотеку SFML, поэтому если вы не настраивали окружение для нее, прочтите сначала небольшое руководство по настройке.

Теперь можно приступить к коду. Исходный код и дополнительные ресурсы будут доступны на этой странице.

Проектируем собственный игровой движок

Самое важное – запуск движка, который будет происходить в файле Main.cpp, но им мы займемся немного позже.

Класс персонажа

Bob – простой класс для представления фигурки персонажа, управляемой игроком. Код класса будет легко расширяться, а что самое главное – его несложно переписать под любой другой игровой объект, который вы захотите добавить. Для этого потребуется заменить текстуру и описать поведение нового объекта в методе update().

Займемся заголовками класса. Выберите правой кнопкой Header Files в Solution Explorer и нажмите Add | New Item. В окне Add New Item выберите Header File (.h), затем в поле Name введите Bob. Нажмите Add и добавьте код заголовка класса:

Здесь мы объявили объекты типа Texture и Sprite. Дальше мы свяжем эти объекты и любое действие на экране с объектом Sprite будет сопровождаться изображением Боба:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Кликните правой кнопкой, чтобы сохранить

Bob.cpp

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

Выберите правой кнопкой мыши Source Files в Solution Explorer и откройте Add | New Item. В окне Add New Item кликните по C++ File (.cpp), а в поле Name укажите Bob.cpp. Теперь добавьте в файл код:

В конструкторе мы установили значение переменной m_Speed на 400. Это значит, что Боб пересечет экран шириной в 1920 пикселей за 5 секунд. Также мы загрузили файл Bob.png в Texture и связали его с объектом Sprite. В переменных m_Position.x и m_Position.y установлено начальное положение Боба.

Функция update обрабатывает два If. Первое If проверяет, нажата ли правая кнопка (m_RightPressed), а второе следит за левой (m_LeftPressed). В каждом If скорость (m_Speed) умножается на elapsedTime. Переменная elapsedTime рассчитывается в функции Start движка (класс Engine). Им мы и займемся далее.

Пишем класс Engine

Класс Engine будет контролировать все остальное.

Engine.h

Добавим заголовок. Откройте окно Add New Item (так же, как для класса Bob), выберите Header File (.h) и в поле Name введите Engine.h. Добавьте в файл следующий код:

Класс библиотеки SFML, RenderWIndow, используется для рендера всего, что есть на экране. Переменные Sprite и Texture нужны для создания фона. Также в заголовке мы создали экземпляр класса Bob.

Engine.cpp

В Engine.cpp мы опишем конструктор и функцию start. Создайте файл класса так же, как для Bob.cpp, и добавьте в него код:

Функция конструктора получает разрешение экрана и разворачивает игру на весь экран с помощью m_Window.create. В конструкторе же загружается Texture и связывается с объектом Sprite.

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Пример фонового изображения

Скачайте пример изображения или используйте любое другое на свое усмотрение. Переименуйте файл в background.jpg и поместите в каталог Simple Game Engine/Simple Game Engine.

Игровой цикл

Следующие три функции будут описаны каждая в своем файле, но при этом они должны быть частью Engine.h. Поэтому в начале каждого файла укажем директиву #include «Engine.h», так что Visual Studio будет знать, что мы делаем.

Обрабатываем пользовательский ввод

Создайте файл Input.cpp и добавьте в него код:

Функция input обрабатывает нажатия клавиш через константу Keyboard::isKeyPressed, предоставляемую SFML. При нажатии Escape m_Window будет закрыто. Для клавиш A и D вызывается соответствующая функция движения.

Обновляем игровые объекты

Теперь опишем простую функцию update. Каждый игровой объект будет иметь собственную функцию update.

Создайте файл Update.cpp и добавьте в него код:

Поскольку у нас пока только один объект «Боб», мы вызываем только функцию m_Bob.update.

Отрисовка сцены

Это последняя функция класса Engine. Создайте файл Draw.cpp и добавьте в него код:

Экран очищается методом clear, затем отрисовывается фон. Первым делом должен быть отрисован фон, чтобы потом поверх него можно было отрисовать Боба.

Запускаем движок в main()

Теперь вернемся к нашему Main.cpp. Время добавить в него немного кода:

Несколько слов в конце

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

Источник

Создаём собственный физический 2D-движок. Часть 1: основы и разрешение импульсов силы

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

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

В этой части туториала мы рассмотрим следующие темы:

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

Необходимые знания

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

Распознавание коллизий

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

Ограничивающий прямоугольник, выровненный по координатным осям

Ограничивающий прямоугольник, выровненный по координатным осям (Axis Aligned Bounding Box, AABB) — это прямоугольник, четыре оси которого выровнены относительно системы координат, в которой он находится. Это значит, что прямоугольник не может вращаться и всегда находится под углом в 90 градусов (обычно выровнен относительно экрана). Обычно его называют «ограничивающим прямоугольником», потому что AABB используются для ограничения других, более сложных форм.

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры
Пример AABB.

AABB сложной формы можно использовать как простую проверку того, могут ли пересекаться более сложные формы внутри AABB. Однако в случае большинства игр AABB используется как фундаментальная форма и на самом деле ничего не ограничивает. Структура AABB очень важна. Есть несколько способов задания AABB, вот моя любимая:

Эта форма позволяет задать AABB двумя точками. Точка min обозначает нижние границы по осям x и y, а max обозначает верхние границы — иными словами, они обозначают верхний левый и нижний правый углы. Чтобы определить, пересекаются ли два AABB, необходимо базовое понимание теоремы о разделяющей оси (Separating Axis Theorem, SAT).

Вот быстрая проверка, взятая с сайта Real-Time Collision Detection Кристера Эриксона, в которой используется SAT:

Окружности

Окружность задаётся радиусом и точкой. Вот как может выглядеть структура окружности:

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

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

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

Разрешение импульсов силы

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

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

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

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

Чтобы достигнуть такого эффекта и при этом следовать интуитивному пониманию того, как должны вести себя объекты, мы используем твёрдые тела и немного математики. Твёрдое тело — это просто форма, задаваемая пользователем (то есть вами, разработчиком), которая явно определяется как недеформируемая. И AABB, и окружности в этой статье недеформируемы, и всегда будут являться либо AABB, либо окружностью. Все сжатия и растяжения запрещены.

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

Объекты столкнулись — что дальше?

Предположим, что мы обнаружили столкновение двух тел. Как их разделить? Будем считать, что распознавание коллизий предоставляет нам две важные характеристики:

Теперь давайте подробно рассмотрим, как же вычислить величину импульса силы. Начнём с двух объектов, для которых обнаружено пересечение:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Теперь мы используем скалярное произведение. Скалярное произведение — это просто сумма покомпонентных произведений:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

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

Получив Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры, мы можем подставить его в уравнение вычисления величины импульса силы.

Ньютоновский закон восстановления гласит следующее:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Заметьте, что здесь появилось отрицательное значение. Notice how we introduced a negative sign here. По ньютоновскому закону восстановления Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры, результирующий вектор после отталкивания, действительно направляется в обратную сторону от V. Так как же представить противоположные направления в нашем уравнении? Ввести знак «минус».

Теперь нам нужно выразить эти скорости под воздействием импульса силы. Вот простое уравнение для изменения вектора на скаляр импульса силы Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрыв определённом направлении Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Три точки в форме треугольника (Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры) можно прочитать как «следовательно». Это обозначение используется для того, чтобы из предшествующего ему вывести истинность последующего.

Мы неплохо двигаемся! Однако нам нужно выразить импульс силы с помощью Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрыотносительно двух разных объектов. Во время коллизии объектов A и B объект A отталкивается в противоположном от B направлении:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Эти два уравнения отталкивают A от B вдоль единичного вектора направления Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрына скаляр импульса силы (величины Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры) Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры.

Всё это нужно для объединения уравнений 8 и 5. Конечное уравнение будет выглядеть примерно так:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Если помните, нашей исходной целью было изолировать величину, потому что мы знаем направление, в котором нужно разрешать коллизию (оно задаётся распознаванием коллизий), и нам осталось только определить величину в этом направлении. В нашем случае неизвестна величина Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры; нам нужно выделить Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрыи решить уравнение для неё.

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Ого, довольно много вычислений! Но на этом всё. Важно понимать, что в окончательной форме уравнения 10 слева у нас Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры(величина), а всё справа нам уже известно. Это значит, что мы можем написать пару строк кода для вычисления скаляра импульса силы Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры. И этот код гораздо более читаем, чем математическая запись!

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры
У двух объектов возникла коллизия, но скорость разделит их в следующем кадре. Не разрешаем этот тип коллизии.

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

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

И последнее, что нужно заметить, что мы должны с умом распределить наш скаляр импульса силы Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрына два объекта. Мы хотим, чтобы мелкие объекты отлетали от крупных с большей долей Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры, а скорости больших объектов изменялись на очень небольшую долю Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры.

Для этого можно сделать следующее:

Тонущие объекты

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

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

Значение «ноль» приведёт к верным вычислениям при разрешении импульсов силы. Это нас устраивает. Проблема тонущих объектов возникает, когда какой-нибудь объект начинает «тонуть» в другом из-за гравитации. Иногда объект с низкой упругостью ударяется о стену с бесконечной массой и начинает тонуть.

Такое утопание возникает из-за ошибок вычислений с плавающей запятой. Во время каждого вычисления с плавающей запятой добавляется небольшая ошибка из-за ограничений оборудования. (Подробнее см. [Floating point error IEEE754] в Google.) Со временем эта ошибка накапливается в ошибку позиционирования, что приводит к утоплению объектов друг в друге.

Для исправления этой ошибки позиционирования необходимо её учитывать, поэтому я покажу вам способ, называемый «линейным проецированием». Линейное проецирование на небольшой процент снижает проникновение двух объектов друг в друга. Оно выполняется после приложения импульса силы. Исправление положения выполняется очень просто: перемещаем каждый объект вдоль нормали коллизии Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игрына процент глубины проникновения:

Учтите, что мы масштабируем penetrationDepth на общую массу системы. Это даст нам коррекцию положения, пропорциональную величине массы. Мелкие объекты отталкиваются быстрее, чем тяжёлые.

Однако в этой реализации есть небольшая проблема: если мы всегда разрешаем ошибку позиционирования, то объекты всегда будут дрожать, пока они находятся друг на друге. Чтобы устранить дрожание, нужно задать небольшой допуск. Мы будем выполнять корректировку положения только если проникновение выше определённого произвольного порога, который мы назовём «погружением» («slop»):

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

Генерирование простого многообразия

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

Вот как выглядит объявление стандартного многообразия:

Во время распознавания коллизий необходимо вычислять проникновение и нормаль коллизии. Для определения этой информации необходимо расширить исходные алгоритмы распознавания коллизий из начала статьи.

Окружность-окружность

Давайте начнём с простейшего алгоритма коллизии: коллизия окружность-окружность. Эта проверка в большей степени тривиальна. Можете ли вы представить, каким будет направление разрешения коллизии? Это вектор от окружности A к окружности B. Его можно получить вычитанием положения B из положения A.

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

Вот полный пример алгоритма генерирования многообразия коллизии окружность-окружность:

AABB-AABB

Проверка AABB-AABB немного более сложна, чем окружность-окружность. Нормаль коллизии не будет вектором из A в B, а будет нормалью к ребру. AABB — это прямоугольник с четырьмя рёбрами. Каждое ребро имеет нормаль. Эта нормаль обозначает единичный вектор, перпендикулярный к ребру.

Исследуем общее уравнение прямой в 2D:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

В уравнении выше a и b — это вектор нормали к прямой, а вектор (a, b) считается нормализованным (длина вектора равна нулю). Нормаль коллизии (направление разрешения коллизии) будет направлена в сторону одной из нормалей рёбер.

Знаете ли вы, что обозначает c в общем уравнении прямой? c — это расстояния до начала координат. Как мы увидим в следующей части статьи, это очень полезно для проверки того, на какой стороне от прямой находится точка.

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

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры
Две оси проникновения; горизонтальная ось X — ось наименьшего проникновения, поэтому эту коллизию нужно разрешать вдоль оси X.

Вот полный алгоритм генерирования многообразия AABB-AABB и распознавания коллизий:

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры

Окружность-AABB

Последняя проверка, которую я рассмотрю — проверка окружность-AABB. Идея здесь заключается в том, чтобы вычислить ближайшую к окружности точку AABB; после этого проверка упрощается до чего-то вроде проверки окружность-окружность. После вычисления ближайшей точки и распознавания коллизий нормаль будет направлением к ближайшей точке из центра окружности. Глубина проникновения — это разность между расстояниями до ближайшей к окружности точки и радиусом окружности.

Как сделать свой движок для игры. Смотреть фото Как сделать свой движок для игры. Смотреть картинку Как сделать свой движок для игры. Картинка про Как сделать свой движок для игры. Фото Как сделать свой движок для игры
Схема пересечения AABB-окружность.

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

Заключение

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *