Quote: " Just place all code in functions. Eg. A function for collision, and use that function in the player movement function."
-- Well, i have already done that. For me it is a lot easier to just handle the movement and collision in the same function, but i guess i could separate it if you think it would help?
Heres what im currently using, I dont think i decribed it accurately the first time.
`Imagine the main loop is here, and it calls MovePlayer(). OBJECT 2 has already been set up as my player object, OBJECT 1 is my terrain.
function MovePlayer()
rem rotate player with mouse
rx# = object angle x(2)+mousemovey()/3.0
if rx# > 65 THEN rx# = 65
if rx# < -65 THEN rx# = -65
yrotate object 2,object angle y(2)+mousemovex()/2
xrotate object 2,rx#
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)
angx# = object angle x(2)
vx# = 0
vz# = 0
`Check if player is underwater, if they are, apply special underwater style movement
`and less gravity.
`if player is not either underwater, jumping, or falling then apply gravity
`if on ground, attempt to keep the player stuck to the floor
if object position y(2)<WaterHeight#
plMoveUnderWater()
endif
if vy#=0 and jumptimer=0 then vy# = vy# + 10*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#)
if keystate(16)=1 then yrotate object 2,object angle y(2)-7
if keystate(18)=1 then yrotate object 2,object angle y(2)+7
rem only jump if on ground, and a certain time after last jump
if ground=1
if spacekey()=1 and jumptimer=0 then vy# = 0.5 : jumptimer = 20
endif
underwaterpass:
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#*3
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
`This ensures that if the player somehow falls thru the terrain, they are caught, and placed slightly above the terrain.
h# = get terrain ground height( 1, object position x(2), object position z(2) )
if oldy# < h# then oldy# = h#+2
`position the player
position object 2,x#,oldy#,z#
text 0,250,"X: "+str$(x#)
text 0,270,"Z: "+str$(z#)
text 0,290,"Y: "+str$(oldy#)
sc_updateObject 2
`reset gravity if user has been underwater
gravity#=-0.03
endfunction
`---Here is the underwater movement function.---
function plMoveUnderWater()
gravity#=0
if keystate(17)=1 then move object 2,1
if keystate(31)=1 then move object 2,-1
if keystate(30)=1 then move object left 2,1
if keystate(32)=1 then move object right 2,1
if spacekey()=1 then move object up 2,1
`This is the only way i know of that would allow me to skip into the middle of my code, without duplicating my collision code.
goto underwaterpass
endfunction
EDIT: I think I have found the problem, or one of them, anyway. Every time i try to do anything with the WaterHeight# variable and my player position, like putting: " if oldy# < WaterHeight# then oldy#=WaterHeight# " before the line " position object 2,x#,oldy#,z# ", it does nothing, so i think the problem is with the fact that i cant use the value of the variable for anything. I am using Evolved's Water Shader, and it clearly defines the variable, so I have no idea what im doing wrong.