Character is Getting Stuck

Blitz3D Forums/Blitz3D Programming/Character is Getting Stuck

Whats My Face(Posted 2010) [#1]
for video of this problem go to:
http://www.youtube.com/watch?v=hR5bdggt-BA

Basically if I jump into some corners, very special ones (see video), my character will hover just a bit above the ground. He can still walk but even though MoveEntity is acting upon him he doesn't go anywhere

Walking Code
charAction = IDLE
	
	;jumping + gravity
	Local playerCollided = EntityCollided(player,ENVIRONMENTTYPE)
	Local collisionIndex
	Local touchingGround = False
	
	TranslateEntity player,0,-.1,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) 
			;if the collision is under the player then
			If CollisionY#(player,collisionIndex) < EntityY#(player)-.1 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#)/3.0) ;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)+.8 Then
				If playerYV# > 0 playerYV# = -playerYV# ;stop his upward momentum
			EndIf 
		Next  
	EndIf
	
	If collisionIndex >= 2 Then
	If touchingGround = False Then
		LinePick EntityX#(player),EntityY#(player),EntityZ#(player),0,-.95,0,.3
		If PickedEntity() <> 0 Then
			nx# = 0
			ny# = 0
			nz# = 0
			touchingGround = True
		EndIf 
	EndIf 
	EndIf 
	
	;if the player not touching the ground
	If touchingGround = False Then
		TranslateEntity player,0,.1,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
		If timeSinceLastGround > 1 Then
			jumpXComp# = 0
			jumpZComp# = 0
		EndIf 
		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 And collisionIndex >= 3 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)
	
	playerNX# = playerNX# - ((playerNX#-nx#)/2)
	playerNY# = playerNY# - ((playerNY#-ny#)/2)
	playerNZ# = playerNZ# - ((playerNZ#-nz#)/2)
	
	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)) < 40) Or (EntityPitch#(player) <= 0) Then 
			If playerYV# <= 0 MoveEntity player,0,0,-.2 
			currentlyMoving = 1
		EndIf 
		
		;tell the computer that hes moving, move him, and set the anim seq to moving 
		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)) > -45) Or (EntityPitch#(player) >= 0) Then 	
			If playerYV# <= 0 MoveEntity player,0,0,.2
			currentlyMoving = -1
		EndIf 
		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 
	
	;jumP + store momentum of jump
	If KeyHit(57) And touchingGround = True And chatOn = False And PlayerYV# <= 0  Then
		touchingGround = False 
		playerYV# = .4
		jumpZComp# = Cos(EntityYaw#(player))*currentlyMoving
		jumpXComp# = Sin(EntityYaw#(player))*currentlyMoving
	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
		If playerYV# < 0 playerYV# = 0
	EndIf 
 	
	;gravity + save the playerY so that it can be used on the next loop
	If playerYV# < -3 Then playerYV# = -3
	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 
		
		If mouse1down And mouse2down=0 And clicklock = False 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



Kryzon(Posted 2010) [#2]
I'd say don't collide with the environment itself, but a hidden (with zero alpha, not HideEntity), lower poly version of it.

When you collide with those specific corners, the math can be quite jerky and eventually it'll stuck your character. Having a "lower resolution" mesh to act as a collider will avoid such issue.


Collisions with levels:
Make a detailed level model as normal and split it up into sections. Don't give this mesh a collision type but rather create a mesh that has basically the same layout with as few polygons as possible, with as little detail as required, set its alpha to zero and use it for detecting collisions between characters and the level.

http://blitzbasic.com/Community/posts.php?topic=39205#497038

You don't need that collider mesh for the whole level, though. Only for buildings and structures where the detail might get your character stuck. Things like terrains and ground can be kept by themselves.