2014-10-03 5 views
0

У меня есть программа, которая запускает метод tick() для каждого кадра. Я хочу, чтобы объект падал в соответствии с установленной константой силы тяжести, поэтому я создал объект Ball, который обновит свое положение до положения на предыдущем кадре минус скорость y. Скорость y будет уменьшаться на постоянную силы тяжести каждого клеща. Но падение слишком быстрое, потому что тики не переводят напрямую на секунды. Я думаю, что мне не хватает базовой математики, но я жонглирую так много переменных, что не вижу, что это такое.Как сделать время независимо от FPS?

EDIT: Добавлен код

@Override 
public void run(){ 
    init(); 

    long lastTime=System.nanoTime(), timer=System.currentTimeMillis(); 
    final double ticks=60.0; 
    double ns=1000000000/ticks, delta=0; 
    int updates=0, frames=0; 

    while(running){ 
     long now=System.nanoTime(); 
     delta+=(now-lastTime)/ns; 
     lastTime=now; 

     if(delta>=1){ 
      tick(); 
      updates++; 
      delta--; 
     } 

     render(); 
     frames++; 

     if((System.currentTimeMillis()-timer)>1000){ 
      timer+=1000; 
      System.out.println(updates+" ticks, FPS "+frames); 
      frame.setTitle("Ball -- "+SCALEWIDTH+"x"+SCALEHEIGHT+" at "+frames+" FPS"); 
      updates=0; 
      frames=0; 
     } 
    } 
    stop(); 
} 
+1

Функция 'tick()' может возвращать временную дельта (время, прошедшее с последнего тика). Тогда вы можете использовать это при вычислении новой y-скорости. – freshtop

+0

Мне кажется, мне нужно повторить программу. Он был изменен из учебника. В общих чертах, что я должен искать? Разделите частоту кадров на время между тиками, чтобы получить «в реальном времени»? – Insederec

+0

Для Java вы ничего не делите. Вы просто вызываете 'System.nanotime()' и используете разницу, чтобы определить, сколько времени прошло с момента последнего вызова. Эта разница - ваш временной шаг. – markspace

ответ

2

Для каждого кадра обновления, вам необходимо вычислить время в секундах между теперь и предыдущим обновлением. Это должно быть float или double, так как это, вероятно, будет составлять долю секунды. Для этого вы получаете текущее время в миллисекундах или наносекундах, вычитаете предыдущее время и конвертируете в секунды.

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

position += velocity * dt; 
velocity += acceleration * dt; 

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

Если вам нужно больше точности, вы хотите посмотреть другие методы интеграции как Верле или Рунге-Кутта.

+0

Является ли дельта в моем коде не раз между секундами? Я думал, что это так, но когда я его протестировал, объект двинулся слишком быстро. – Insederec

+0

Я изменил код, так что это 'speed - = g/2 * (dt^2);' для соответствия фактическому уравнению для движения снаряда и выглядит правильно, но я уверен, что математически это неправильно. – Insederec

+0

Похоже, есть пара проблем. dt - разница между кадрами, а не скопление между кадрами. Каждое обновление вычисляет его как delta = (now-lastTime) /1000000000.0. Затем передайте это значение везде, где вы обновляете свой мяч (отметьте()?) И ​​используйте его, как я показал выше. Вы не должны добавлять или вычитать из дельта, как в вашем коде, и не делить на 60. – megadan

Смежные вопросы