jumping problem

Blitz3D Forums/Blitz3D Beginners Area/jumping problem

Cubed Inc.(Posted 2010) [#1]
Here's my problem. In my game, there is double jumping. I set up a flag where when the player is touching the map, jumping = 1. When jumping = 1, he can jump. Whenever he is not touching the map, jumping = 0, so he can't jump.

While in the air, pressing the key to jump makes jumping = 2, so he can jump again. When jumping = 2, he absolutly cannot jump anymore until he touches the map.

Now for the problem.

I used entitycollided to determine when the player lands on the floor so he can jump again. The problem is that when the player is colliding with ANYTHING on the map, walls, buildings etc, he can jump again, so there is now limit to how much you can jump, even when touching a wall.

Is there anyway to determine whether the player is touching the floor or touching the wall in a map? I'm honestly stumped.


Rob the Great(Posted 2010) [#2]
I had the same problem for a while, not with infinite jumping, but with the player hitting a wall and sliding down without getting hurt from a long fall.

There's a couple of ways you can correct this:

1. If possible, use a different EntityType on walls than you use on the floor. This would require separate meshes for each type, so this may not be an option.

2. Create a pivot at the players feet. Then create another pivot and place it directly at the point of the player/level intersection using CollisionX(), CollisionY(), and CollisionZ(). Last, perform an EntityDistance check between the two pivots. If they are close together, then you know that the player's "feet" are touching the ground, but if they are not close, then you know that it's the player's chest or head or somewhere other than the feet colliding. You can use this check to disable infinite jumping like you described above.

I was going to provide some sample code, but I don't have access to it right now, and I'm not thinking clearly enough to re-write it. Let me know if a sample would be helpful.


Cubed Inc.(Posted 2010) [#3]
Rob the Great
Seeing a sample would be very helpful. Also, I have another idea, but i'm not sure if I can use it.

You could use the findchild command to pick out peices of the map, let's say the floor, and create an entitytype for it. It sounds like it would make sense, but i'm still kinda weary on it.

I'm actually pretty interested in your idea, since you can do other things with the pivots, such as allow the player to jump on enemie heads to kill them.

If you could be generous enough, maybe you can try to re-write the example so I can get the idea better. I'm still very confused with collision functions.


Rob the Great(Posted 2010) [#4]
Give this a try. It's a little longer than I had remembered, but it works. When you run the demo, purposely jump around, and then run into a wall and try jumping off of that wall again:
Graphics3D 640,480,0,2  ;Set Up Graphics

SetBuffer BackBuffer()  ;Set Up the Buffer

While Not KeyDown(28)   ;This is just some demo text...

	Text 0,0,"The purpose of this demo is to show"
	Text 0,20,"how to determine if the player's feet are"
	Text 0,40,"touching the ground or not. This is"
	Text 0,60,"useful to ensure that your character"
	Text 0,80,"can't slide down walls or perform"
	Text 0,100,"double jumping when they hit a wall."
	Text 0,180,"Press Enter to Continue..."
	Flip
	
Wend

Cls

Type feet   ;Create a type for our feet. You'll need this later to keep track of all collisions for the player
	Field state$  ;We only need to store the current state of the specific collision
End Type

Global feettouching$ = "No"   ;This is a string variable to know for sure whether or not the feet of the player are touching the ground.

Global type_level = 1  ;Set Up the Level to be collision type 1
Global type_player = 2 ;Set Up the Player to be collision type 2

Global UPKEY = 200
Global DOWNKEY = 208
Global RIGHTKEY = 205
Global LEFTKEY = 203

Global sun = CreateLight(2)
PositionEntity sun,0,500,0

Global camera = CreateCamera()  ;Create a camera
MoveEntity camera,0,2,-5  ;Move it up 1 and back 10

Global player = CreateSphere()  ;Create a ball for our player
EntityColor player,255,0,0  ;Color him Red
EntityType player,type_player   ;Set our player to be collision type 2
Global playerfeet = CreateCube()  ;Create a cube to represent our player's feet
EntityColor playerfeet,0,0,255  ;Color his feet blue
MoveEntity playerfeet,0,-0.9,0  ;Move his feet where they need to be
ScaleEntity playerfeet,1,0.1,1  ;Make his feet the right size
EntityParent playerfeet,player  ;Now whever the player goes, so do the feet

Global feetpivot = CreatePivot()   ;Create a pivot for the feet
PositionEntity feetpivot,0,-0.7,0   ;This is roughly where the player's feet are
EntityParent feetpivot,player   ;The Feet Pivot will now follow the player
Global feetpivot2 = CreatePivot()   ;Create a second pivot for the feet. We will use this later to get collision location.

EntityParent camera,player   ;Just make the camera follow the player, makes for an easy camera system

Global level = CreatePlane()   ;Create an infinite plane for the ground
EntityColor level,0,255,0   ;Color the ground green
MoveEntity level,0,-5,0   ;Move the ground down 5
EntityType level,type_level   ;Set the level to be collision type 1

For i = 1 To 500   ;Use this for:next loop to make a multi-surface level
	cube = CreateCube()
	ScaleEntity cube,2,30,2
	PositionEntity cube,Rand(-100,100),0,Rand(-100,100)
	EntityColor cube,255,255,255
	EntityType cube,type_level
Next

Collisions type_player,type_level,2,3   ;Tell Blitz that you want collision type 2 (player) to collide with collision type 1 (level)

While Not KeyDown(1)   ;Until we push the esc key, the MAIN LOOP

	PointEntity camera,player   ;Point the camera at the player
	
	TranslateEntity player,0,-0.2,0   ;Gravity on our player, very slow fall to see the full effect
	
	GetPlayerMovement()   ;Call this function to use the arrows keys to move
	
	UpdatePlayerJump()   ;Call this function to make the player jump
	
	UpdateFeetCollision()   ;Call this function to see if the player's feet are touching

	RenderWorld   ;Tell Blitz to Update all 3D positions, rotations, ect.
	UpdateWorld   ;Tell Blitz to Update all Animations, Collisions, ect.
	If EntityCollided(player,type_level)   ;If the Player has collided with the level
		Text 0,0,"The Player has Collided with the Level."   ;Tell us that he has
	EndIf
	If Not EntityCollided(player,type_level)   ;If the player is in the air
		Text 0,0,"The Player is in the air."   ;Tell us that he is in the air
	EndIf
	Text 0,20,"Are the player's feet touching?   " + feettouching$
	Text 0,40,"Here's the distance between the the feet"
	Text 0,50,"and the point of the last collision: " + EntityDistance(feetpivot,feetpivot2)
	Flip   ;Physically draw all of the updated game to the screen
	
Wend   ;Return to the MAIN LOOP, repeat until we push the esc key



Function GetPlayerMovement()   ;Call this function to use the arrows keys to move


	If KeyDown(UPKEY)
		MoveEntity player,0,0,0.5
	EndIf
	
	If KeyDown(DOWNKEY)
		MoveEntity player,0,0,-0.5
	EndIf
	
	If KeyDown(RIGHTKEY)
		TurnEntity player,0,-5,0
	EndIf
	
	If KeyDown(LEFTKEY)
		TurnEntity player,0,5,0
	EndIf


End Function


Function UpdatePlayerJump()   ;Call this function to make the player jump (CRUDE EXAMPLE)


	If EntityCollided(player,type_level)   ;If the player is touching the level
		If KeyDown(57)   ;And if we hit the space bar
			If feettouching$ = "Yes"   ;This is the most important line. If, and only if, the feet are touching, can the player jump. Comment this line out to see the difference without it.
				TranslateEntity player,0,20,0   ;Just move the player up 10 and let gravity do the rest
			EndIf
		EndIf
	EndIf


End Function


Function UpdateFeetCollision()   ;Call this function to see if the player's feet are touching


	For x = 1 To CountCollisions(player)   ;For Every Single Collision that the Player had in this loop...
		f.feet = New feet   ;Create a new type feet to 'remember' this specific collision
		PositionEntity feetpivot2,EntityX(player),CollisionY(player,x),EntityZ(player) ;move the pivot to the vertical collision spot. X and Z don't matter.
		If EntityDistance(feetpivot,feetpivot2) <= 0.35   ;If the player's 'feet' and the collision location of the player are close...
			f\state$ = "Yes"   ;the feet type state of being string is True, Yes, Confirmed, the feet are touching
		EndIf
		If EntityDistance(feetpivot,feetpivot2) > 0.35   ;If the player's 'feet' and the collision location of the player are not close...
			f\state$ = "No"   ;the feet type state of being string is False, No, Denied, the feet are not touching
		EndIf
	Next   ;Go back to the top of this loop until we've done this for every single collision the player had in the main loop.
	
	For f.feet = Each feet   ;For every single feet type we've created up above...
		If f\state$ = "Yes"   ;If the feet type state of being for that one is True, Yes, Confirmed, the feet are touching...
			feettouching$ = "Yes"   ;then, even if it's only one collision, we now want to remember that the feet are touching.
		EndIf
	Next
	
	For f.feet = Each feet   ;Again, for ever single feet type we've created up above...
		Delete f   ;get rid of the bastards and start over for the next loop around
	Next
	
	If Not EntityCollided(player,type_level)   ;Finally, we need to check to reset the feettouching state if the player isn't touching the level anywhere
		feettouching$ = "No"
	EndIf


End Function

End   ;Kill this sample!!!

Read the comments in the sample carefully, and it should all make sense.

Let me know if there are questions or problems.