Гравитация с эфирным временем, ускорением и увеличением скорости - PullRequest
9 голосов
/ 25 ноября 2011



Я пытаюсь выполнить гравитацию, включая эфирное время, а также ускорение.
Я пытался использовать обычную гравитацию, которая выглядит примерно так:

velocity += gravity * dt;
position += velocity * dt;


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

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

Это изображение иллюстрирует кривую, которую я бы хотелось бы иметь:
Link to curve

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

Я потратил часы, пытаясь заставить его работать, но без uccess. Я также пытался искать в интернете, но безуспешно.

Игра "Whale Trails" получила ту степень тяжести, которую я хотел.
Вот ссылка на видео игры: http://www.youtube.com/watch?v=5OQ0OWcuDJs

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

Ответы [ 3 ]

4 голосов
/ 25 ноября 2011

Гравитация - это сила, которая тянет объекты вниз. Ваш игрок - это сила, которая притягивает предметы. Соответственно ваш код должен быть:

if(keyPressed) {
  velocity += POWER_OF_PLAYER;
}

velocity += G;
position += velocity;

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

G = -9.81
POWER_OF_PLAYER = 20

Экономия энергии - это простая проверка.

if(keyPressed) {
  if(powerSaved > 0) {
    velocity += POWER_OF_PLAYER;
    powerSaved -= SOMETHING;
  }
} else if (velocity >= SOME_MINIMUM_SPEED_BEFORE_GETTING_POWER) {
  powerSaved += SOMETHING;
}

SOME_MINIMUM_SPEED_BEFORE_GETTING_POWER должно быть чем-то меньшим или равным 0.

P.S. Я предположил, что ваша ось Y начинается с земли и стреляет в небо. Знаки ставить соответственно.

0 голосов
/ 26 ноября 2011

Звучит как включение «подъема», основанного на горизонтальной скорости, и нажатие кнопки запускает движение «носом» достаточно хорошо.

Таким образом, lift будет некоторой константой k, умноженной на горизонтальную скорость Vx и вертикальную скорость Vy, будет разница в gravity и lift раз во времени dt

lift = k * Vx
Vy += ( lift - gravity ) * dt

def noseup
  k = 0.01 #some small chunk
  dx = k * Vx
  dy = k * Vy
  Vx -= dy
  Vy += dx

Когда самолет (или что-то еще) обнюхивается, он в основном снижает скорость на одной оси, увеличивая ее на другой.

Вероятно, было бы неплохо было бы добавить туда где-нибудь также drag, теперь, когда я об этом думаю, она должна зависеть от абсолютной скорости V = ( Vx**2 + Vy**2 )**0.5 ... и вес - это лучшее слово, чем гравитация в этом случае (менее запутанно, единицы измерения), но я думаю, что это работает.

Не совсем "физика", но близкое приближение, которое должно работать довольно хорошо. Поиграйте со значениями k и посмотрите, сможете ли вы сделать так, как вы хотите.

Кстати, простите за супер дерьмовый псевдокод: -P

0 голосов
/ 25 ноября 2011

Похоже, что скорость рыбы постоянна.

Попробуйте следующее:

velocity исправлено и не должно меняться (если рыба не съедает скорость при включении). angle = 0 эквивалентно полету уровня.

angle -= gravity * dt;
if (angle < - Math.PI / 2) {
  angle = Math.PI / 2;
}
if (keyPressed) { 
  angle += power * dt;
}

if (angle < - Math.PI / 2) {
  // Stop the player from doing a looping
  angle = - Math.PI / 2;
}
if (angle > Math.PI / 2) {
  // Stop the player from doing an inverted looping
  angle = Math.PI / 2;
}
// Move the fish (vertical component of velocity)
position += velocity * dt * Math.sin(angle);
// Move the background (horizontal component of velocity)
background_position -= velocity * dt * Math.sin(angle);
...