Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411528 Posts in 69377 Topics- by 58432 Members - Latest Member: Bohdan_Zoshchenko

April 28, 2024, 09:59:01 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Box2D Platformer Implementation
Pages: [1]
Print
Author Topic: Box2D Platformer Implementation  (Read 8351 times)
Willseph
Level 0
**


Code monkey.


View Profile WWW
« on: January 19, 2011, 09:14:10 PM »

Hello there TIG. I haven't posted in a while but I thought I might as well. I've been working a lot with Box2D lately, which really is a great tool if you're into making 2D physics games like Angry Birds and the sort. However, one of the most interesting applications I could think of to use Box2D for was a platformer game. Sure platformers are a dime a dozen, but my theory was that using the Box2D engine would greatly ease tedious things like level design instead of using the conventional tile method, as well as provide some pretty cool effects for your game. Maybe your character can shoot at buildings and have them fall down realistically, or perhaps you wanted to make a platform game with an easy way to manipulate gravity. The possibilities are endless.

However, there was an issue with this concept. On one hand, you want the player to be a solid object acting upon the other objects in the world, such as the ground and platforms and gravity. This leaves the player's body at the mercy of the physics engine, which is fine. The problem comes when you also have to deal with user control. You no longer have complete control over the player's movement, because if you just used the arrow keys or whatever configuration you like, you would probably end up modifying the player's body's position directly, which counteracts the physical world.

In real life, you walk because you transfer energy from your leg against the floor, and because of friction, you push against the ground and propel yourself forward. This is probably very obvious, but considering we're somewhat mimicking human movement when making a platformer, it's hard to get your player to be controlled nicely. That is, unless you program little legs and feet on your player to have it push against the ground using various joints and other things provided by Box2D, but I think a game called QWOP tried this and you can see how that turned out.



Researching this problem online, I found a handful of articles that tackle it. They all look pretty good, but I had trouble understanding the details on how to control the movement. I didn't find tutorials as much as I just found long lines of commentless code. Well I've been working on it for a while and I think I've found a fairly simple and efficient solution.

Box2D has many functions dealing with force, one particularly useful one located in b2Body called ApplyImpulse. If you are unfamiliar with Box2D, this function basically applies a sudden force on a body given a particular vector. The magic happens when you apply a very small horizontal force continuously. Imagine your character has small rockets on its sides, and you can control the thrust with your control scheme.

However, this creates the issue of over-acceleration. Even holding it down for just a few seconds builds up so much velocity, it flies across the screen. However, keeping the impulse low but only applying it when its horizontal velocity is too low seems to work surprisingly well as a platformer-like control style. This allows the player to control the player well, while the physics engine still overpowers any user control without any conflict.

You can see a demo in action by clicking the image below. Use WASD to control the character (the blue block) around the screen. Just to demonstrate how the player is affected just like any other physical body, click anywhere on the screen to attract nearby objects, including the player.



There are still some kinks to work out, most notably the fact that while in air, the character doesn't slow down like it would in a typical platformer game. I know this has been a pretty lengthy post, but I hope I could shed some light on the subject for anyone curious about this as well. I'm still a novice, so constructive criticism is always greatly appreciated! If anyone would like me to post the source code to my demo I would be happy to.
Logged
SFBTom
Level 1
*



View Profile WWW
« Reply #1 on: January 20, 2011, 03:18:21 AM »

What you're after is a nice bit of air resistance or drag for your world. This'll stop your character from over accelerating by providing a force with a magnitude proportional to it's speed, which is exactly why falling objects in the real world have a terminal velocity.

Sadly, I don't recall Box2D including proper drag, at least not in the Flash port. You do have a property called linearDamping in your b2BodyDef class though, which simulates it to a certain degree. It defaults to 0, but any value above that (0-1) will produce a basic damping effect similar to air resistance. Try out different values, see what feels the nicest.


I would recommend trying another physics engine, one that does have more flexibility. The Box2D port is nice, and well documented, but it's far from the fastest engine out there, and on a personal note, the c-like naming conventions bug me.

I'd try out the motor2 engine, based on the original Box2D code but with many additions and speed improvements specific to the AS3 language.

Or if you're feeling daring, try the nape engine, which is just about the fastest engine I know, and is very usable in the context of a game (I used it in this game). It's a different approach than Box2D though, so it takes a little getting used to.
« Last Edit: January 20, 2011, 03:23:28 AM by SFBTom » Logged

Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #2 on: January 20, 2011, 09:13:25 AM »

I'd try out the motor2 engine, based on the original Box2D code but with many additions and speed improvements specific to the AS3 language.

The stacked blocks in the demo for motor2 seems a lot more stable than its Box2D equivalent, so I'll definitely check it out. Thanks for the tip!
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #3 on: January 20, 2011, 11:43:05 AM »

Or if you're feeling daring, try the nape engine. It's a different approach than Box2D though, so it takes a little getting used to.
Really, how so?
Logged
SFBTom
Level 1
*



View Profile WWW
« Reply #4 on: January 20, 2011, 02:17:19 PM »

It's mostly that box2dflashas3 and motor2 are based on the original Box2D, whereas nape was built from the ground up, inspired by other engines like glaze and chipmunk. The callback system is a little different too, but overall it's not much of a hurdle.
Logged

zacaj
Level 3
***


void main()


View Profile WWW
« Reply #5 on: January 21, 2011, 04:13:17 AM »

I dont see what you mean about the not slowing down... 
Logged

My twitter: @zacaj_

Quote from: mcc
Well let's just take a look at this "getting started" page and see--
Quote
Download and install cmake
Noooooooo
Golds
Loves Juno
Level 10
*


Juno sucks


View Profile WWW
« Reply #6 on: January 21, 2011, 04:57:08 AM »

You don't slow down in the air in Mario or Meat Boy....
Logged

@doomlaser, mark johns
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #7 on: January 25, 2011, 12:58:32 PM »

I've been working on it a little more and I thought I'd post the newer version to see what you guys think of the controls. There's still a little bit of tweaking to do with the wall-jumping, but overall I think it's very fun and playable.

WASD moves, jump against platforms to cling to them, holding down the mouse attracts objects (including the player). This is a very bare demo, so when playing, consider that it's all built in Box2D and the player can interact with all these different objects.

It also uses SFBTom's amazing Sxfr port to generate the random jumping sound as a test. Obviously the Mario sprite is just a test for character movement animation as well. The yellow ball on the far right is a test to switch between levels/screens; all of the levels are in their own Level child classes, and switching between them is easy and handles all of the body deletions from the previous levels.

Check it out here:
http://www.newgrounds.com/dump/item/6d4ce140a4bd9f7c7e5d3820db837ed5
Logged
Golds
Loves Juno
Level 10
*


Juno sucks


View Profile WWW
« Reply #8 on: January 25, 2011, 01:12:53 PM »

Feels pretty good, though the gravity is awfully moonlike.  If it were me, I'd bump up the gravity up about 1.5-2x where its at now and adjust jump velocity accordingly.
Logged

@doomlaser, mark johns
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #9 on: January 25, 2011, 01:14:21 PM »

Duly noted. Also I forgot to mention, the longer you hold down W, the higher you jump. I'm currently making another simple test level, so when I post that I'll fix the gravity first.
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #10 on: January 25, 2011, 01:16:09 PM »

Problems you might not realize you have:

1) You can hold yourself against vertical walls
2) You may have difficulties walking over a tiled surface (your level has none)
3) Mario has near infinite walk power - he could push crates thousands of times his weight.

No worries though, most box2d platforms end up in similar problems. You've at least avoided

4) Poor detection of when standing on solid ground.

I'd be interested to know how you did that part.
Logged
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #11 on: January 25, 2011, 01:29:30 PM »

Problems you might not realize you have:

1) You can hold yourself against vertical walls
2) You may have difficulties walking over a tiled surface (your level has none)
3) Mario has near infinite walk power - he could push crates thousands of times his weight.

No worries though, most box2d platforms end up in similar problems. You've at least avoided

4) Poor detection of when standing on solid ground.

I'd be interested to know how you did that part.

For #1, do you mean that you can grab walls and jump off of them? That was actually an issue I couldn't fix, so I just made it a "feature". However, this trick only works with designated platforms. I'll have to be careful when designing the levels in this case. Even still, glitchy fun > realism, in my opinion.

I'm not sure what you mean by tiled surfaces in #2. If you mean using tileblocks to design levels, I haven't tried it out yet but I don't really plan on doing that for this engine anyway.

#3, he actually doesn't but it seems like he does. It all depends on the masses of the other objects, but if I made them bigger you would see that eventually Mario can't push them any longer.

As for detecting when the player is on solid ground, I wrote this function:
Code:
private function onFloor():Boolean
{
for (var c:b2ContactEdge = body.GetContactList(); c != null; c = c.next)
{
if (c.contact.GetFixtureB().GetUserData() == "floor") return true;
}
return false;
}

Probably not the fastest method, but basically it calls that function to check when the W key is pressed (not upon every update). It looks at all the contact points on the player's body, and if any of them have the "floor" flag I've given to solid platforms, it returns true.

And sorry for the slow updates, I have some hardware issues at the moment so compiling Flash seriously takes like, 10 minutes.

EDIT: I forgot to mention that the onFloor() function isn't the only thing I use to tell if it's... well, on the floor. Technically this just checks to see if it's touching the floor. I use this in conjunction with checking the player's vertical speed to make sure it's 0 (or near 0).
Logged
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #12 on: January 25, 2011, 01:45:22 PM »

Okay I've uploaded the new version. Click the link in the post above or just right here:
http://www.newgrounds.com/dump/item/6d4ce140a4bd9f7c7e5d3820db837ed5
Logged
kefka
Level 0
**



View Profile WWW
« Reply #13 on: January 25, 2011, 07:18:32 PM »

Wow... after the first flash link you posted I was going to say:  I've tried doing platformers with Box2D before (in C++) and couldn't get it working.  The problem was always that making the player character part of the physics engine takes a lot of control away from the programmer in how to adjust the "feel" of the game, which is very important to me.  And with your first demo this problem is demonstrated...there are some weird feel issues, mainly when landing from a jump.

But the latest demo you posted is quite an improvement.  You've piqued my interest again in box2D.  I look forward to seeing how you develop this Smiley
Logged
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #14 on: January 25, 2011, 07:19:21 PM »

Thank you kefka! :D
Logged
FK in the Coffee
Level 10
*****


meme pixels


View Profile
« Reply #15 on: January 25, 2011, 07:46:03 PM »

Not sure if this is useful or not, but one game in particular that I think utilizes Box2D for platform physics exceptionally is

.  The character really reacts to forces around him like you'd expect he should, but at the same time, you never feel like you're losing control of him.
Logged
Willseph
Level 0
**


Code monkey.


View Profile WWW
« Reply #16 on: January 25, 2011, 09:01:07 PM »

Those look like some very impressive controls. This is my first successful attempt at this kind of engine, but I hope to practice with it on multiple platforms and improve on it over time.
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #17 on: January 26, 2011, 11:14:15 AM »

As for detecting when the player is on solid ground, I wrote this function:
Code:
private function onFloor():Boolean
{
for (var c:b2ContactEdge = body.GetContactList(); c != null; c = c.next)
{
if (c.contact.GetFixtureB().GetUserData() == "floor") return true;
}
return false;
}

Probably not the fastest method, but basically it calls that function to check when the W key is pressed (not upon every update). It looks at all the contact points on the player's body, and if any of them have the "floor" flag I've given to solid platforms, it returns true.

And sorry for the slow updates, I have some hardware issues at the moment so compiling Flash seriously takes like, 10 minutes.

EDIT: I forgot to mention that the onFloor() function isn't the only thing I use to tell if it's... well, on the floor. Technically this just checks to see if it's touching the floor. I use this in conjunction with checking the player's vertical speed to make sure it's 0 (or near 0).
Huh? It's possible to jump off of debris in your game, but presumeably that is not marked as floor.
« Last Edit: January 27, 2011, 11:10:33 AM by BorisTheBrave » Logged
goshki
Level 4
****



View Profile WWW
« Reply #18 on: January 27, 2011, 01:04:42 AM »

Okay I've uploaded the new version. Click the link in the post above or just right here:
http://www.newgrounds.com/dump/item/6d4ce140a4bd9f7c7e5d3820db837ed5

The controls seem very solid. Great work! One funny thing I've noticed is that if you happen to catch a falling block between Mario and the wall then the block gets glued to the wall (it stops falling - like if something pins it on the wall).
Logged

Trent
Level 0
***


Someday I'll make games!


View Profile WWW
« Reply #19 on: January 29, 2011, 02:16:28 AM »

Just wondering if you'd post the sourcecode. Wink

If you want to get rid of the wall-grabbing, you should set the body's friction to 0 when your feet aren't in contact with the ground. I'd suggest you use sensors and not just the body to detect the floor.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic