Platform game basics using Box2D
- October 26, 2008 by Emanuele Feronato
- Filed under Actionscript 3, Box2D, Flash, Game design, Users contributions | 29 Comments
I wrote about Box2D Flash version about a year ago, then I published Playing with Box2DFlashAS3 and Create a Flash game like Totem Destroyer as examples covering what you can do with this library.
But I was really impressed by a thread on TriquiTips submitted by Hawdon called Box2DAs3 For Beginners! (read steps 1 and 2) that in my opinion deserves to be posted on this blog, to reach a wider public… because I know there is a lot of people looking for AS3 and Box2D and platform tutorials… and the prototype made by Hawdon merges them all this way:
Left-right to move and up to jump
This is the source code with some comments
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | package {
// Imports some things into the movie.
import flash.display.Sprite;
import flash.events.*;
import flash.events.KeyboardEvent;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
public class Box2d extends Sprite {
public function Box2d() {
addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, KeyUp);
var worldAABB:b2AABB = new b2AABB();//Creates a new world
worldAABB.lowerBound.Set(-100.0, -100.0);//Sets the lower bloundaries of the world (If a shape goes outside this it will freez)
worldAABB.upperBound.Set(100.0, 100.0);//Sets the upper bloundaries of the world (If a shape goes outside this it will freez)
var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);//Sets gravity. First number is Y and second is x
var doSleep:Boolean = true;//If the shapes are allowed to sleep. (Stop simulating)
m_world = new b2World(worldAABB, gravity, doSleep);//Sets everything together to make a Box2d World
CreateBox(275, 375, 600, 50, true, new Ground());//Ground
CreateCircle(250, 100, 50, false, new Circle());//Ball
CreateHero(200, 300);//Player
CreateBox(500, 302, 200, 100, true, new Ground());//Static Box on right side
/* following code makes some stacks of blocks*/
for (var x:int = 1; x<4; x++) {
for (var i:int = 1; i<11; i++) {
CreateBox(((300+(20*x))-(.25*i)), (365-(20*i)), 20, 20, false, new Box());
}
}
}
/*
I personaly think its MUCh easier to put the code into functions,
because then you dont need to type it again, and again, and again. And it works just fine with function like createCircle and createBox.
And when its time to start making levels, you will have a lot less typing to do when you can just type in the function.
*/
/*
Following Function Creates the Hero
CreateHero(X Posision, Y Posision, Width of Hero, Height of Hero)
*/
public function CreateHero(x:Number, y:Number, width:Number = 20, height:Number = 20) {
bodyDef = new b2BodyDef();
bodyDef.position.x = (x)/physScale;
bodyDef.position.y = (y)/physScale;
boxDef = new b2PolygonDef();
boxDef.SetAsBox(GetRealWH(20), GetRealWH(20));
boxDef.density = 1.0;//Because the density is at higher then 0 it moves.
boxDef.friction = 0.3;
boxDef.restitution = 0.2;
bodyDef.userData = new PlayerBox();
bodyDef.userData.name = "Player";
bodyDef.userData.width = physScale * 2 * GetRealWH(width);
bodyDef.userData.height = physScale * 2 * GetRealWH(height);
body = m_world.CreateBody(bodyDef);
body.SetBullet(true);//Tells flash to treat it like a bullet (Continuous collision detection.)
body.CreateShape(boxDef);
body.SetMassFromShapes();
bodyDef.userData.body = body;//This is the only way I know that u can get a specific body from the World.
//If you have a better idea, tell me!
addChild(bodyDef.userData);
}
/*
Following function Creates a Circle
CreateCircle(X posision, Y Posision, Width/Height of ball, Is the ball static (Inmoveable), The movieclip you want to be shown as the circle (Example: new Circle())
*/
public function CreateCircle(x:Number, y:Number, width:Number, static:Boolean, Cover) {
/* Following Code creates a circle */
bodyDef = new b2BodyDef();
bodyDef.position.x = x/physScale;
bodyDef.position.y = y/physScale;
circleDef = new b2CircleDef();//Defines circleDef as a new b2CircleDef
circleDef.radius = GetRealWH(width);//Sets the radius of the ball
circleDef.density = 1.0;
circleDef.friction = 0.3;
circleDef.restitution = 0.2;
bodyDef.userData = Cover;//sets userData to a new Circle (See Library)
bodyDef.userData.width = 30 * 2 * GetRealWH(width);//Sets width and height. Third Number is the same as the radius.
bodyDef.userData.height = 30 * 2 * GetRealWH(width);
trace(bodyDef.userData.height);
body = m_world.CreateBody(bodyDef);
body.CreateShape(circleDef);
body.SetMassFromShapes();
addChild(bodyDef.userData);
}
/*
Following function creates a box
CreateBox(X posision, Y Posision, Width, Height, Is the box static (Inmoveable), The movieclip you want to be shown as the box (Example: new Box())
*/
public function CreateBox(x:Number, y:Number, width:Number, height:Number, static:Boolean, Cover) {
/* Creates the static box on the right side of the screen*/
bodyDef = new b2BodyDef();
bodyDef.position.x = (x)/physScale;
bodyDef.position.y = (y)/physScale;
boxDef = new b2PolygonDef();
boxDef.SetAsBox(GetRealWH(width), GetRealWH(height));
if (static) {
boxDef.density = 0.0;
}
else {
boxDef.density = 1.0;
}
boxDef.friction = 0.3;
boxDef.restitution = 0.4;
bodyDef.userData = Cover;
bodyDef.userData.width = physScale * 2 * GetRealWH(width);
bodyDef.userData.height = physScale * 2 * GetRealWH(height);
bodyDef.isBullet = true;//This tells flash to treat all boxes like bullets. This is CPU consuming with a lot of boxes.
//But the hit test is WAY better when you use this.
body = m_world.CreateBody(bodyDef);
body.CreateShape(boxDef);
body.SetMassFromShapes();
addChild(bodyDef.userData);
}
/*
I hade to make this function because I noticed that
the width and height of the shapes were 2 times to large
even to I divided it by physScale.
This is because Box2d when doing width and height only takes from the center out.
For Example: if I use this SetAsBox(100/physScale, 100/physScale)
I will get a box that is 200x200 because the 100/physScale is the distance from the
center of the box to the top or the sides.
I made this function because I like using the numbers I usualy use in flash
when making games.
*/
public function GetRealWH(Num:Number) {
return Num / physScale / 2;
}
/*
Following functions a controls when any aroow key is pressed.
*/
public var Left:Boolean = false;
public var Right:Boolean = false;
public var Up:Boolean = false;
public function KeyDown(e:KeyboardEvent) {
trace(e.keyCode);
var TheChild = getChildByName("Player");
var Body = TheChild.body;
switch (e.keyCode) {
case 37 ://Left
Left = true;
break;
case 38 ://Up
Up = true;
break;
case 39 ://Right
Right = true;
break;
}
}
public function KeyUp(e:KeyboardEvent) {
trace(e.keyCode);
var TheChild = getChildByName("Player");
var Body = TheChild.body;
switch (e.keyCode) {
case 37 ://Left
Left = false;
break;
case 38 ://Up
Up = false;
break;
case 39 ://Right
Right = false;
break;
}
}
/* Following function gets the body from a cordinate (x, y)*/
public function GetBodyAtPoint(px:Number, py:Number, includeStatic:Boolean = false) {
// Make a small box.
var px2 = px/physScale;
var py2 = py/physScale;
var PointVec:b2Vec2 = new b2Vec2();
PointVec.Set(px2, py2);
var aabb:b2AABB = new b2AABB();
aabb.lowerBound.Set(px2 - 0.001, py2 - 0.001);
aabb.upperBound.Set(px2 + 0.001, py2 + 0.001);
// Query the world for overlapping shapes.
var k_maxCount:int = 10;
var shapes:Array = new Array();
var count:int = m_world.Query(aabb, shapes, k_maxCount);
var body:b2Body = null;
for (var i:int = 0; i < count; ++i) {
if (shapes[i].m_body.IsStatic() == false || includeStatic) {
var tShape:b2Shape = shapes[i] as b2Shape;
var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), PointVec);
if (inside) {
body = tShape.m_body;
break;
}
}
}
return body;
}
public function Update(e:Event):void {
/*Following code down to line 252 Makes the Player move left, right and jump*/
var TheChild = getChildByName("Player");//Getts a child named Box
var Body = TheChild.body;//Get the var body from the child.
if (Left) {//If Left Arrow is down
Body.WakeUp();//Wakes the body up if its sleeping
Body.m_linearVelocity.x = -3;//Adds to the linearVelocity of the box.
}
if (Right) {//If right arrow is down
Body.WakeUp();//Wakes the body up if its sleeping
Body.m_linearVelocity.x = 3;//Adds to the linearVelocity of the box.
}
if (Up) {
if (Body.GetLinearVelocity().y > -1) {//Stops player from sometimes jumpping higher then suppose to
/*
I have made 3 hit points.
*/
var Hit = GetBodyAtPoint(TheChild.x, TheChild.y+(TheChild.height/2+2), true);//Under
var Hit1 = GetBodyAtPoint(TheChild.x-(TheChild.width/2)+2, TheChild.y+(TheChild.height/2+2), true);//Down-Left
var Hit2 = GetBodyAtPoint(TheChild.x+(TheChild.width/2)-2, TheChild.y+(TheChild.height/2+2), true);//Down-Right
if (Hit != null && Hit.m_userData != TheChild) {
Body.ApplyImpulse(new b2Vec2(0.0, -3.0), Body.GetWorldCenter());//Applys and impuls to the player. (Makes it jump)
}
else if (Hit1 != null && Hit1.m_userData != TheChild || Hit2 != null && Hit2.m_userData != TheChild) {
Body.ApplyImpulse(new b2Vec2(0.0, -3.0), Body.GetWorldCenter());
}//Applys and impuls to the player. (Makes it jump)
}
}
};
Body.m_sweep.a = 0;//This is what stops the player from rotating
/*
But because its only called once a frame it will allow the player to rotate a little.
Which makes it more realistic.
*/
m_world.Step(m_timeStep, m_iterations);//This runns the Box2D World
//Body.m_sweep.a = 0; //If you wanned to take the tiny movement away you could move this code here.
// The follwoing code rotates, sets the x and y cordinates of the movieclips the player sees.
for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) {//Makes a for loop scanning all the bodys in the World
if (bb.m_userData is Sprite) {//Checks if bb.m_userData is a spirit (Movieclip)
bb.m_userData.x = bb.GetPosition().x * physScale;//Changes the x
bb.m_userData.y = bb.GetPosition().y * physScale;//Changes the y
bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);//Changes the rotation
}
}
}
/* Vars used in creating shapes */
public var body:b2Body;
public var bodyDef:b2BodyDef;
public var boxDef:b2PolygonDef;
public var circleDef:b2CircleDef;
public var m_world:b2World;
public var m_iterations:int = 15;
public var physScale:Number = 30;
public var m_timeStep:Number = 1.0/physScale;
}
} |
I have to say I am quite impressed about this work and I am porting my platform engine using Box2D, and release some Box2D tutorials if this post gets a good feedback.
They can be easily customized to meet the unique requirements of your project.
29 Responses
Leave a Reply
TUTORIAL SERIES:
- Una guida completa al gioco del poker online e una selezione dei migliori casino online.
- casino online
- migliori casino online
- BlackJack online
- casinò online

(31 votes, average: 4.48 out of 5)

Really nice, Box2D makes a realistic game, more than the tile engine.
Got to say, didn’t excpect you to post it on the blog…
But thanks!
I’m, too, very intérested to hear what ppl think.
If there is a lot of good feedback I might too post some more tutorials.
I caught this on Triqui and somehow messed up during the tutorial. So glad to have a reminder to try it once again! :)
“I have to say I am quite impressed about this work and I am porting my platform engine using Box2D…”
YAY! Made my week.
It would be much better if you finish your engine first….I would really apreciate it :P
You should check out sideroller.com, and the world creation kit [http://www.sideroller.com/wck/]
I like your website and I come here every day,please go on the BOX2D engine tutorial.
éžå¸¸æœŸå¾…ä½ çš„box 2d教程,也éžå¸¸å°Šæ•¬ä½ ,å¼å¼ï¼Œè¯·ä¸€å®šåŠ æ²¹ï¼Œæˆ‘æ˜¯ä¸€åFLASH GAME DEVELOPERï¼Œä¸€ç›´åœ¨å…³æ³¨ä½ çš„ç½‘ç«™ï¼Œéžå¸¸éžå¸¸éžå¸¸æœŸå¾…ä½ çš„ç‰©ç†å¼•擎教程
awesome!!!
Wow! Just awesome! I’m going to try to combine the previous platform engine with this one :D
AWESOME! make more tutorials about box2d!!!
Yay! I got the ball up the wall!
“…and I am porting my platform engine using Box2D…â€
That would be awsome!
awesome! box2d rocks!
box2d is awesome!!! because of this im going to learn as3!! please make more!!!!!
Thanks for another great tutorial! Box2D is awesome. More Box2D please :D !
what we could do for the scrolling?
i get alot of errors when i try to compile your example with the latest box3d code. Is there a newer Verison availabe? Did you alot of customizations to the Box2D Classes?
Yeah, it’s not working for me either, but I only get one error on line 1.
“5006: An ActionScript file can not have more than one externally visible definition: Box2d, body”
why making an tutorial it it’s full of errors ? :E
yeah, sure, i can make changes to use for my project, but what if i have no time ? and for very beginners?
[...] http://www.emanueleferonato.com/2008/10/26/platform-game-basics-using-box2d/ [...]
This tutorial it’s great, I was looking for something like this over the internet for a long time. However this example doens’t show how to scroll smothly the world like this game made with box2dAS3
http://www.huesforalice.com/project/box2d_tinger
Does anyone know some tutorial that could explain that?
Thank you
I really like your work and constant progression. Go on! You do great!
Just for you to know for linking bodies and graphics, i use this myself (the actor part):
http://www.box2d.org/wiki/index.php?title=Linking_graphics_to_bodies_in_Box2D_AS3
Hope it helps you someway!
JF
Really good tutorial, but it seems to have a little bug: if you jump into the wall and keep the right arrow pressed, the hero stays stuck on the wall and does not fall as it should.
Is there anyway to fix this?
Thanks.
to make this scroll do you just do that like normal and extend your Box2D bounding area?
since I guess that site went down this tutorial is really hard to follow. too many errors and with out the source I can’t figure them out!
SOURCE PLZ
tanks for sharing tutorial
How do we keep our player object from bouncing?!
[...] Box 2D for Absolute Beginners Pt 1 Box 2D for Absolute Beginners Pt 2 Creation of a Flash Artillery Game with Box2D Box2D Rope Platform Game Basics Using Box2D [...]
OK! now I have translate this great tutorial to fit fro Box2dAS3_2.1alpha.