Главная » Правописание слов » Как написать свой движок для игры

Слово Как написать свой движок для игры - однокоренные слова и морфемный разбор слова (приставка, корень, суффикс, окончание):


Морфемный разбор слова:

Однокоренные слова к слову:

Свой скриптовый движок для игр средствами С++ и Lua (часть — 1)

Предисловие

Что нужно?

Как все устроено?

Вся игровая логика будет программироваться в файле, например — «main.lua». Движок будет читать этот файл и исполнять действия описанные в этом файле. Вывод графики будет с помощью SDL 2.0, физика — Box2D, аудио — OpenAl, скриптинг — Lua. IDE — Microsoft Visual Studio любой версии.

Нарисовал схему

Начинаем!

Сначала надо скачать:

Заполняем пока таким образом:

Компилируем, если скомпилировалось, идем дальше. Жмем «Project → project properties». Выбираем «C/C++ → General» и добавляем дополнительные папки включения (указывайте путь где вы извлекли из архива Lua). Указываем путь к «include» Lua.

После этого заходим «Linker → General» и добавляем путь к либе.

Применяем и изменяем «main.cpp»

Компилируем, идем дальше. Далее нам нужно создать отдельный заголовочный файл, в котором будет основная часть движка. Добавляем файл «Engine.h». И сразу заполняем его таким образом.

Компилируем, если нет ошибок, идем дальше, если же есть, значит вы где- то накосячили. Изменяем «main.cpp»:

Компилируем, если без ошибок, двигаемся дальше. Создаем в папке проекта текстовый файл «main.lua». Заполняем его так:

Компилируем, бросаем «lua5*.dll» в папку проекта, запускаем, и Оппа! В консоле вывело «Lua inited!». По сути мы написали простой Lua — интерпретатор. В второй части приступим к выводу графики.

Источник

Как написать собственный игровой движок на C++

Перевод статьи Джеффа Прешинга (Jeff Preshing) How to Write Your Own C++ Game Engine.

Как написать собственный игровой движок на C++

В последнее время я занят тем, что пишу игровой движок на C++. Я пользуюсь им для создания небольшой мобильной игры Hop Out. Вот ролик, записанный с моего iPhone 6. (Можете включить звук!)

Hop Out — та игра, в которую мне хочется играть самому: ретро-аркада с мультяшной 3D-графикой. Цель игры — перекрасить каждую из платформ, как в Q*Bert.

Hop Out всё ещё в разработке, но движок, который приводит её в действие, начинает принимать зрелые очертания, так что я решил поделиться здесь несколькими советами о разработке движка.

С чего бы кому-то хотеть написать игровой движок? Возможных причин много:

Игровые платформы в 2017-ом — мобильные, консоли и ПК — очень мощные и во многом похожи друг на друга. Разработка игрового движка перестала быть борьбой со слабым и редким железом, как это было в прошлом. По-моему, теперь это скорее борьба со сложностью вашего собственного произведения. Запросто можно сотворить монстра! Вот почему все советы в этой статье вращаются вокруг того, как сохранить код управляемым. Я объединил их в три группы:

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

Используйте итеративный подход

Мой первый совет — не задерживаясь заставьте что-нибудь (что угодно!) работать, затем повторите.

Вуаля! У меня появился замечательный вращающийся кубик, использующий OpenGL ES 2.0.

Моим следующим шагом было скачивание сделанной кем-то 3D-модели Марио. Я быстро написал черновой загрузчик OBJ-файлов — этот формат не так уж сложен — и подправил пример, чтобы он отрисовывал Марио вместо кубика. Ещё я интегрировал SDL_Image, чтобы загружать текстуры.

Затем я реализовал управление двумя стиками, чтобы перемещать Марио. (Поначалу я рассматривал идею создания dual-stick шутера. Впрочем, не с Марио).

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

К тому моменту я отказался от формата OBJ и написал скрипт на Python для экспорта собственных JSON-файлов из Blender. Эти JSON-файлы описывали заскиненный меш, скелет и данные анимации. Я загружал эти файлы в игру с помощью библиотеки C++ JSON.

Как только всё заработало, я вернулся в Blender и создал более проработанного персонажа (Это был первый сделанный и зариганный мной трёхмерный человек. Я им весьма гордился.)

В течение следующих нескольких месяцев я сделал такие шаги:

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

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

Готов поспорить, что больше времени тратится при противоположном подходе: пытаться заранее продумать архитектуру, которая будет делать всё, что вам понадобится. Две моих любимых статьи про опасности чрезмерной инженерии — The Vicious Circle of Generalization Томаша Дабровски и Don’t Let Architecture Astronauts Scare You Джоэла Спольски.

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

Итеративный подход дал мне куда более элегантную архитектуру, чем я мог бы вообразить, глядя на чистый лист бумаги. iOS-сборка моего движка сегодня на 100% состоит из оригинального кода, включая собственную математическую библиотеку, шаблоны контейнеров, систему рефлексии/сериализации, фреймворк рендеринга, физику и аудио микшер. У меня были причины писать каждый из этих модулей самостоятельно, но для вас это может быть необязательным. Вместо этого есть множество отличных библиотек с открытым исходным кодом и разрешительной лицензией, которые могут оказаться подходящими вашему движку. GLM, Bullet Physics и STB headers — лишь некоторые из интересных примеров.

Дважды подумайте, прежде чем слишком обобщать

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

Время от времени нарушайте принцип DRY

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

Использовать разные соглашения о вызове — это нормально

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

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

Осознайте, что сериализация — обширная тема

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

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

Можно писать более гибкий, менее подверженный ошибкам код сериализации, пользуясь преимуществом рефлексии — а именно, созданием данных времени выполнения, описывающих расположение ваших C++ типов. Чтобы получить краткое представление о том, как рефлексия может помочь с сериализацией, взглянем на то, как это делает Blender, проект с открытым исходным кодом.

Как и Blender, многие игровые движки — и связанные с ними инструменты — создают и используют собственные данные рефлексии. Есть много способов делать это: вы можете разбирать собственный исходный код на C/C++, чтобы извлечь информацию о типах, как это делает Blender. Можете создать отдельный язык описания данных и написать инструмент для генерации описаний типов и данных рефлексии C++ из этого языка. Можете использовать макросы препроцессора и шаблоны C++ для генерации данных рефлексии во время выполнения. И как только у вас под рукой появятся данные рефлексии, открываются бесчисленные способы написать общий сериализатор поверх всего этого.

Несомненно, я упускаю множество деталей. В этой статье я хотел только показать, что есть много способов сериализовать данные, некоторые из которых очень сложны. Программисты просто не обсуждают сериализацию столько же, сколько другие системы движка, даже несмотря на то, что большинство других систем зависят от неё. Например, из 96 программистских докладов GDC 2017, я насчитал 31 доклад о графике, 11 об онлайне, 10 об инструментах, 3 о физике, 2 об аудио — и только один, касающийся непосредственно сериализации.

Как минимум, постарайтесь представить, насколько сложными будут ваши требования. Если вы делаете маленькую игру вроде Flappy Bird, с несколькими ассетами, вам скорее всего не придётся много думать о сериализации. Вероятно, вы можете загружать текстуры напрямую из PNG и этого будет достаточно. Если вам нужен компактный бинарный формат с обратной совместимостью, но вы не хотите разрабатывать свой — взгляните на сторонние библиотеки, такие как Cereal или Boost.Serialization. Не думаю, что Google Protocol Buffers идеально подходят для сериализации игровых ресурсов, но они всё равно стоят изучения.

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

Я люблю сравнивать наблюдения по этой теме, так что мне очень интересно услышать мнение других разработчиков. Если вы писали движок, привел ли ваш опыт к тем же выводам? А если не писали или ещё только собираетесь, ваши мысли мне тоже интересны. Что вы считаете хорошим ресурсом для обучения? Какие аспекты ещё кажутся вам загадочными? Не стесняйтесь оставлять комментарии ниже или свяжитесь со мной через Twitter.

Источник

Как написать свой игровой движок с нуля

Возможно, тема надоевшая, но я поискал в интернете на эту тему и понял что в интернете(youtube, yandex, habr) нет ничего полезного, вернее оно есть, но без объяснений.

Сразу скажу что, C# я знаю больше чем C++, просьба отталкивать от этого.

Что я подразумеваю под словом ‘с нуля’.
1. Нужно определиться с языком программирования. C++ или C#?
Если я напишу: «Мне нужен обоснованный ответ!», будет немного грубо.
По этому, желательно обосновать ответ и написать названия книг по выбранному языку.
Не нужно писать: вот C++ быстрее чем C#, пиши на C++ и т.д.
2. Какой фреймворк? (Если неправильно назвал поправьте)
OpenTK, GLFW и т.д. Источники, где можно поподробнее разобраться.
3. Что нужно знать в языке программирования что бы написать свой игровой движок?
Пример ответа: Нужно уметь пользоваться массивами, отладчиком, искать ошибки и т.д.
4. Ну и с чего стоит начать, после изучения языка.

Написать свой движок с нуля
Как написать свой движок с нуля при помощью C++. Заранее спасибо.

Можно ли в Visual Basic написать свой игровой движок
Здравствуйте господа программисты. Я хотел сделать свою игру, и для этого я искал разные движки.

Свой игровой движок
Я писал 3 раза игровой движок. Теперь предстоит четвертый. Подскажите, на чем лучшего его написать.

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

Ответ на твой вопрос зависит от того что ты хочешь получить на выхлопе?
По тому что если тебе нужен CryBiteUnrealUnity 10K5000 то запросы одни, а если тебе двиг для майнкрафта то запросы другие.

Добавлено через 1 час 0 минут
Я предположу, что ты делаешь CryBiteUnrealUnity 10K5000.

Те же фростбайты, анриалы, юнити и край энжины написаны на c/c++, сам сделай выводы.

У шарпа вообще плюсов нет :), помогите их найти? Единственный аргумент в таких спорах что я слышал, это дот нет и куча библиотек, так ведь у с++ тоже их море, один qt если вспомнить, а в контексте разработки с нуля с# не о чем

Опять же, если ты будешь писать свой серьезный движ то использовать сторонние библиотеки не будешь, по тому что все будешь писать под свои запросы. По тому openTK тебе не нужен, тебе нужно что-то типа glfw+gluw, которые только лишь создают окно и импортируют функции api opengl (ты же на opengl смотришь?), но можешь и по хардкору #include и самому импортировать функции и создавать окна.

Все что нужно знать об openGL есть тут.

Конкретно тебе нужно знать:
1.1) как создать окно
Первый самый простой этап.
2.1) ты должен узнать что такое шейдер, как его скомпилить на гпу, как его применить.
2.2) как создать vao (обязательно нужно разобраться как использовать несколько атрибутов), и как его выводить (рисовать), тут ты узнаешь что заходит на вход вершинному шейдеру и что выходит из фрагментного.

Тут ты уже поймешь как работает opengl, тебе станет очень радостно если ты добрался до сюда.

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

Вот от сюда будет начинаться что-то серьезное.
3.1) Нужно будет разобраться с тем что такое fbo, как его создавать, как его применять/чистить и как в него рендерить.
3.2) Зная что такое fbo, нужно будет в первый раз что то отрендерить в текстуру (тобишь в fbo), сделаешь тени.

Вот на этом моменте кончается 90% работы. Можешь начать с этого после изучения языка.

Потом ты еще должен будешь выбрать аудио апи аля OpenAl.

Что нужно знать о языке?
Само собой нужно уметь работать с массивами, циклами (for, while), блоками ветвлений (if/else, switch/case), структуры. Потом ты должен знать как алоцировать память динамически, аля new и delete, указатели ( не умные, а обычные, умные таковыми только называются).
Не плохо бы знать ооп (классы, наследование), опять же, перегрузка и таблицы виртуальных функций для риалтайма зло.

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

Источник

Создаём собственный физический 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 не будет опубликован. Обязательные поля помечены *