Этот вопрос является «дополнительным» из моего предыдущего вопроса об обнаружении и разрешении столкновений, который вы можете найти здесь .
Если вы не хотите читать предыдущий вопрос, вот краткое описание того, как работает мой физический движок:
Каждый физический объект хранится в классе с именем SSSPBody.
Поддерживаются только AABB.
Каждый SSSPBody хранится в классе под названием SSSPWorld, который обновляет каждое тело и обрабатывает гравитацию.
Каждый кадр, SSSPWorld обновляет каждое тело.
Каждое обновленное тело ищет близлежащие тела в пространственном хеше, проверяет, нужно ли им обнаруживать столкновения с ними. Если да, они вызывают событие «столкновения» и проверяют, нужно ли им разрешать столкновения с ними. Если да, они рассчитывают вектор проникновения и направленное перекрытие, затем меняют свое положение, чтобы разрешить проникновение.
Когда тело сталкивается с другим, оно передает свою скорость другому, просто устанавливая скорость тела на свою собственную.
Скорость тела установлена в 0, если она не изменила положение с последнего кадра. Если он также сталкивается с движущимся телом (например, лифтом или движущимися платформами), он рассчитывает разницу движения лифта, чтобы увидеть, не было ли тело перемещено из своего последнего положения.
Кроме того, тело вызывает «раздавленное» событие, когда все его углы AABB перекрывают что-либо в кадре.
Это ПОЛНЫЙ исходный код моей игры. Он разделен на три проекта. SFMLStart - это простая библиотека, обрабатывающая ввод, отрисовку и обновление сущностей. SFMLStartPhysics является наиболее важным, где классы SSSPBody и SSSPWorld. PlatformerPhysicsTest - игровой проект, содержащий всю игровую логику.
И это метод "update" в классе SSSPBody, прокомментированный и упрощенный. Вы можете взглянуть только на это, если вам не хочется смотреть на весь проект SFMLStartSimplePhysics. (И даже если вы это сделаете, вы все равно должны взглянуть на это, поскольку он прокомментирован.)
.Gif показывает две проблемы.
- Если тела размещены в другом порядке, получаются разные результаты. Ящики слева идентичны ящикам справа, размещены только в обратном порядке (в редакторе).
- Оба ящика должны быть продвинуты к верхней части экрана. В ситуации слева ящики не приводятся в движение. Справа только один из них. Обе ситуации являются непреднамеренными.
Первая проблема: порядок обновления
Это довольно просто понять. В ситуации слева самый верхний ящик обновляется раньше другого. Даже если ящик снизу «передает» скорость другому, ему нужно подождать, пока следующий кадр не сдвинется. Поскольку он не двигался, скорость нижнего ящика установлена на 0.
Я понятия не имею, как это исправить. Я бы предпочел, чтобы решение не зависело от «сортировки» списка обновлений, потому что я чувствую, что делаю что-то не так во всей конструкции физического движка.
Как основные физические движки (Box2D, Bullet, Chipmunk) обрабатывают порядок обновления?
Вторая проблема: только один ящик движется к потолку
Я пока не понимаю, почему это происходит. То, что делает «пружинная» сущность, это установить скорость тела на -4000 и переместить ее поверх самой пружины. Даже если я отключу код повторного позиционирования, проблема все равно возникает.
Моя идея состоит в том, что когда нижний ящик сталкивается с верхним, его скорость устанавливается равной 0. Я не уверен, почему это происходит.
Несмотря на возможность выглядеть как кто-то, кто сдается из-за первой проблемы, я разместил весь исходный код проекта выше. У меня нет ничего, чтобы доказать это, но, поверьте мне, я изо всех сил пытался это исправить, но я просто не мог найти решение, и у меня нет никакого предыдущего опыта с физикой и столкновениями. Я пытался решить эти две проблемы больше недели, и теперь я в отчаянии.
Я не думаю, что смогу найти решение самостоятельно, не убрав из игры многие функции (например, передачу скорости и пружины).
Большое спасибо за время, потраченное на чтение этого вопроса, и еще больше спасибо, если вы даже попытаетесь найти решение или предложение.