Tutorial The Physics of Jumping

13lade619

is now a game developer :)
Reaction score
399
This tutorial will show you how to make ‘close-to-real’ jumps, using a physics equation.
First off, the vertical jump. (forward jump will be added later.)

Ok.. let’s start with a simple lesson in physics/calculus.

THE PHYSICS OF JUMPING : VERTICAL

Acceleration : the change of velocity over time.

*Calculating for velocity.*
A = dV/dT​

And because the object is falling, it has constant acceleration due to gravity.
And it is also negative because it is pulling downwards.

-A = constant​

Now if we take the formula and isolate dV,

dV = (-A)dT​

now integrate to solve for V,

V = -A*T + c​

That gives us a new variable c, which is the initial velocity.
Let’s denote that by vi.

This is now our equation for velocity based on a
given acceleration due to gravity in a given timeframe T,
plus an initial velocity vi going upwards (of course you need to push the object upward).

V = -A*T + vi​

Velocity : the change of displacement over time.

*Calculating for z-height.*
V = dZ/dT​

V = -A*T + vi

Now to keep track of the displacement of our unit, we need to see the height of the object,
Its displacement, denote by Z.

Same as before, we isolate then integrate.

dZ = V *dT, but because we have an equation for V...

dZ = (-A*T + vi)dT, then

Z = (-A/2)*T^2 + vi*T + c​

The c another constant for the initial displacement, so we dont need that for now since we are jumping in a level plane.

Now we have a formula to track the displacement Z of a unit through time T as it jumps
Given that we have a constant acceleration due to gravity A
And an initial velocity vi that pushes it upward.

Z = (-A/2)*T^2 + vi*T

And because A and vi are constants, we can solve for T.
In this, we solve for when Z reaches 0 again,
showing that the unit has reached ground.

*Calculating for hangtime formula.*
Set Z to 0
0 = (-A/2)*T^2 + vi*T​
Move the negative half to the other side, nullifying negative sign.
(A/2)*T^2 = vi*T​
Divide by T to eliminate it from the right side and we have:
(A/2)*T = vi​
Now we divide by the acceleration/2 to isolate T.
T = vi / (A/2)​

And we have the ‘hangtime’ formula needed in the next chapter of the lesson later.

T = vi / (A/2)​

We can also calculate for the maximum height reached by the object of anyone is interested..

Maximum height is attained when velocity is zero,
which is when the object is at the topmost point,
when it makes the transition from upward to downward motion.

*Calculating for V=0.*
From the V formula,
V = -A*T + vi​
Set V to 0,
0 = -A*T + vi​
Then to the other side again,
A*T = vi​
Division
T = vi/A​

We got the T for which V = 0.
Now use that T value in the Z equation to obtain maximum Z.

Z = (-A/2)*T^2 + vi*T


//============================================================
TRIGGERING A VERTICAL JUMP
These sample actions will make a unit jump vertically when it casts an ability.

And now we test vertical jump in a trigger:

Use a simple ‘starts the effect of ability’ event, and ability comparison condition.

And a struct:

JASS:

struct jump
    unit caster
    //constants A and vi, set later.
    real A
    real vi
    //counters Z and T, incremented later so add a starting value 0 for simplicity
    real Z = 0
    real T = 0
endstruct


and also, a struct to timer attachment system.
In this tutorial, we will be using Timer Ticker from Cohadar

Here’s the actions, with comments of course.
JASS:

function Jump_Actions takes nothing returns nothing
    //caster and struct only, since we're just dealing with flyheight.
    local jump j = jump.create()
    
    //set the struct values.
    set j.caster = GetTriggerUnit() // Caster
    //just play around with the constants..
    //i have these for the example.
    set j.A = 3200 //from the real 32 ft/sec^2.
    set j.vi = 1000 //pushed up at a speed of 1000.
    
    //Crow Form for flying.
    call UnitAddAbility(j.caster,'Amrf')
    call UnitRemoveAbility(j.caster,'Amrf')
    
    //i'm using Cohadar's TT by the way, you can search it on the site.
    call TT_Start(function JumpFunc, j)
endfunction


Now the JumpFunc
JASS:
 function JumpFunc takes nothing returns boolean
    //get the struct from the timer.
    local jump j = TT_GetData()
    //increment the time value with the periodic timeout of the expiring timer.
    set j.T = j.T + .035

    //now using our formula for displacement : Z = (-A/2)*T^2 + vi*T
    set j.Z = ((-j.A/2)*(j.T*j.T)) + (j.vi*j.T)
    
    //set the flying height of the caster.
    call SetUnitFlyHeight(j.caster,j.Z,0)

    // if object fell to the ground already, then stop the trigger.
    if j.Z <= 0 then
        //take care of the leaks and finish off.
        set j.caster = null
        call j.destroy()
        return true
    else
        return false
    endif
endfunction
//============================================================


FORWARD JUMPING

>> In this method we will be 'assigning' a forward speed (wc3 units / time) to travel from point a to point b.
Then we will have formulas to take care of the jumping.

Reviewing some ideas:

Forward Movement
Forward Speed = ( Travel Distance / Travel Time )
Time = Distance / Speed

Vertical Jump
Hangtime = T = ( Initial Velocity / ( Gravity / 2 ) )

Basically we want to precisely time the jump and move so that the unit will reach its target point and at the same time fall from the jump. And we will only be using a given forward speed that you will assign, then the formula will calculate for vertical speed so that times will match.

So now we want to equate the time of the 2 events :

(FDistance/FSpeed) = (VVelocity/(VGravity/2))
^Now to isolate VVelocity, we multiply by VGravity/2 both sides; which cancels the left side.
so we have this equation for VVelocity:
((VGravity/2)*FDistance)/FSpeed = VVelocity

And that's *basically* all what we need to make a forward jump.

B U T . . .

By thoroughly testing some triggers i made, the jump is sometimes unnoticeable due to the fast speeds of the forward jump..

So, I've come up with a solution :
multiplying the gravity and upward velocity by a factor of the speed so that the caster will jump higher.

Like this : (by a factor of 300)

vi = vi * (fs/300)
A = A * (fs/300)

So now, to the triggers:

//============================================================
TRIGGERING A FORWARD JUMP

Use a simple ‘starts the effect of ability’ event, and ability comparison condition.

And a struct.

and also, a struct to timer attachment system.
In this tutorial, we will be using Timer Ticker from Cohadar

Here's a sample trigger w/ Comments.

JASS:
struct jump
    unit caster
    real A          //Gravity set later
    real vi         //Vi calculated later
    real fs         //forward speed you set.
    real angle
    //counters Z and T, incremented later so add a starting value 0 for simplicity
    real Z = 0
    real T = 0
endstruct

function JumpFuncFly takes nothing returns boolean
    //get the struct from the timer.
    local jump j = TT_GetData()
    // we divide j.fs by 28.57 because you need j.fs units/second.
    // but the interval is .035 and 1/.035 = 28.57
    local real NX = GetUnitX(j.caster) + (j.fs/28.57) * Cos(j.angle * bj_DEGTORAD)
    local real NY = GetUnitY(j.caster) + (j.fs/28.57) * Sin(j.angle * bj_DEGTORAD)

    //increment the time value with the periodic timeout of the expiring timer.
    set j.T = j.T + .035

    //now using our formula for displacement : Z = (-A/2)*T^2 + vi*T
    set j.Z = ((-j.A/2)*(j.T*j.T)) + (j.vi*j.T)
    
    //move the caster..
    call SetUnitX(j.caster,NX)
    call SetUnitY(j.caster,NY)
    call BJDebugMsg(R2S(j.Z))
    
    //set the flying height of the caster.
    call SetUnitFlyHeight(j.caster,j.Z,0)

    // if object fell to the ground already, then stop the trigger.
    if j.Z <= 0 then
        //take care of the leaks and finish off.
        set j.caster = null
        call j.destroy()
        return true
    else
        return false
    endif
endfunction

function Trig_JumpFunc_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'AOwk' //Using Wind Walk.
endfunction

function Trig_JumpFunc_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local location cp = GetUnitLoc(caster)
    //Since i'm using Wind Walk, it's instant so i need to set the target point manually.
    local location tp = PolarProjectionBJ(cp, 500, GetUnitFacing(caster))
    //You should use this if you have a point target ability:
    //local location tp = GetSpellTargetLoc()
    //You should use this if you have a unit target ability:
    //local location tp = GetUnitLoc(target)
    local jump j = jump.create()
    
    //set the struct values.
    set j.caster = caster
    //Now set the gravity constant, vi will be set later.
    set j.A = 3200
    set j.angle = AngleBetweenPoints(cp,tp)
    
    set j.fs = 2000 //depends upon you.
    
    //(FDistance/FSpeed) = (VVelocity/(VGravity/2))
    //^Now to isolate VVelocity, we multiply by VGravity/2 both sides; which cancels the left side.
    //so we have this equation for VVelocity:
    //((VGravity/2)*FDistance)/FSpeed = VVelocity
    set j.vi = (DistanceBetweenPoints(cp,tp)*( j.A/2 )) / (j.fs)
    
    //through hi-speeds, the normal jump may be unnoticeable.
    //we multiply the values by j.fs/300 to overcome that.
    set j.vi = j.vi * (j.fs/300)
    set j.A = j.A * (j.fs/300)
    
    call BJDebugMsg(R2S(j.vi))
    call AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl",tp)
    
    //Crow Form for flying.
    call UnitAddAbility(j.caster,'Amrf')
    call UnitRemoveAbility(j.caster,'Amrf')
    
    //Start the Timer.
    call TT_Start(function JumpFuncFly, j)
    
    call RemoveLocation(cp)
    call RemoveLocation(tp)
    set cp = null
    set tp = null
endfunction

//===========================================================================
function InitTrig_JumpFunc takes nothing returns nothing
    set gg_trg_JumpFunc = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_JumpFunc, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_JumpFunc, Condition( function Trig_JumpFunc_Conditions ) )
    call TriggerAddAction( gg_trg_JumpFunc, function Trig_JumpFunc_Actions )
endfunction
//============================================================


Thanks for reading and i hope you learned something today.
 

Trollvottel

never aging title
Reaction score
262
Kind of very basic

and isnt:

JASS:
set j.Z = ((-j.A/2)*(j.T*j.T)) + (j.vi*j.T)


too much math? you could just have a velocity and an acceleration and each tick add the acceleration to the velocity and add velocity to Z.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Ironically, if you know what δV/δT means, then chances are you're a mathematics academic and already understand how jumping physics works (mathematically). What led you to write a tutorial for mappers in academic mathematical notation?

>the change of velocity over time.
What you have written there is the change in velocity over the change in time. Which is correct. δ (delta) means "change in" when used like this.

>now integrate to solve for V
Betcha half the people on this site don't know what "integrate" means (although I could be wrong). Furthermore, why integrate?

You also use TT randomly in there and give no explanation as to why or what it does.

Personally I think jump functions look much better in quartics. If you could find δV/δT in terms of V and/or T for a cubic acceleration, you could give the unit some hang-time and make this quite impressive. But this is just my preference in my own maps.

JASS:
function Jump_Actions takes nothing returns nothing
    //caster and struct only, since we're just dealing with flyheight.
    local unit caster = GetTriggerUnit()
    local jump j = jump.create()
    
    //Crow Form for flying.
    call UnitAddAbility(caster,'Amrf')
    call UnitRemoveAbility(caster,'Amrf')
    
    //set the struct values.
    set j.caster = caster
    //just play around with the constants..
    //i have these for the example.
    set j.A = 3200 //from the real 32 ft/sec^2.
    set j.vi = 1000 //pushed up at a speed of 1000.
    
    //i'm using Cohadar's TT by the way, you can search it on the site.
    call TT_Start(function JumpFunc, j)
    
    set caster = null
endfunction
Should be
JASS:
function Jump_Actions takes nothing returns nothing
    //caster and struct only, since we're just dealing with flyheight.
    local jump j = jump.create()
    
    //set the struct values.
    set j.caster = GetTriggerUnit() // Caster
    //just play around with the constants..
    //i have these for the example.
    set j.A = 3200 //from the real 32 ft/sec^2.
    set j.vi = 1000 //pushed up at a speed of 1000.
    
    //Crow Form for flying.
    call UnitAddAbility(j.caster,'Amrf')
    call UnitRemoveAbility(j.caster,'Amrf')
    
    //i'm using Cohadar's TT by the way, you can search it on the site.
    call TT_Start(function JumpFunc, j)
endfunction

And TT should ideally be linked if it's used in this tutorial.
 

wraithseeker

Tired.
Reaction score
122
Does this support only vertical jumps? Could you teach me how to make a non vertical jump? I need to find C.
 

_whelp

New Member
Reaction score
54
Errm... someone jumps in an unnaturally curvy way, then everyone will think he's sliding in a semicircular path-ish.
 

13lade619

is now a game developer :)
Reaction score
399
well, in a certain 'sense' you can actually use this for pushing something back with an instant force while that thing pushes back
with a weaker but constant force.

but you have to stop it as soon as you hit the zero velocity at the 'top' of the jump..
else the thing will bounce back.
 

wraithseeker

Tired.
Reaction score
122
I don't really understand what you mean but could you update this to fit with forward jumps?

It'll be really helpful since I can't do much physics maths :eek:
 

Trollvottel

never aging title
Reaction score
262
The x/y and z movement are independent of each other.
so if you have a gun and shoot from 8 meters height in an angle of 0° it doesnt matter if you shoot it 800 miles/hour fast or 20 miles/hour fast, the time it needs to fall down will always be the same (it would fly not as far if you shoot something at 20 miles/hour).
So the formula for the z stays the same, you will just have to add x/y movement...
 

wraithseeker

Tired.
Reaction score
122
Still waiting for a more documented forward jump.

@Trollvottel

Recently alot of people put alot of bullets into my head and the bullets are so cramped and i can't think much..
 

Romek

Super Moderator
Reaction score
963
You don't say what each of those variables are. :p
A, dV, dT, etc.

Is this still being worked on?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top