Back in 2006 as part of the N-vidia competition I made a code snippet which showed how to jump using the character controller.
Example 1 - no collision detection.
REM Project: PhyJump
REM Created: 15/12/2006 11:20:51
REM
REM ***** Main Source File *****
REM
`Use W.S.A.D or Curser keys + mouse to move
`Use Space To Jump
`pretty standand initialisation routine
sync on
phy start
` i use a scale of one DB point= one centimetre - the standard is one Metre
`so gravity has to be scaled by 100
phy set gravity 0.0,-98, 0.0.
autocam off
hide mouse
set ambient light 50
sync rate 60
`variables
sw=screen width() : sh=screen height()
`charicter position variables
gx#=0 : gy#=10: gz#=0
`how long charecter hill jump for and the speed at which they jump
jumpspeed=-250 : jumptime=31
`camera
camheight=10
camdist=-20
`Make a simple scene
make object box 10,1000,5,1000
position object 10,0,0,0
color object 10,RGB(128,128,0)
make object box 11,50,5,50
position object 11,50,50,50
color object 11,RGB(0,255,0)
make object box 12,50,5,50
position object 12,25,25,25
color object 12,RGB(128,128,255)
make object box 13,50,5,50
position object 13,25,75,25
color object 13,RGB(255,0,0)
`make rigid bodies
for temp=10 to 13
phy make rigid body static box temp
next temp
`make charechter
make object box 3,3,10,3
color object 3,RGB(255,0,255)
`phy make capsule character controller ID, x#, y#, z#, radius#, height#, up, step#, slope limit#
phy make capsule character controller 3, gx#,gy#,gz#, 1.5,10, 1, 1.5, 45.0
`main loop
do
`this bit just checks mouse position and keeps it in the screen - helps if using a window
mx=mousex()
my=mousey()
if mx>sw-2 then mx=mx-sw
if mx<1 then mx=sw-mx
if my>sh-2 then my=my-sh
if my<1 then my=sy-my
position mouse mx,my
`make charachter fall
oldjgy#=object position y(3)
phy set character controller displacement 3, 98, 0
phy move character controller 3, 0.1
phy move character controller 3, -0.1
`check position and rotate charachter with mouse
move=0
grx#=object angle x(3)
gry#=object angle y(3)
grz#=object angle z(3)
gry#=wrapvalue(gry#+ (mousemovex()/2))
yrotate object 3,gry#
oldgry#=gry#
`this bit moves charachter with wsad or cursor keys
`left
if keystate(30)=1 or keystate(203)=1
phy set character controller displacement 3, 0, 0
yrotate object 3,wrapvalue(gry#-90)
phy move character controller 3, 50.0
yrotate object 3,oldgry#
move=1
endif
`right
if keystate(32)=1 or keystate(205)=1
phy set character controller displacement 3, 0, 0
yrotate object 3,wrapvalue(gry#+90)
phy move character controller 3, 50.0
yrotate object 3,oldgry#
move=1
endif
`forward
if keystate(17)=1 or keystate(200)=1
phy set character controller displacement 3, 0, 0
phy move character controller 3, 50.0
move=1
endif
`back
if keystate(31)=1 or keystate(208)=1
phy set character controller displacement 3, 0, 0
phy move character controller 3, -40.0
move=1
endif
`this is the bit that caused me much problems
`jumping
`tags are
` jump=0 : no jump
`jump<0 : Falling
`jump>0 : rising
`check we want to jump
if spacekey()=1 and jump=0 then startgy#=object position y(3):jump=1 :oldgy#=0
if jump>0
`this checks to see if characher has a restricted jump ( platform above the head )
if object position y(3)=oldgy# then jump=jumptime-1
oldgy#=object position y(3)
`move charachter up
phy set character controller displacement 3, 0,jumpspeed
`displacement only seems to work when characher is moving - so move it a wee bit then back a wee bit
phy move character controller 3, 0.1
phy move character controller 3, -0.1
jump=jump+1 `incrament timer
if jump=jumptime then jump=-1
endif
`this is a check that the jump has finished before you can start a new jump
if jump<0
jump=jump-1
if jump<(0-jumptime)
jgy#=object position y(3)
if jgy# = oldjgy# then jump=0
endif
endif
`documentation states for smooth movement you should allways call this comand - even if not moving
if move=0 then phy move character controller 3, 0.0
`camera up and down
crx#=camera angle x()
crx#=wrapvalue(crx#+ (mousemovey()/2))
gx#=object position x(3)
gy#=object position y(3)
gz#=object position z(3)
position camera gx#,gy#+camheight,gz#
SET CAMERA TO OBJECT ORIENTATION 3
move camera camdist
if crx#> 45 and crx#<270 then crx#=45
if crx#<300 and crx#>269 then crx#=300
xrotate camera crx#
phy update
sync
loop
Three years later during my entry to the community competition #1, I was tracked down by Zaibatsu who stated.
Quote: "The character won't jump if it's moving on sloped surfaces."
I checked, and sure enough, as the above code relies on changing Y coordinates to check if player is jumping or falling moving on a slope gives false results. I had not noticed this at the time because my game had no slopes.
After checking the forums, I could not find another easy example of how to jump. It became clear that collision detection was the only sure way to detect if the player was on the ground. I changed the above snippet to include slopes and collision detection using DBPs own System.
Example 2 - With DBP own Collision detection.
REM Project: PhyJump
REM Created: 15/12/2006 11:20:51
REM
REM ***** Main Source File *****
REM
`Use W.S.A.D or Curser keys + mouse to move
`Use Space To Jump
`pretty standand initialisation routine
sync on
phy start
` i use a scale of one DB point= one centimetre - the standard is one Metre
`so gravity has to be scaled by 100
phy set gravity 0.0,-98, 0.0.
autocam off
hide mouse
set ambient light 50
sync rate 60
`variables
sw=screen width() : sh=screen height()
`charicter position variables
gx#=0 : gy#=10: gz#=0
`how long charecter hill jump for and the speed at which they jump
jumpspeed=-250 : jumptime=31
`camera
camheight=10
camdist=-20
`Make a simple scene
make object box 10,1000,5,1000
position object 10,0,0,0
color object 10,RGB(128,128,0)
make object box 11,50,5,50
position object 11,50,50,50
color object 11,RGB(0,255,0)
make object box 12,50,5,50
position object 12,25,25,25
color object 12,RGB(128,128,255)
make object box 13,50,5,50
position object 13,25,75,25
rotate object 13,0,0,-45
color object 13,RGB(255,0,0)
make object box 14,500,5,50
position object 14,125,50,-125
rotate object 14,0,0,15
color object 14,RGB(0,255,0)
make object box 15,500,5,50
position object 15,125,30,-250
rotate object 15,0,0,45
color object 15,RGB(0,0,255)
`make rigid bodies
for temp=10 to 15
phy make rigid body static box temp
next temp
`make charechter
make object box 3,3,15,3
color object 3,RGB(255,0,255)
`phy make capsule character controller ID, x#, y#, z#, radius#, height#, up, step#, slope limit#
phy make capsule character controller 3, gx#,gy#,gz#, 1.5,10, 1, 2, 60.0
`main loop
do
`this bit just checks mouse position and keeps it in the screen - helps if using a window
mx=mousex()
my=mousey()
if mx>sw-2 then mx=mx-sw
if mx<1 then mx=sw-mx
if my>sh-2 then my=my-sh
if my<1 then my=sy-my
position mouse mx,my
`make charachter fall
oldjgy#=object position y(3)
phy set character controller displacement 3, 98, 0
phy move character controller 3, 0.1
phy move character controller 3, -0.1
`check position and rotate charachter with mouse
move=0
grx#=object angle x(3)
gry#=object angle y(3)
grz#=object angle z(3)
gry#=wrapvalue(gry#+ (mousemovex()/2))
yrotate object 3,gry#
oldgry#=gry#
`this bit moves charachter with wsad or cursor keys
`left
if keystate(30)=1 or keystate(203)=1
phy set character controller displacement 3, 0, 0
yrotate object 3,wrapvalue(gry#-90)
phy move character controller 3, 50.0
yrotate object 3,oldgry#
move=1
endif
`right
if keystate(32)=1 or keystate(205)=1
phy set character controller displacement 3, 0, 0
yrotate object 3,wrapvalue(gry#+90)
phy move character controller 3, 50.0
yrotate object 3,oldgry#
move=1
endif
`forward
if keystate(17)=1 or keystate(200)=1
phy set character controller displacement 3, 0, 0
phy move character controller 3, 50.0
move=1
endif
`back
if keystate(31)=1 or keystate(208)=1
phy set character controller displacement 3, 0, 0
phy move character controller 3, -40.0
move=1
endif
`this is the bit that caused me much problems
`jumping
`tags are
` jump=0 : no jump
`jump<0 : Falling
`jump>0 : rising
`check we want to jump
if spacekey()=1 and jump=0 then startgy#=object position y(3):jump=1 :oldgy#=0
if jump>0
`this checks to see if characher has a restricted jump ( platform above the head )
if object position y(3)=oldgy# then jump=jumptime-1
oldgy#=object position y(3)
`move charachter up
phy set character controller displacement 3, 0,jumpspeed
`displacement only seems to work when characher is moving - so move it a wee bit then back a wee bit
phy move character controller 3, 0.1
phy move character controller 3, -0.1
jump=jump+1 `incrament timer
if jump=jumptime then jump=-1
endif
`this is a check that the jump has finished before you can start a new jump
if jump<0
jump=jump-1
if jump<(0-jumptime)
jgy#=object position y(3)
if jgy# = oldjgy# then jump=0
endif
endif
`check to see if you are touching the ground (to get collision i had to make the player bigger than controler capsule)
hit = object collision(3,0)
if hit>9
`check to see collision is not above player
jump=0
endif
`documentation states for smooth movement you should allways call this comand - even if not moving
if move=0 then phy move character controller 3, 0.0
`camera up and down
crx#=camera angle x()
crx#=wrapvalue(crx#+ (mousemovey()/2))
gx#=object position x(3)
gy#=object position y(3)
gz#=object position z(3)
position camera gx#,gy#+camheight,gz#
SET CAMERA TO OBJECT ORIENTATION 3
move camera camdist
if crx#> 45 and crx#<270 then crx#=45
if crx#<300 and crx#>269 then crx#=300
xrotate camera crx#
phy update
sync
loop
This was still not ideal, as to make the collision detection work I had to make the player model bigger than the character controller, which means the players feet would be below ground level. I suggested using an invisible actor positioned just below your player and using it for collision detection or using sparkys collision DLL and raycasting.
Zaibatsu stated
Quote: "The new jumping code works as long as you use a world made of individual boxes. If you build a world in a 3D modeling program and export it as a single model, then it doesn't exactly work. If you press and hole the spacebar, it will make your character hover up to the highest point on the map, and then kind of bob there until you release the spacebar."
I suggested some potential causes
1) Have you set your landscape to polygon collision? If not, It might just be one big cube of a collision box.
2) If using a sky sphere or box, make sure its collision is disabled.
3) If you have scaled your objects, Collision data may be messed up.
4) Try the SHOW OBJECT BOUNDS command to get an idea of your collision data.
and said once i got some time off work I would make a working example with a real model.
I came up with this.
Example 3 - using a real model and an actor positioned under the player.
Can be downloaded here
http://www.mediafire.com/file/zzzuwdjkkj2/LemmingDrop.zip
or attached to this post.
When I get some more time, I will make an example using sparkeys collision, as I still think this would be the best solution.
I moved our discussion here as it may be helpful to some people and would be unfair for them to try and find it in a work in progress post under a community competition board.
If you can improve my examples or have some of your own, please post them here. Or if you have any problems I will try and help.