Box2D platformer concept

BlitzMax Forums/Brucey's Modules/Box2D platformer concept

_JIM(Posted 2009) [#1]
Hi,

I though I should ask more experienced users about this. I'm working on a platformer using Box2D.

My design looks like this so far:

Make the character a box2d body.
Move it left-right with SetVelocity(speed * direction).
Jump with ApplyImpulse.

Now, I'm stuck on checking when he can jump. I was thinking about checking for collisions, get the normal vector of the surface the character is standing on, then jump only is it's not steeper than 30 degrees.

I've also seen an example where 3 points were picked around the character, and he could jump only if the 3 points hit objects. However, I find this a bit flawed in certain scenarios.

Last, I though about a more realistic concept. That is, build the player out of 2 connected bodies. Think of the first one as the character body, and the second one the feet. When jumping, just push the feet down with an impulse and set a distance and angle constraint. This should work in all scenarios and even have sweet side effects (like when jumping off an airborn object). But it might be quite hard to implement.

I'd love to hear your opinions on this.


Armitage 1982(Posted 2009) [#2]
This is how I'm working (I need to rewrite the code) :

First I cut the corners of my Player rectangle shape to cross more easily slopes (SetFixedRotation to true)
Then in the contact point resolver I setup at least 4 variables

againstDownWall
againstUpWall
againstRightWall
againstLeftWall


This help me to see if the player is on the ground or is falling against a wall, hit the ceiling, etc.
(Be carefull, the sending point object is sometimes your player sometimes objects/grounds depends on many parameters but basically you have to invert sign).

To determine the surface step I'm using the cp.normal.Y() and set a jumpAllowed:int as well as a forceSlope:float flags.
I'm not using set linearVelocity to move my character but rather impulse forces for various reasons and then adding the forceSlope (+speed force,-damping force, etc.) to walk more slowly as the ground rises.
When Y Normal reaches a certain threshold I reset forceSlope and remove the jump allowance then my player naturally fall or stay in place.

...' In your contact resolver
Local signA:Double = 1.0
Local signB:Double = -1.0
Local obj2:Object
			
obj2 = cp.shape2.GetBody()
obj2 = b2Body(obj2).GetUserData()
			
' If Player is sending ContactPoint then reverse object cache and sign
If obj2 = Self
	obj2 = cp.shape1.GetBody()
	obj2 = b2Body(obj2).GetUserData()
	signA = -1.0
	signB = 1.0
End If
If Round(cp.normal.GetX()) = signA Then againstRightWall = 1
If Round(cp.normal.GetX()) = signB Then againstLeftWall = 1
If Round(cp.normal.GetY()) = signA Then againstUpWall = 1
If Round(cp.normal.GetY()) = signB Then againstDownWall = 1

setForceSlope(cp.normal.Y())

...

Function Round:Int(value:Double)
  Return value:Double + (0.5 * Sgn(value:Double))
End Function

Method setForceSlope(YNormal:Float)
	jumpAllowed = True		
	Local p:Float = YNormal + 1
	If p > 0.0 And p < 0.3 Then
		' Prevent a 'slope slip' bug
		If Not KeyDown(KEY_SPACE) Then forceSlope = p * 525
	Else
		' Disable jump on steep slope (0.0 = horizontal 1.0 = vertical)
		If p > 0.0 And p < 1.0 then jumpAllowed = False
		forceSlope = 0.0
	End If
	
End Method


The forceSlope parameters help my character to walk over 30% slope without too much slow down since I'm using impulsion and not linearVelocity settings.
You can probably find others solutions with that :)

The way I explain this is quite messy but I don't have much time for the moment :s
HTH


_JIM(Posted 2009) [#3]
Thanks for the explanation and code sample. I have a better understanding of what's going on. I'll try some new stuff when I get home.

I'm somewhat a beginner when it comes to Box2D and that slows me down as well. I'm tempted to try the last idea in my 1st post, but it seems really complicated to me right now.

Also, how do you cut the corners of your player shape? I'm using a sphere right now. (if I'm not mistaking, that should be really fast as well)


Armitage 1982(Posted 2009) [#4]
Yeah it's faster and you can keep a sphere if you like.
Me just choose a rectangle shape (polyshape in fact) because my player is more rectangular than spherical.
I thought it would be more realistic for collision with other objects.

But you can always use a sphere for ground interaction and a rectangular one (with correct bitmasking and groupmask) for objects.
You can also probably connect those two shapes with a particular joint and use a motor force to easily switch it on or off (think about a unicycle).

There is certainly not one solution with box2d which is why it's so great but also very complicated sometimes.