This one's been puzzling me for a couple of days now.
Recently I started learning Sparky's Collision dll as someone told me it was not only good for collision (which it's AMAZING at!), but that it could help me create gravity for my games.
I checked out the Sliding Demo that comes with Sparky's, and I played around with it a bit to get the hang of modifying variables and seeing the results. Everything worked fine.
Then I tried to code it myself (but I cheated and looked at the Sliding Demo's source file

) to help keep the techniques permanently burned into my brain, however, I have two problems.
First, using WASD to move, the player object does
not stop moving after the player has let go of the keys. The object just keeps flying until it reaches the end of the ground object and then falls forever.
Second, my jumping code doesn't seem to work. I figured out how to use the Jump Timer variable from the original Sliding Demo to create a triple-jump, but when I implemented the very same code into my own program, it didn't work. And the jump looks very hard and it's not at all smooth like in the original demo.
Here is my code...please copy>paste and run it in your DBPro compiler:
REM Another Sparky's Test
REM Call the initialize routine
Gosub Initialize
REM Main Program Loop
Do
Text 0,0,"FPS: "+Str$(Screen FPS())
Text 0,12,"Ground "+Str$(Ground)
Text 0,24,"jTimer "+Str$(jTimer)
MovePlayer()
Sync
Loop
REM ++++++++++++++++++++++++++++++++++
REM S U B R O U T I N E S
REM ++++++++++++++++++++++++++++++++++
Initialize:
`Set up the essentials
Set Display Mode 1024,768,32
Set Window On
Set Window Title "Collision Test"
Set Window Position 50,50
Set Window Size 800,600
Sync On
Sync Rate 66
Set Ambient Light 0
Make Light 1
Color Light 1,RGB(255,255,255)
Position Light 1,0,200,0
Rotate Light 1, 45,-90,0
`Declare all of the variables
Global Radius# as Double Float : Radius#=2.0
Global Gravity# as Double Float : Gravity#=-0.1
Global SlopeAng# as Double Float : SlopeAng#=0.5
Global Ground as Integer : Ground=0
Global jTimer as Integer : jTimer=0
`Set up player vectors
Global Vx# as Double Float
Global Vy# as Double Float
Global Vz# as Double Float
`Build the player object
Make Object Sphere 1,Radius#*2
Color Object 1,RGB(0,100,255)
Position Object 1,0,20,0
SC_SetupObject 1,0,1 : `Player has no group
`Build the ground and walls (group 1)
Make Object Box 2,450,5,450
Position Object 2,0,-2,0
Color Object 2,RGB(0,0,0)
SC_SetupObject 2,1,2
Make Object Box 3,5,20,450
Position Object 3,-450,0,0
Color Object 3,RGB(0,255,25)
SC_SetupObject 3,1,2
Make Object Box 4,450,20,5
Position Object 4,0,0,450
Color Object 4,RGB(0,150,255)
SC_SetupObject 4,1,2
Make Object Box 5,5,20,450
Position Object 5,450,0,0
Color Object 5,RGB(255,150,20)
SC_SetupObject 5,1,2
Return
REM -------------------------
REM - F U N C T I O N S -
REM -------------------------
Function MovePlayer()
`Store the player's position
OldX#=Object Position X(1)
OldY#=Object Position Y(1)
OldZ#=Object Position Z(1)
`Apply gravity and movement
AngY#=Object Angle Y(1)
Vx#=0
Vy#=0
If Vy#=0 and jTimer=0 Then Vy#=Vy#+10*Gravity# Else Vy#=Vy#+Gravity#
`Move with WASD
If KeyState(32)=1 Then Vx# = Vx# + Cos(AngY#) : Vz# = Vz# - Sin(AngY#)
If KeyState(30)=1 Then Vx# = Vx# - Cos(AngY#) : Vz# = Vz# + Sin(AngY#)
If KeyState(31)=1 Then Vx# = Vx# - Sin(AngY#) : Vz# = Vz# - Cos(AngY#)
If KeyState(17)=1 Then Vx# = Vx# + Sin(AngY#) : Vz# = Vz# + Cos(AngY#)
`Jump (Only on the ground)
If Ground=1
If SpaceKey()=1 and jTimer=0
Vy#=Vy#+3.0
jTimer=30 : `Begin countdown for triple-jump
EndIf
If SpaceKey()=1 and jTimer=25
Vy#=Vy#+3.5
jTimer=20
EndIf
If SpaceKey()=1 and jTimer=15
Vy#=Vy#+4.0
jTimer=12
EndIf
EndIf
`Collision Detection
`Player's final position before collision
X#=OldX#+Vx#
Y#=OldY#+Vy#
Z#=OldZ#+Vz#
`Cast collision ray
Collide = SC_SphereCastGroup(1,OldX#,OldY#,OldZ#,OldX#,OldY#+Vy#,OldZ#,Radius#,0)
`Check for collision
If Collide > 0
Ny#=SC_GetCollisionNormalY()
If ABS(Ny#)>SlopeAng#
`If angle is flat, stay put
OldY#=SC_GetStaticCollisionY()
Else
`If angle is not flat, SLIDE real smooth-like...
X#=X#-OldX# : Z#=Z#-OldZ#
OldX#=SC_GetCollisionSlideX()
OldY#=SC_GetCollisionSlideY()
OldZ#=SC_GetCollisionSlideZ()
X#=X#+OldX# : Z#=Z#+OldZ#
EndIf
Else
`Nothing below player, not on ground, add vertical speed to player
OldY#=OldY#+Vy#
Ground=0
EndIf
If Ny#>SlopeAng#
Ground=1
Vy#=0
Else
Ground=0
If Ny#<-SlopeAng# Then Vy#=Gravity#
EndIf
`Decrease the jTimer
If Ground=1 and jTimer>0 then Dec jTimer
`Handle horizontal movement
Collide = SC_SphereCastGroup(1,OldX#,OldY#,OldZ#,X#,OldY#,Z#,Radius#,0)
If Collide>0
X#=SC_GetCollisionSlideX()
OldY#=SC_GetCollisionSlideY()
Z#=SC_GetCollisionSlideZ()
Vx#=0
Vy#=0
EndIf
`Update the player
Position Object 1,X#,OldY#,Z#
SC_UpdateObject 1
EndFunction
Here's the original (but modified) version of the Sliding Demo for comparison...for some reason some of the formatting got messed up when I opened it up in Notepad. Sorry.
sync on
sync rate 60
autocam off
randomize timer()
global numSpheres as integer : numSpheres = 5
global radius# as double float : radius# = 7.0
global littleRadius# as double float : littleRadius# = 2.0
makeLevel()
makePlayer()
makeExtraSpheres(numSpheres)
global rtimer as integer
global stimer as integer
global vtimer as integer
rem player movement vector
global vx# as double float
global vy# as double float
global vz# as double float
global gravity# as double float : gravity# = -0.1
global slope# as double float : slope# = 0.5
global ground as integer : ground = 1
global jumptimer as integer : jumptimer = 0
global syncmode as integer : syncmode = 60
global view as integer : view = 1
global hide as integer : hide = 0
do
handleExtraSpheres(numSpheres)
MovePlayer()
rem change view
if inkey$()="v" and vtimer<timer() then vtimer = timer()+300 : view = 1-view
rem enable/disable sync limit
if inkey$()="l" and stimer<timer()
stimer = timer()+300
syncmode = 60-syncmode
sync rate syncmode
endif
positionCameraToObject(2,view)
text 0,0,"Use W/A/S/D to move, SPACE to jump and V to change view"
text 0,20,"Press L to enable/disable sync limiting"
text 0,40,"Press RETURN to show/hide colored spheres"
text 0,80,"FPS: "+str$(screen fps())
text 0,100,"Touching Ground: "+str$(ground)
sync
loop
function makeLevel()
set ambient light 0
make light 1
color light 1,rgb(255,255,255)
position light 1,0,90,0
rotate light 1,10,90,0
load object "level.x",1
sc_setupComplexObject 1,1,2
load image "1.jpg",1
texture object 1,1
rem add box and sphere to the level
make object box 3,10,20,30
position object 3,-80,30,30
rotate object 3,rnd(360),rnd(360),rnd(360)
sc_setupObject 3,1,2
make object sphere 4,30
position object 4,80,30,30
rotate object 4,rnd(360),rnd(360),rnd(360)
sc_setupObject 4,1,1
make object sphere 100,3+rnd(8)*2.5
position object 100,0,50,rnd(2)*2
color object 100,rgb(rnd(2),rnd(55),rnd(255))
sc_setupObject 100,1,1
make object box 101,15,2,15
set object light 101,1
position object 101,-80,45,-25
color object 101,rgb(0,0,0)
sc_setupObject 101,1,2
make object cone 102,5.0*3
position object 102,0,65,-20
color object 102,rgb(255,255,255)
sc_SetupObject 102,1,0
rem all level objects are group 1
endfunction
function makePlayer()
make object sphere 2,radius#*2.0
position object 2,-80,15,-20
sc_setupObject 2,0,1
rem player has no group
endfunction
function makeExtraSpheres(num)
for i=10 to 10+num
make object sphere i,littleRadius#*2.0
position object i,rnd(50)-25,rnd(50)+100,rnd(50)-25
color object i,rgb(rnd(255),rnd(255),rnd(255))
sc_setupObject i,3,1
sc_allowobjectscaling i
next i
rem extra spheres are group 3
endfunction
function handleExtraSpheres(num)
for i=10 to 10+num
rem move all the little spheres towards the player and slide them
oldx# = object position x(i)
oldy# = object position y(i)
oldz# = object position z(i)
point object i,object position x(2),object position y(2),object position z(2)
move object i,0.5
x# = object position x(i)
y# = object position y(i)
z# = object position z(i)
rem little spheres collide with all (0)
collide = sc_sphereSlide(0,oldx#,oldy#,oldz#,x#,y#,z#,littleRadius#,i)
if collide>0
position object i,sc_getCollisionSlideX(),sc_getCollisionSlideY(),sc_getCollisionSlideZ()
endif
sc_updateObject i
next i
rem show/hide the extra spheres
if returnkey()=1 and rtimer<timer()
rtimer = timer()+300
hide = 1-hide
if hide = 1
for i=10 to 10+num
hide object i
next i
else
for i=10 to 10+num
show object i
next i
endif
endif
endfunction
function movePlayer()
rem rotate player with mouse
yrotate object 2,object angle y(2)+mousemovex()/3.0
xrotate object 2,object angle x(2)+mousemovey()/3.0
oldx# = object position x(2)
oldy# = object position y(2)
oldz# = object position z(2)
rem apply gravity, and user changes to movement
angy# = object angle y(2)
vx# = 0
vz# = 0
rem if player is jumping or falling then apply 'normal' gravity
rem if not attempt to keep the player stuck to the floor
if vy#=0 and jumptimer=0 then vy# = vy# + 5*gravity# else vy# = vy# + gravity#
if keystate(32)=1 then vx# = vx# + cos(angy#) : vz# = vz# - sin(angy#)
if keystate(30)=1 then vx# = vx# - cos(angy#) : vz# = vz# + sin(angy#)
if keystate(31)=1 then vx# = vx# - sin(angy#) : vz# = vz# - cos(angy#)
if keystate(17)=1 then vx# = vx# + sin(angy#) : vz# = vz# + cos(angy#)
rem only jump if on ground, and a certain time after last jump
if ground=1
if spacekey()=1 and jumptimer=0
vy# = vy# + 3.0 : jumptimer = 30
endif
if spacekey()=1 and jumptimer = 25
vy# = vy# + 3.5 : jumptimer = 20
endif
if spacekey()=1 and jumptimer = 15
vy# = vy# + 4.2 : jumptimer = 10
endif
endif
rem this would be the player's final position without collision
x# = oldx#+vx#
y# = oldy#+vy#
z# = oldz#+vz#
rem first handle gravity - seperated from horizontal movement
rem to achieve a more realistic effect
rem Method: simple - cast a sphere vertically down, if it hits the level then
rem position the object there (sticky collision) then move
rem on to horizontal movement
rem more complex - if we were to only use the simple method the player would be
rem allowed to climb almost vertical slopes. Alternative is to
rem get the normalY direction to work out how flat the gorund
rem below the player is, 0-slope# is flatter, slope#-1 is steeper.
rem if it's flat, use sticky collision, if it's steep slide the
rem player down the slope. Changing slope# determines how steep the
rem player can climb. NOTE: this also effects stairs.
collide = sc_SphereCastGroup(1,oldx#,oldy#,oldz#,oldx#,oldy#+vy#,oldz#,radius#,0)
if collide>0
rem how flat is this ground
ny# = sc_getCollisionNormalY()
if abs(ny#)>slope#
rem FLAT, stick
oldy# = sc_getStaticCollisionY()
else
rem STEEP, slide
x# = x# - oldx# : z# = z# - oldz#
oldx# = sc_getCollisionSlideX()
oldy# = sc_getCollisionSlideY()
oldz# = sc_getCollisionSlideZ()
x# = x# + oldx# : z# = z# + oldz#
endif
rem ny#<0 means the player has hit a ceiling rather than a floor
if ny#>slope#
rem only on ground if standing on flat ground
ground = 1
vy# = 0
else
ground = 0
rem if player has hit a flat ceiling then stop vy# movement
if ny#<-slope# then vy# = gravity#
endif
else
rem nothing below player, not on ground, add vertical speed to player
oldy# = oldy# + vy#
ground = 0
endif
rem jumptimer will decrease only when player is back on ground
rem creates a pause between two successive jumps
if ground = 1 and jumptimer>0 then dec jumptimer
rem handle horizontal movement as sliding
rem player only collides with group 1 (level) objs and moves freely through others
collide = sc_SphereSlideGroup(1,oldx#,oldy#,oldz#,x#,oldy#,z#,radius#,0)
if collide>0
rem if hit, reposition player, halt movement vector
x# = sc_getCollisionSlideX()
oldy# = sc_getCollisionSlideY()
z# = sc_getCollisionSlideZ()
vx# = 0
vz# = 0
rem possible code for giving the player a jumping help up stairs...
rem might be useful if slope# is set very high but stairs are still required
`dy# = oldy#-sc_getStaticCollisionY()
`if dy#<slope# and dy#>0 and ground=1 then vy# = 0.5
endif
rem position the player
position object 2,x#,oldy#,z#
sc_updateObject 2
endfunction
function positionCameraToObject(obj,thirdPerson)
position camera object position x(2),object position y(2),object position z(2)
rotate camera object angle x(2),object angle y(2),object angle z(2)
if thirdPerson=1
pitch camera down 10
move camera -30
endif
endfunction
if memblock exist(1) then delete memblock 1
So what am I doing wrong? How come it works fine for Sparky but doesn't work for me? Am I overlooking something or updating something wrong?
Thanks to any and all who help me figure this out!