Как справиться с физикой движущихся платформ в платформер?

8

Итак, после нескольких часов поиска в интернете, я так и не нашел приятного ответа о том, как обращаться с движущимися платформами в игре на 2d-платформе. Поэтому я решил создать простой прототип, в котором вы будете взаимодействовать с двумя разными платформами, одна из которых будет двигаться вертикально, а другая - горизонтально. Я хотел бы помочь разобраться и посмотреть, что не работает, и как их исправить. Ниже я отправил файл .fla + .as, сопровождаемый ссылкой на воспроизводимый файл .swf.

Цель состоит в том, чтобы заставить Героя взаимодействовать с платформами, как если бы они были твердыми объектами, на которых он мог бы стоять, толкаться рядом, прыгать на / под и т. Д. И т. Д.

Проблемы с моим прототипом следующие:

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

  • Когда вы стоите на горизонтально движущейся платформе и прыгаете, вы двигаетесь вместе с платформой в воздухе (некоторые игры предпочитают, чтобы она была такой, но она не кажется естественной и здесь не нужна). Что может быть вызвано тем, что Герой сохранил скорость на оси Х от платформы.

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

  • Когда вы прыгаете на вертикально движущейся платформе, скорость по оси Y сохраняется, поэтому, когда вы уходите с платформы, вы падаете с более высокой скоростью. Со скоростью сохраняемой скорости + гравитация (это в основном потому, что я не могу придумать, как сбросить скорость по оси Y до 0, когда вы приземлитесь на платформу, без зависания игрока в воздухе).

Я начинающий программист, поэтому я уверен, что есть ЛУЧШИЕ способы сделать это, и я хотел бы услышать их все. Приветствуются любые идеи о том, как улучшить код или другие методы, с помощью которых вы можете реализовать перемещение платформ в игру на основе Tile. В конце концов, я пытаюсь найти надежный способ обработки движущихся платформ в 2d платформерах.

Воспроизводимый SWF: http://dl.dropbox.com/u/28271061/PlatformerhowtoFLA.html (перемещение с помощью клавиш со стрелками, переход с помощью клавиши X, запуск с помощью клавиши Z)

Исходный код AS-файла: http://dl.dropbox.com/u/28271061/Platformerhowto.as

SourcefileFLA: http://dl.dropbox.com/u/28271061/PlatformerhowtoFLA.fla

Если вы предпочитаете просто прочитать код через Pastie онлайн: http://pastie.org/2266764

Дитя
источник
Соответствующий (маловероятный дубликат): как мне управлять движущимися платформами в игровой платформе? ,
двойник
Я прочитал эту ветку, но поскольку я не использую узлы ни в коем случае, создается впечатление, что это не решило проблему. Игра, которую я создаю, основана на плитке, но движущиеся платформы будут реализованы, как описано выше (свободное перемещение). Использование узлов потребовало бы переписать мой движок в целом, на что я уже потратил много времени. Думаю, я надеялся, что кто-нибудь посмотрит на код и предложит решение, подобное предложенному, или найдет улучшение кода.
Малыш
Вы бы использовать узлы , как только вы реализовать это решение для движущихся платформ, даже если это единственное место , где вы их используете. Это решило бы вашу проблему со скольжением.
двойник
2
«(некоторые игры предпочитают, чтобы это было так, но это не кажется естественным и не нужно здесь)» Как это не «чувствовать себя естественно»? Google Inertia and Momentum ...
Рики,
1
@Felheart, естественно с точки зрения игрового процесса, а не реального физического мира. Если вы играете в Super Mario Bros или любой из классических платформеров, вы заметите, что они НЕ сохраняют импульс при прыжках на движущихся платформах. Это нарушает ощущение стояния и взаимодействия с движущейся платформой.
Малыш

Ответы:

17

Давайте разделим вашу проблему на отдельные вопросы ...

Слово о качестве кода

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

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

Пусть ваш игрок определит, где он находится по отношению к объекту напольного типа (платформы и этажи будут иметь BodyType = BodyTypes.Floorили что-то подобное), и сам определит, где он находится по отношению к объекту, как он должен реагировать и падает ли он или на земле.

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

Горизонтальная / вертикальная инерция при выходе из платформы

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

  • Относительно горизонтальной скорости: Ваш код устанавливает горизонтальную скорость на 0, только когда игрок падает на землю (на линии Пасти 200) или на платформу.
  • Относительно вертикальной скорости: у вашего игрока постоянное ускорение падения. Когда он уходит с вертикальной платформы, это ускорение падения только добавляется к его и без того нисходящему движению.

Ваш игрок просто страдает от инерции : его импульс сохраняется, пока что-то не остановит его.

Решение: Обе проблемы будут решены путем решения jSepia в к Как обрабатывать движущиеся платформы в игровой платформы? поскольку это полностью отделило бы процесс перемещения игрока от того, как платформы перемещают его. Вы просто не упали бы быстрее, уйдя с вертикальной платформы, и не сохранили бы ваш горизонтальный импульс, спрыгнув с горизонтального, потому что платформы больше не будут влиять на vx и vy вашего игрока .

Примечание: у вас могут возникнуть трудности с реализацией решения jSepia до того, как ваш код подвергнется рефакторингу.

Скольжение из стороны в сторону вокруг горизонтальной платформы

Ваш игрок на самом деле не двигается горизонтально так быстро, как движется платформа. Для меня не очевидно почему. Эта проблема также, вероятно, будет решена путем реализации решения jSepia и правильного рефакторинга вашего кода (последний просто сделает причину очевидной).

Обнаружение столкновения: перекрытие с вертикальной платформой

Смотрите строку Pastie 381: каждый шаг сбрасывает vy игрока на 0, пока игрок сталкивается с нижней стороной вертикальной платформы. На следующем шаге vy увеличивается за счет ускорения силы тяжести, а затем игрок перемещается (и затем он снова сбрасывается до 0).

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

Решение: не сбрасывайте vy игрока на 0. Просто установите vy игрока на вертикальную скорость платформы ( если платформа движется вниз ). Ваш игрок будет тогда уходить от вертикальной платформы, по крайней мере, так же быстро, как платформа, и ускоряться от нее.

doppelgreener
источник
Отлично! Во-первых, спасибо за решение о прыжках и проникновении на вертикальную платформу (работает!). А во-вторых, вы правы, код ужасен в этом состоянии. Хотя это не игра сама по себе, это быстрый прототип, созданный для экспериментов и лучшего понимания движущихся платформ. Тем не менее, если я хочу перевести это в реальный игровой код, я должен сохранить более структурированный и объектно-ориентированный код. Это сгладит передачу. Теперь, что касается решения jSpeias, я думаю, что у меня есть концепция дерева узлов, просто я не знаю, как правильно ее реализовать.
Малыш
Моя первая мысль - создать логические значения, которые описывают состояние игроков, например: «onFloor», «onPlatform», «onGround», «fall», «jumping» и т. Д., А затем выполнить оператор if в Событие enterFrame, которое проверяет текущее состояние и соответственно изменяет свойства игроков (?) Например: if (Hero.onPlatform == true) {Player.x = platform.x (относительно игроков x глобальных);}. Что-то в этом роде.
Малыш
Я работаю над этим, как мы говорим, но в то же время я разделяю код на разные классы, как вы предложили, что также немного сбивает с толку (общение между платформами / столкновениями / игроками - это сложная задача).
Малыш
@Kid: Playerимеет метод GetPositionи внутренние переменные parent(для его родительского узла) и position(для его положения относительно его родителя). Player.GetPosition()возвращается position + parent.GetPosition(). Его родитель делает то же самое, пока вы не достигнете корня дерева - мирового узла. Когда ваш игрок движется, вы имеете дело только с приватной positionпеременной. Ваш игрок рисуется на игровом экране в соответствии GetPosition()со значением игрока . Я дам вам понять, как происходит переход между узлами. ;)
двойник
Наличие класса игрока, который знает, как изменить собственную скорость, конечно же, не поддерживает разделение интересов
Энди Рэй,