Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Actionscript 3, Box2D and Flash.

Nape is an open source physics engine written I Haxe by Luca Deltodesco which is also available for AS3 as swc library and is going to generate some interest about it.

In this post, I am creating a simple Hello World for both engines, with a dynamic square falling over a static floor, and explain the difference between the scripts.

Box2D

This is the script:

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 MainBox2D extends Sprite {
		private var world:b2World=new b2World(new b2Vec2(0,10),true);
		private var worldScale:Number=30;
		public function MainBox2D() {
			var debugDraw:b2DebugDraw = new b2DebugDraw();
			var debugSprite:Sprite = new Sprite();
			addChild(debugSprite);
			debugDraw.SetSprite(debugSprite);
			debugDraw.SetDrawScale(worldScale);
			debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
			debugDraw.SetFillAlpha(0.5);
			world.SetDebugDraw(debugDraw);
			var bodyDef:b2BodyDef=new b2BodyDef;
			bodyDef.position.Set(320/worldScale,460/worldScale);
			var polygonShape:b2PolygonShape=new b2PolygonShape();
			polygonShape.SetAsBox(320/worldScale,20/worldScale);
			var fixtureDef:b2FixtureDef=new b2FixtureDef();
			fixtureDef.shape=polygonShape;
			var staticFloor:b2Body=world.CreateBody(bodyDef);
			staticFloor.CreateFixture(fixtureDef);
			bodyDef.position.Set(320/worldScale,0/worldScale);
			bodyDef.type=b2Body.b2_dynamicBody;
			polygonShape.SetAsBox(25/worldScale,25/worldScale);
			fixtureDef.shape=polygonShape;
			var dynamicBox:b2Body=world.CreateBody(bodyDef);
			dynamicBox.CreateFixture(fixtureDef);
			addEventListener(Event.ENTER_FRAME, update);
		}
		private function update(e:Event):void {
			world.Step(1/30,10,10);
			world.ClearForces();
			world.DrawDebugData();
		}
	}
}

and this is the result:

Here we go with next engine:

Nape

This is the script:

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import nape.geom.Vec2;
	import nape.phys.Body;
	import nape.phys.BodyType;
	import nape.shape.Polygon;
	import nape.space.Space;
	import nape.util.ShapeDebug;
	public class MainNape extends Sprite {
		private var world:Space=new Space(new Vec2(0,500));
		private var debug:ShapeDebug=new ShapeDebug(640,480,0x00ff00);
		public function MainNape() {
			addChild(debug.display);
			var staticFloor:Body=new Body(BodyType.STATIC,new Vec2(320,460));
			staticFloor.shapes.add(new Polygon(Polygon.box(640,40)));
			staticFloor.space=world;
			var dynamicBox:Body=new Body(BodyType.DYNAMIC,new Vec2(320,0));
			var block:Polygon=new Polygon(Polygon.box(50,50));
			dynamicBox.shapes.add(block);
			dynamicBox.space=world;
			addEventListener(Event.ENTER_FRAME, update);
		}
		private function update(e:Event):void {
			debug.clear();
			world.step(1/30,10,10);
			debug.draw(world);
			debug.flush();
		}
	}
}

and this is the result

Now, let’s see the differences:

World creation

Box2D: everything is managed by a b2World object, which wants the gravity in the constructor.

private var world:b2World=new b2World(new b2Vec2(0,10),true);

Nape: the world is a Space object, which wants the gravity in the constructor:

private var world:Space=new Space(new Vec2(0,500));

Vec2 is basically the same as b2Vec2. Also notice gravity is defined using different scales, I personally prefer Box2D approach as it’s intended as real world gravity.

Debug Draw

Box2D: debug draw in Box2D allows great customization, including what to display (shapes, joints, and so on), scale and fill alpha, but you’ll have to write some lines of code:

var debugSprite:Sprite = new Sprite();
addChild(debugSprite);
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
debugDraw.SetFillAlpha(0.5);
world.SetDebugDraw(debugDraw);

Nape: debug draw in Nape is easier to setup but it does not allow customization. Just declare a variable defining the viewport and the main color:

private var debug:ShapeDebug=new ShapeDebug(640,480,0x00ff00);

and then you are ready to add debug draw to Display List:

addChild(debug.display);

I’m personally finding Box2D debug draw more elegant, thanks to filled shapes.

Adding a simple box

Box2D: even adding a box can be quite a task for beginners, you have to create a body definition, then shape, then a fixture to attach the shape to the body.

var bodyDef:b2BodyDef=new b2BodyDef;
bodyDef.position.Set(320/worldScale,460/worldScale);
var polygonShape:b2PolygonShape=new b2PolygonShape();
polygonShape.SetAsBox(320/worldScale,20/worldScale);
var fixtureDef:b2FixtureDef=new b2FixtureDef();
fixtureDef.shape=polygonShape;
var staticFloor:b2Body=world.CreateBody(bodyDef);
staticFloor.CreateFixture(fixtureDef);

Not the most intuitive thing, but it allows a lot of customization. Also, Box2D works in meters and you will have to convert it to pixels.

Nape: basic shapes are really easy to crate with Nape you just need to define a body and a shapes.

var staticFloor:Body=new Body(BodyType.STATIC,new Vec2(320,460));
staticFloor.shapes.add(new Polygon(Polygon.box(640,40)));
staticFloor.space=world;

And as you can see it works with pixels.

World update

Updating the world is a critical process as it renders the world in our Flash movie

Box2D: in three lines we make the simulation run and draw:

world.Step(1/30,10,10);
world.ClearForces();
world.DrawDebugData();

The core lies in Step method which runs in this case the simulation at 1/30 seconds at time.

Nape: it’s basically the same, step method handles the simulation.

debug.clear();
world.step(1/30,10,10);
debug.draw(world);
debug.flush();

And that’s all at the moment. As you can see, there isn’t that much difference between these two engines when dealing with basic projects. During next days I’ll show you something more complicated.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.