Использование времени для увеличения скорости из-за проблемы гравитации (не удалось получить идеальную эластичность)

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

Сократив код до минимума, у меня есть следующее:

public void onDrawFrame(GL10 gl) {

float timeDelta = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();

update(timeDelta);
}

float gravity = -1.0f;
float PosY = 2400;
float VelocityY = 0;

public void update(float timeDelta){

PosY+=VelocityY;
if(PosY<=0){
    VelocityY=Math.abs(VelocityY);
} else{
    VelocityY+=gravity*timeDelta;
}       
Log.d(SystemSingleton.sLogDebug,String.format("Pos: y%f. y%f, timeDelta: %f",PosY, VelocityY, timeDelta));

}

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

Если я игнорирую timeDelta и просто применяю всю гравитацию в каждом кадре, это работает нормально, пик его отскока будет ровно 2400 (это начальная позиция). Но, принимая во внимание timedelta, она всегда меньше 2400 и медленно деградирует, а затем время от времени подскакивает на значительную величину (иногда намного выше 2400), прежде чем снова начнет деградировать.

Я, очевидно, получил что-то совершенно неправильно, но я не вижу этого.

Любая помощь приветствуется.


person Steve    schedule 20.06.2011    source источник
comment
Исправьте временной шаг   -  person YXD    schedule 21.06.2011


Ответы (2)


При расчете новой позиции необходимо учитывать временной шаг (timeDelta). Вместо этого:

PosY += VelocityY;  // no!!

Сделай это:

PosY += VelocityY * timeDelta;

А еще лучше сделать так:

PosY += VelocityY * timeDelta + 0.5 * gravity * timeDelta * timeDelta;

Кроме того, я бы немного изменил определение отскока. Вот новый код, который стоит попробовать:

// Perform the integration
PosY      += VelocityY * timeDelta + 0.5 * gravity * timeDelta * timeDelta;
VelocityY += gravity * timeDelta;

// Check whether it's time to bounce
if (PosY<=0 && VelocityY<0){
    VelocityY = Math.abs(VelocityY);
}       
Log.d(...)
person nibot    schedule 21.06.2011

float timeDelta = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();

Я предполагаю, что это причина. Вызов currentTimeMillis может дать вам два разных номера. Что бы я сделал:

float currentTime = System.currentTimeMillis();
float delta = currentTime - startTime;
startTime = currentTime;
person Coeffect    schedule 20.06.2011
comment
Ваш способ лучше, но это не главная проблема. - person nibot; 21.06.2011
comment
Не проблема, но определенно проблема, и я должен был ее увидеть. Ваше здоровье. - person Steve; 21.06.2011