This is a short program I wrote to demonstrate my terrain collision. I needed a very versatile way to do collision with almost any surface on a map, so I used Kensupen's basic sliding collision idea and Sparky's collision commands to create this. You slide horizontally and vertically off of any surface with a slope greater than about 45 degrees, but can walk on any surfaces with a slope lower than that. I will be using this in the game I'm creating, and I hope this is useful to someone else. Please post with comments, suggestions, or problems, and also post your performance and fps with this. You can download the whole program with attached media, but I've also supplied the source below.
rem the speed MUST be lower than the radius for collision to work right
radius#=0.4
speed#=0.1
gravity#=0.01
rem this defines the maximum steepness of a climbable slope, where 0.707 is a 45 degree slope
rem this value should be tweaked with caution, because setting it too high or low causes problems
global slope#=0.7
rem number of directions to check collision in
global angles=8
temp#=360/angles : global anglesize#=temp#
rem setup the world
hide mouse
sync on
set camera range 0.01,5000
position camera 0,15,0
set ambient light 0
make light 1
set point light 1,0,30,0
set light range 1,200
set normalization on
global level=1
load object "level.x",level
scale object level,200,200,200
position object level,0,0,0
setupterraincollision level,0,100
do
rem rotate the camera
rx#=wrapvalue(rx#+mousemovey()/2)
ry#=wrapvalue(ry#+mousemovex()/2)
rotate camera rx#,ry#,0
rem move the camera horizontally
if keystate(17)=1
position camera newxvalue(camera position x(),ry#,speed#),camera position y(),newzvalue(camera position z(),ry#,speed#)
else
if keystate(31)=1 then position camera newxvalue(camera position x(),wrapvalue(ry#-180),speed#),camera position y(),newzvalue(camera position z(),wrapvalue(ry#-180),speed#)
endif
rem peform collision check twice for smoothness
cameracollision(radius#)
cameracollision(radius#)
rem set positional variables
x#=camera position x()
y#=camera position y()
z#=camera position z()
inc grav#,gravity#
newy#=y#-grav#
rem if the camera will collide after gravity is performed
if intersectobject(level,0,x#,y#,z#,x#,newy#-radius#,z#,0)=1
rem if the ground is not too steep, set gravity to initial amount
if getcollisionnormaly()>slope#
grav#=gravity#
endif
rem position the camera at the right height above the ground
position camera x#,getstaticcollisiony()+radius#,z#
rem perform collision check twice for smoothness
cameracollision(radius#)
cameracollision(radius#)
else
rem if the camera doesn't collide from gravity, position it at its new location
position camera x#,newy#,z#
endif
rem print fps, refresh, and loop
text 10,10,"fps: "+str$(screen fps())
sync : loop
rem the collision function
function cameracollision(radius#)
rem set variables
x#=camera position x()
y#=camera position y()
z#=camera position z()
ry#=camera angle y()
cd#=radius#*2
rem perform multiple collision checks in different directions
for x=0 to angles-1
rem calculate the new angle and the new x and z positions
a#=wrapvalue(ry#+x*anglesize#)
tx#=newxvalue(x#,a#,radius#)
tz#=newzvalue(z#,a#,radius#)
rem if camera is too close to a wall
if intersectobject(level,0,x#,y#,z#,tx#,y#,tz#,0)=1
collision=1
rem get the distance to collision
d#=getcollisiondistance()
rem if new distance is closer than the current closest distance
if d#<cd#
rem store new values
cd#=d# : ca#=a#
cx#=getstaticcollisionx()
cz#=getstaticcollisionz()
ny#=getcollisionnormaly()
endif
endif
next x
rem if a collision occurred and the slope was too steep, position camera away
if collision=1 and ny#<slope#
position camera newxvalue(cx#,wrapvalue(ca#-180),radius#),y#,newzvalue(cz#,wrapvalue(ca#-180),radius#)
endif
endfunction
rem required in order for Sparky's collision to work
null:
if memblock exist(1)=1 then delete memblock 1
return
"Genius is 1% inspiration and 99% perspiration"