Box2D tutorial for the absolute beginners – revamped

About a year ago I published a Box2D tutorial for the absolute beginners.

With 2.1 release, a lot of things changed, so it’s time to publish another tutorial for the absolute beginners.

In this tutorial we’ll cover needed libraries to import, world creation, debug draw and the creation of static and dynamic boxes and circles. And obviously the simulation itself

This is the movie we are going to make:

And this is the script used to do it:

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	public class absolute extends Sprite {
		public var world:b2World=new b2World(new b2Vec2(0,10.0),true);
		public var world_scale:int=30;
		public function absolute():void {
			debug_draw();
			draw_box(250,300,500,100,false);
			draw_box(250,100,100,100,true);
			draw_circle(100,100,50,false);
			draw_circle(400,100,50,true);
			addEventListener(Event.ENTER_FRAME, update);
		}
		public function draw_circle(px,py,r,d):void {
			var my_body:b2BodyDef= new b2BodyDef();
			my_body.position.Set(px/world_scale, py/world_scale);
			if (d) {
				my_body.type=b2Body.b2_dynamicBody;
			}
			var my_circle:b2CircleShape=new b2CircleShape(r/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.shape=my_circle;
			var world_body:b2Body=world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
		}
		public function draw_box(px,py,w,h,d):void {
			var my_body:b2BodyDef= new b2BodyDef();
			my_body.position.Set(px/world_scale, py/world_scale);
			if (d) {
				my_body.type=b2Body.b2_dynamicBody;
			}
			var my_box:b2PolygonShape = new b2PolygonShape();
			my_box.SetAsBox(w/2/world_scale, h/2/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.shape=my_box;
			var world_body:b2Body=world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
		}
		public function debug_draw():void {
			var debug_draw:b2DebugDraw = new b2DebugDraw();
			var debug_sprite:Sprite = new Sprite();
			addChild(debug_sprite);
			debug_draw.SetSprite(debug_sprite);
			debug_draw.SetDrawScale(world_scale);
			debug_draw.SetFlags(b2DebugDraw.e_shapeBit);
			world.SetDebugDraw(debug_draw);
		}
		public function update(e : Event):void {
			world.Step(1/30,10,10);
			world.ClearForces();
			world.DrawDebugData();
		}
	}
}

Libraries

Libraries are imported at lines 4-7. Box2D folder and your .fla and .as files must be in the same folder

World creation

The only line needed to create an empty world is line 9. The world class is b2World and you must pass two parameters:

* the first one is a vector representing the world gravity.

* the second one is a boolean that allows you to improve performance by not simulating inactive bodies. In Box2D terminology, an inactive body is called “sleeping body”.

Now the world is ready, but you must face the problem of representing meters with pixels. Box2D works with meters, and there is a rule saying 1 meter = 30pixels. That’s why at line 10 I am declaring world_scale at 30. You can find more information about pixels and meters at this post.

Debug draw

As you should know, Box2D does not render the scene, it’s up to you attaching real objects to Box2D bodies. Anyway, there is a debug environment you can see at lines 44-52. This is the simplest debug draw you can make: basically you create a sprite and assign it to a b2DebugDraw class. More theory about debug draw theory at this post.

There are more options to configure the debug draw, but at the moment we are keeping things as simpler as we can. Notice at line 49 how I am setting the debug scale at the same value of the world scale.

Creation of a box

The most basic box is defined by an origin (the centre of the box), a width and an height. We are doing it at lines 31-43.

Let’s see the anatomy of a simple Box2D box.

A box is a body that must be static or dynamic. Only dynamic boxes are affected by gravity, collisions and physics forces. Static ones remain immovable.

Once we create a body (line 32) place it into the world (line 33) and set it as dynamic or not (lines 34-36), we just created a generic body.

It’s time to create a polygon shape (line 37) and define it as a box (line 38). Notice when I define the shape as a box, both width and height are divided by the world scale and by 2. The second division is necessary because the SetAsBox function wants the half width and the half height.

Now we have a body and a polygon. It’s time to create a fixture. The fixture will hold various attributes such as density and restitution, but at the moment to keep things easy I just want to create a fixture (line 39) and assigning it the polygon shape previously created (line 40)

Then it’s time to place the generic body in the world (line 41) and to assign it the fixture previously created with the attached shape (line 42).

And finally the box is created.

Creation of a circle

The creation of a circle is very similar to the box creation, the only difference is the shape this time is a circle shape (line 25) the radius as parameter.

The simulation

We simulate the world in three steps: first we update the world (line 54) passing the amount of time to simulate (normally 1/30), the velocity constraint solver and the position constraint solver.

Constraint solvers determine how many times the engine sweeps over all the contacts and joints in the world to find the final position and velocity of each body. More iterations always yields a better simulation.

Finally we need to clear forces (line 55) to give more stability and it’s time to draw the debug data (line 56) if you are using the debug draw.

In the end…

In the end I created a large static box (line 13), a small dynamic one (line 14), a static (line 15) and a dynamic (line 16) sphere and I am updating the world at every frame (line 17).

Download the source code, library included.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers