Ok, I spent some time looking at that article, and have come up with this demo. If has time based physics, with spring forces, damping, air resistance and simple forces, but only in one dimension, although two dimensions would be very much possible, if they were independent of each other, you could just stick two calls to integrate() in, but if they are dependent on each other, you'll have to put two dimensional functionality into the functions (not forgetting to use the total displacement with spring constants and such, using pythagorus (x^2 = y^2 + z^2))
Use code snippet button, not code box...
remstart
===================================
RK4 Integration Demo
29/12/04
Converted and Edited by Joseph Thomson
===================================
Original code copyright info...
===================================
Simple RK4 integration framework
Copyright (c) 2004, Glenn Fiedler
http://www.gaffer.org/articles
===================================
This demo shows how to use the RK4 integration technique for game physics, undoubtedly
it will have to be edited and re-arranged to suit your purpose.
RK4 integration is a technique used in game physics, it takes any operation you are doing
to an object (eg. springs, damping, air resistance, friction, forces) and makes a best
estimate about what state it will be in (position and velocity) after a set time (dt).
You can use this by making dt your loop time, then the physics will always be the same,
no matter how fast your game loop is. Unfortunately, due to fact that the calculations
are estimates, the calculations are really only reliable over 10fps (my estimate), dt
time calculations should be limited to the 10fps, or more, equivilent, this way, if the fps
go below 10, the simulation will run more slowly, but won't explode.
Please visit...
http://www.gaffer.org:8080/articles/Integration.html
...for more information
===================================
remend
`Create constants to refer to vectors by
#constant Vstate 1
#constant Va 2
#constant Vb 3
#constant Vc 4
#constant Vd 5
#constant Vempty 6
#constant Vspare 7
`Create vectors. Vectors in this example will NOT be used for x and y space coordianates,
`instead they are used for position and velocity in one dimension (ie. the state of the object)
tmp = make vector2(Vstate)
tmp = make vector2(Va)
tmp = make vector2(Vb)
tmp = make vector2(Vc)
tmp = make vector2(Vd)
tmp = make vector2(Vempty)
tmp = make vector2(Vspare)
`Main loop
main()
end
`This function will integrate the state of the object using dt, with the RK4 method
`t is not used in this example, but could be used if you want to affect the object
`based on the time
function integrate(state as integer, t as float, dt as float)
local dxdt as float
local dvdt as float
`RK4 requires four integrations, with these preset values, each integration uses the result from the one
`before it (which is the velocity as acceleration, since integrating displacement and velocity gets
`velocity and acceleration respectively). Each one also uses state, which is integrated at each step
evaluate(Va, state, t, 0, Vempty)
evaluate(Vb, state, t, dt*0.5, Va)
evaluate(Vc, state, t, dt*0.5, Vb)
evaluate(Vd, state, t, dt, Vc)
`This bit is just another part of RK4 integration, it weighs the four results, and does an estimate of
`the average velocity and acceleration
dxdt = 1.0/6.0 * (x vector2(Va) + 2.0*(x vector2(Vb) + x vector2(Vc)) + x vector2(Vd))
dvdt = 1.0/6.0 * (y vector2(Va) + 2.0*(y vector2(Vb) + y vector2(Vc)) + y vector2(Vd))
`Change the state displacement and velocity using the estimated velocity and acceleration for this time step
set vector2 state, x vector2(state) + dxdt*dt, y vector2(state) + dvdt*dt
endfunction
function evaluate(Vout as integer, initial as integer, t as float, dt as float, Vin as integer)
`First, simply integrate the position and velocity over dt, using the velocity and acceleration passed in
set vector2 Vspare, x vector2(initial) + x vector2(Vin)*dt, y vector2(initial) + y vector2(Vin)*dt
`Now calculate the velocity and acceleration. Velocity is simple, but acceleration is worked from another function
set vector2 Vout, y vector2(Vspare), acceleration(Vspare, t+dt)
endfunction
`This function requires on dt or integration, it is simply what you want to do to your object
function acceleration(state as integer, t as float)
spring as float = 0.02
damping as float = 0.01
airRes as float = 0.001
force as float = 0.0
result as float
`You can make the object go left when you press this
if spacekey() then force = -4.0
`The acceleration is increased when the displacement from the origin get higher (spring force)
`it is increased when the velocity increases (damping)
`it is increased when the velocity increases, by a factor of vel^2 (air resistance)
`it also has a constant added to it
result = -spring*x vector2(state) - damping*y vector2(state) - airRes*y vector2(state)^2*(y vector2(state)/abs(y vector2(state))) + force
endfunction result
function main()
local t as float = 0.0
local dt as float
local time as integer = 10
local syncRate as float
local loopSpeed as float
local lastLoopTime as integer
local loopTime as integer
local loopConstant as float
local dt as float
`Initial dt variables
syncRate = 60.0
loopSpeed = 60.0
loopConstant = loopSpeed/1000.0
sync on
sync rate syncRate
`Set the position and velocity of the object
set vector2 Vstate, 200.0, 0.0
lastLoopTime = timer()
do
`Change the frame rate with up and down keys
if upkey()
inc syncRate,0.5*dt
sync rate syncRate
endif
if downkey()
dec syncRate,0.5*dt
if syncRate < 10.0 then syncRate = 10.0
sync rate syncRate
endif
`Work out dt variable
loopTime = timer() - lastLoopTime
lastLoopTime = timer()
dt = loopTime * loopConstant
`Draw the circle and integrate the state
integrate(Vstate, t, dt)
circle x vector2(Vstate)+320,240,30
inc t,dt
`info
text 0,0,"Set Frame Rate: " + str$(syncRate)
text 0,20,"Actual Frame Rate: " + str$(screen fps())
sync
cls
loop
wait key
endfunction
Isn't it? Wasn't it? Marvellous!
