Accelerating/decelerating motion and frame rate

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Devil Master
Posts: 81
Joined: Wed Apr 23, 2008 8:47 pm

Accelerating/decelerating motion and frame rate

Post by Devil Master »

I have made a program where an animated character moves left or right (like in a sidescroller, even though everything is polygonal) and can jump and fall. I wanted to make sure that all movements happen at a consistent speed, independently from the frame rate (so, with a higher frame rate, the character must move a shorter distance per frame than it would with a lower frame rate). For this I made a function, called at every iteration of the main cycle, that calculates a proportionality factor:

Code: Select all

void TimerManager(void)
{
  gametime=timer->getTime();
 
 frameduration=gametime-oldgametime; // gametime and oldgametime are global variables
 oldgametime=gametime;
 
 // How many SIXTIETHS OF A SECOND between the last frame and the current frame?
 fpsmultiplicationfactor=frameduration*0.06;
}
This works well for running, which happens at a uniform motion, in this snippet of the function that handles movement:

Code: Select all

 if (!dukerot.Y)
 dukex=dukepos.X+DUKESTEP*fpsmultiplicationfactor;
else
 dukex=dukepos.X-DUKESTEP*fpsmultiplicationfactor;
This means that if the main character is facing right (=his Y angle equals zero), his new X coordinate is obtained by adding a constant, multiplied by the proportionality factor, to the old X coordinate. Instead, if he's facing left, the value is subtracted from the old X coordinate.
This works as expected, and the running speed is exactly the same at any frame rate.

The jumping and falling is where the problem lies. I know the theory: in order to make it look realistic, jumping must be a uniformly decelerating motion, where the velocity starts at a maximum and is brought down to zero, frame after frame. Falling, instead must be a uniformly accelerating motion.
Anyway, this is the function that is executed every time I want the character to jump:

Code: Select all

void StartJumping(void)
{
 // when Duke is jumping, he is "falling up"
 dukefallingspeed=12*fpsmultiplicationfactor;
}
And this is the snippet of the function that is executed as part of the main loop, that handles gravity:

Code: Select all

if (dukepos.Y>0)
{
 dukefallingspeed=dukefallingspeed-GRAVITY*fpsmultiplicationfactor;
 dukey=dukepos.Y+dukefallingspeed;
}
node[duke]->setPosition(core::vector3df(dukex,dukey,0));
Note that GRAVITY is a constant that determines how much to vary the main character's vertical velocity during each cycle.

What I want to happen is for the main character to jump at the same height, at the same speed, no matter the frame rate.
What actually happens is that the height and speed are what I expect to be if the game runs at 60 fps. Instead, if it runs at 30 fps, the height of the jump is much higher, and the deceleration is much lower. But... why? Am I not supposed to multiply the velocity variation by a factor that depends on the duration of each frame, like I do with the (uniform) horizontal motion?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Accelerating/decelerating motion and frame rate

Post by thanhle »

Jumping would be time dependent.
A lower framerate would missed some of the position in between.
t = time between frame.

v = u + at
v^2 = u^2 + 2a (s-so)
s = so + ut + 1/2at^2

Play around with those equations.

Regards
thanh
Devil Master
Posts: 81
Joined: Wed Apr 23, 2008 8:47 pm

Re: Accelerating/decelerating motion and frame rate

Post by Devil Master »

In the end, I remembered that acceleration is defined as distance divided by squared time, so I succeeded by turning this:

Code: Select all

dukefallingspeed=dukefallingspeed-GRAVITY*fpsmultiplicationfactor;
into this:

Code: Select all

dukefallingspeed=dukefallingspeed-GRAVITY*fpsmultiplicationfactor*fpsmultiplicationfactor;
Post Reply