Solving the time an object takes to accelerate upwards taking gravity into account

StackOverflow https://stackoverflow.com/questions/23240014

  •  08-07-2023
  •  | 
  •  

Question

I have an character in a game that can jump; the jump height can be affected by holding down the jump button for a longer time. There is a maximum velocity the character can reach in the upwards direction, and I am trying to figure out how long the longest jump can be taking gravity into account.

I'm pretty sure this has something to do with SUVAT equations as the object is accelerating, but I can't seem to work gravity into the equation. Here are the variables I'm working with...

JumpVelocity = 2.0,
JumpAccel = 0.5,
JumpMax = 7.5,
Gravity = -14.0,

as soon as jump is pressed an initial velocity is set...

yVelocity = JumpVelocity;

and then every frame the jump button is held the velocity is increased until it reaches the cap

if (!jumpFinished)
{
    yVelocity += JumpAccel; 
    yVelocity += Gravity * deltaTime;
    if (yVelocity >= JumpMax) 
    {
        yVelocity = JumpMax;
        jumpFinished = true;
    }
}
yVelocity *= deltaTime;

I check to see if the jump is finished with:

if (yVelocity <= 0.0)

What I want to solve is how long the whole upwards phase of the jump process will take if the user were to max-out the jump velocity?

Was it helpful?

Solution

You let the initial velocity be increased while pressing, with the character already moving, so you have 2 differente stages:

STAGE 1

An initial positive acceleration, your character accelerate, sort of rocket or jetpack.

Initial conditions (t=0 of this branch):

v0   = JumpVelocity
vmax = JumpMax
a    = Gravity + jaccel 
r0   = 0 (initial height)

note that jaccel is not JumpAccel. Given your code JumpAccel is the variation of velocity in deltaTime time. So the actual burst acceleration is jaccel = JumpAccel/deltaTime. (USEFUL: for completeness - provide deltaTime).

This line in your code makes no sense to me: please explain.

yVelocity *= deltaTime;

Now you want to know when v, the velocity, reaches vmax. Given:

v = v0 + a*t

you want to find the value of t at which v=vmax. So you substitute and solve for t:

vmax = v0 + a*t
t = (vmax - v0)/a

or, using your symbols:

t = (JumpMax - JumpVelocity)/(Gravity + jaccel)

From t you can now evaluate the height that you have reached when you are at the maximum velocity. Get this kinematic equation:

r = r0 + v0*t + 0.5*a*t*t

and substitute all the variables to get r1, the position at the end of the thurst.

r1 = 0 + JumpVelocity*t + 0.5*(Gravity + jaccel)*t*t

STAGE 2

The character continue decelerating until reaches the maximum height, that's what you want to know.

In this second problem we "move" the time origin here, where the first stage has just completed, so we are at t=0 again (this cannot be applied in the graph - the coordinate system is only one there... few more subtractions because of this in the gnuplot commands below). Forget about the previously evaluated t - its out of scope now. Our current initial conditions are:

v0   = JumpMax
a    = Gravity
r0   = r1, r evaluated at the previous stage

Now you want to find the value of t when v=0. So, using again:

v = v0 + a*t

substituting v = 0 and solving for t:

0 = v0 + a*t
t = -v0/a

That using your variables (no symbols substitutions as shown before - easier to follow and you can evaluate it actually):

t = -JumpMax/Gravity

replacing t in the kinematic equation with constant acceleration, in order to find the position at that time (the time of the maximum height!):

r = r0 + v0*t + 0.5*a*t*t

that, using your variables is:

rmax = r1 + JumpMax*t + 0.5*Gravity*t*t.

That's it: rmax is the maximum height reached by your character.

To conclude, I have enjoyed to plot the two functions using gnuplot - it's available for free for both linux and windows, so you can play with it.

In the graph you can get the position at the various timesteps (each point is at a subsequent timestep, being plotted the height, r, versus the time, t). The two arrows point to r1 and rmax, evaluated using the formulas obtained above (see the gnuplot commands)

plotted with gnuplot

Here the gnuplot commands to generate the graph - good luck!

unset key

JumpVelocity = 2.0
JumpMax = 7.5
Gravity = -14
jaccel = 30

const_acc(t,r0,v0,a) = r0 + v0*t + 0.5*a*t**2

t1 = (JumpMax - JumpVelocity)/(Gravity + jaccel)
r1 = const_acc(t1, 0, JumpVelocity,Gravity+jaccel)
t2 = -JumpMax/Gravity + t1
rmax = const_acc(t2-t1, r1, JumpMax, Gravity)

set arrow from t1,0 to t1,r1
set arrow from t2,0 to t2,rmax

set xlabel "t" 
set ylabel "r" 
set xrange [ 0 : 2 ]
set yrange [ 0 : ]

plot x <= t1 ? const_acc(x,0,JumpVelocity,Gravity + jaccel) : 1/0 w p, x >= t1 ? const_acc(x-t1, r1, JumpMax, Gravity) : 1/0 w p
pause -1

OTHER TIPS

The basic equation you need is v=u+at, where u is initial velocity, v the velocity after time t, and a the acceleration. You appear to have two accelerations, that of the character and that of gravity. These combine to give one acceleration of -14 + 0.5 = -13.5

When v = 0

t= -u/a

I assume 2D world (for 3D is almost the same)

when jumping there is no upwards acceleration (unless you have rockets ...)

  • instead you accelerate a while feet are still on the ground (for limited time while pressing key)
  • after lift off from ground there are just friction and gravity accelerations
  • the jump height depends on escape velocity (when you lift off the ground)

I would do it like this:

// globals
struct pnt { float x,y; };
int jump=0; // jump flag
pnt acc; // acceleration [m/s^2]
pnt vel; // velocity [m/s]
pnt pos; // position [m]
float M=75.0; // player mass [kg]
float F=1000.0; // player jump force [N]
float a;
float dt; // time of your timer interval [s]
float tjump;

// init jump on some key hit ... 
jump=1;
acc.x+= F*cos(a)/m; // F/m is the jump strength force / mass
acc.y+= F*sin(a)/m; // a is angle of the jump force
pos.y-= crouch to jump lift off offset; // bigger offset means bigger jump 0.4[m] for example
tjump=0.0;

// integration timer with dt interval
vel+=acc*dt
pos+=vel*dt
if ((jump==1)&&(pos.y>=ground(x).y)) // lift off test
 {
 acc.x= 0.00;
 acc.y=-9.81; // just gravity no movement or jump ...
 jump++;
 }
if ((jump==2)&&(pos.y<=ground(x).y)) // hit the ground test
 {
 acc.y= 0.00;
 vel.y= 0.00;
 pos.y=ground(x).y; // stop on ground
 jump=0; // end of jump
 }
// now for your question add this
if ((jump==2)&&(vel.y>=0)) tjump+=dt; // and at the end tjump will contain the time you want
  • function: pnt ground(float x); returns the point on the ground for x axis
  • if you have more floors than you need pnt ground(pnt p);
  • which return nearest floor ground point downwards from p

If you really need the time then just do this in some for loop instead of timer before the actual jump take place

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top