Falling When Running Into Two Walls At Once

Blitz3D Forums/Blitz3D Programming/Falling When Running Into Two Walls At Once

Whats My Face(Posted 2010) [#1]
Basically, I have a player and he runs along the ground and does it fairly well. However, when that player runs into two walls his ability to also run into the ground is somewhat impaired. So for several frames he will fall through the ground and then be reset for no good reason. Heres the code for the walking function

Heres some video of the problem if that helps:
http://www.youtube.com/watch?v=QUtHQ61kOwo

Don't ask me what happened to it near the end but you can get a clear view of the problem before the video looks bad.

	charAction = IDLE
	
	;jumping + gravity
	Local playerCollided = EntityCollided(player,ENVIRONMENTTYPE)
	Local collisionIndex
	Local touchingGround = False
	
	TranslateEntity player,0,-.05,0 ;push the player down to make sure he is touching the ground
	
	;cycle through the player collisions
	If playerCollided <> 0 Then
		For collisionIndex = 1 To CountCollisions(player) 
			;this just gives a visual cue as to where the collision is
			PositionEntity colcube[collisionIndex],CollisionX#(player,collisionIndex),CollisionY#(player,collisionIndex),CollisionZ#(player,collisionIndex)
			ShowEntity colcube[collisionIndex]
			
			;if the collision is under the player then
			If CollisionY#(player,collisionIndex) < EntityY#(player) Then
				touchingGround = True ;tell the computer hes touching the ground
				nx# = CollisionNX#(player,collisionIndex) ;get the normals
				ny# = CollisionNY#(player,collisionIndex)
				nz# = CollisionNZ#(player,collisionIndex)
				If playerYV# < -.5 curHealth# = curHealth# + maxHealth*(playerYV#/2.50) ;subtract health if he fell too far
				RotateEntity character,0,0,0 ;make sure that the player is upright
				RotateEntity player,0,EntityYaw#(player),0
			
			;if the collision is over the player
			ElseIf CollisionY#(player,collisionIndex) > EntityY#(player)+.6 Then
				If playerYV# > 0 playerYV# = 0 ;stop his upward momentum
			EndIf 
		Next  
	EndIf
	
	;if the player not touching the ground
	If touchingGround = False Then
		TranslateEntity player,0,.05,0 ;move the player back down (we move him up above to smooth collisions)
		timeSinceLastGround = timeSinceLastGround + 1 ;add 1 to a counter that counts how many frames since the last collision
	Else
		timeSinceLastGround = 0
	EndIf 
	
	;keep player from getting stuck in corners (fixes a bug that kept player who were falling from a jump from getting stuck)
	If Abs((EntityY#(player)-oldPlayerY#)-playerYV#) > .001 Then
		jumpXComp# = 0
		jumpZComp# = 0
	EndIf 
	
	;this rotates the player so hes facing on the lay of the land but save the pitch yaw and roll so we can put him back after hes done
	pitch# = EntityPitch#(player)
	yaw# = EntityYaw#(player)
	roll# = EntityRoll#(player)
	AlignToVector player,nx#,ny#,nz#,2
	
	;character movement
	If KeyHit(33) And chatOn = False autorun = 1-autorun
	Local currentlyMoving = 0
	
	;turns off autorun if the player presses a key
	If KeyDown(200) Or (KeyDown(17) And chatOn = False) Or (mouse1down And mouse2down) Or KeyDown(208) Or (KeyDown(31) And chatOn = False) autorun = 0
	
	;if the player should be going foward
	If ((KeyDown(200) Or (KeyDown(17) And chatOn = False) Or (mouse1down And mouse2down) Or autorun = 1)) And ((touchingGround = True) Or (timeSinceLastGround < 10)) Then 
		;if the player is going up too steep a hill then face him down so he can't walk up it
		If (EntityPitch#(player)+Abs(EntityRoll#(player)) < 60) Or (EntityPitch#(player) <= 0) Then 
		Else
			RotateEntity player,-15,EntityYaw#(player),0
		EndIf
		
		;tell the computer that hes moving, move him, and set the anim seq to moving 
		currentlyMoving = 1
		If playerYV# <= 0 MoveEntity player,0,0,-.2 
		charAction = MOVING 
	
	;if the player is supposed to be going backwards do much the same thing
	ElseIf (KeyDown(208) Or (KeyDown(31) And chatOn = False)) And (touchingGround = True Or timeSinceLastGround < 10)
		If (EntityPitch#(player)-Abs(EntityRoll#(player)) > -60) Or (EntityPitch#(player) >= 0) Then 	
		Else
			RotateEntity player,15,EntityYaw#(player),0
		EndIf 
		currentlyMoving = -1
		If playerYV# <= 0 MoveEntity player,0,0,.2
		charAction = MOVING
	EndIf 
	
	;rerotate the player to his original rotation
	RotateEntity player,pitch#,yaw#,roll#
	
	;turn the player if he's got the turn keys down
	If KeyDown(203) Or (KeyDown(30) And chatOn = False) Then
		TurnEntity player,0,2,0
	ElseIf KeyDown(205) Or (KeyDown(32) And chatOn = False)
		TurnEntity player,0,-2,0
	EndIf 
	
	;if the player isn't touching ground
	If touchingGround = False Then
		;and he hasn't been touching the ground for at least ten frames make him touch the ground
		If timeSinceLastGround >= 10 charAction = JUMPING
		playerYV# = playerYV# - .025 ;move him downwards
		TranslateEntity player,jumpXComp#*.2,0,jumpZComp#*-.2 ;if he had any momentum move him that way
	Else
		playerYV# = 0
	EndIf 
 	
	;if the player is touching the ground then take away the momentum that he had when he was jumping
	If touchingGround = True Then
		jumpZComp# = 0 
		jumpXComp# = 0
	EndIf 
	
	;jumP + store momentum of jump
	If KeyHit(57) And touchingGround = True And chatOn = False Then
		playerYV# = .4
		jumpZComp# = Cos(EntityYaw#(player))*currentlyMoving
		jumpXComp# = Sin(EntityYaw#(player))*currentlyMoving
	EndIf 
	
	;gravity + save the playerY so that it can be used on the next loop
	If playerYV# < -2.5 Then playerYV# = -2.5
	oldPlayerY# = EntityY#(player)
	TranslateEntity player,0,playerYV#,0
	
	;animation
	If charAction = IDLE Then
		If AnimSeq(character) <> 1 Animate character,1,.1,1
	ElseIf charAction = MOVING Then
		If AnimSeq(character) <> 2 Animate character,1,1,2
	ElseIf charAction = JUMPING Then
		If AnimSeq(character) <> 3 Animate character,2,1,3
	EndIf 
	
	;camera rotation (for when the user wants to pivot around the player mesh)
	If curPlayerKeyMode = RUNMODE Then 
		Local mxs = MouseXSpeed()
		Local mys = MouseYSpeed()
		
		If mouse1down And mouse2down=0 Then
			TurnEntity campiv,-mys/3.0,-mxs/3.0,0
		ElseIf mouse2down Then
			If mouse2hit Then
				RotateEntity player,0,EntityYaw#(campiv)+EntityYaw#(player),0
				RotateEntity campiv,EntityPitch#(campiv),0,0
			EndIf 
			
			TurnEntity player,0,-mxs/3.0,0
			TurnEntity campiv,-mys/3.0,0,0
		Else
			TurnEntity campiv,-EntityPitch#(campiv)/10,-EntityYaw#(campiv)/10,0
		EndIf 
	EndIf 
	
	If EntityPitch#(campiv) > 80 RotateEntity campiv,80,EntityYaw#(campiv),0
	If EntityPitch#(campiv) < -80 RotateEntity campiv,-80,EntityYaw#(campiv),0
	
	RotateEntity campiv,EntityPitch#(campiv),EntityYaw#(campiv),0
End Function



Ross C(Posted 2010) [#2]
If it's any help, i usually use blitz collisions, in conjunction with a short linepick downwards, to make sure the player is actually touching the ground.


Ross C(Posted 2010) [#3]
Looking at this further, i would say the align to vector command could be causing this, be feeding the wall vectors to the align command, and very briefly causing the player to be aligned to the wall, therefore making forward, be upwards.


Whats My Face(Posted 2010) [#4]
Thanks Ross C! Your line picking technique fixes 99% of the cases.


Warner(Posted 2010) [#5]
You might try setting up a different collision type for walls and floors.
If you want to walk on your model, you could split the model up into a 'walls' part and a 'floors' part.