Talking about Way of an Idea game, Actionscript 3, Box2D, Flash and Game development.
Three years ago I published a three steps tutorial about the creation of a Flash game like Way of an Idea.
Following the same concepts I already explained in steps 1, 2 and 3, here is the updated Box2D 2.1a version running together with the Nape version of the game.
This is what we have:
Draw the track with your mouse, press SPACE to play/pause the simulation and delete the chalk pressing 0 (zero) and moving the mouse over the chalk.
You should be able to recognize both debug draws, Box2D and Nape.
This is the source code, with comments to show which part of the code belongs to Box2D and which to Nape:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
// BOX2D
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
// NAPE
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.BodyList;
import nape.phys.BodyType;
import nape.shape.Polygon;
import nape.shape.Circle;
import nape.space.Space;
import nape.util.ShapeDebug;
public class Main extends Sprite {
private var drawing:Boolean=false;
private var canvas:Sprite = new Sprite();
private var pointsArray:Array;
private var pixelDist:int=20;
private var savedX:int;
private var savedY:int;
private var timeStep:Number=0;
// BOX2D
private var world:b2World=new b2World(new b2Vec2(0,10),true);
private var worldScale:Number=30;
private var debugSprite:Sprite=new Sprite();
// NAPE
private var napeWorld:Space=new Space(new Vec2(0,500));
private var debug:ShapeDebug=new ShapeDebug(640,480,0x00ff00);
private var napeDebugSprite:Sprite=new Sprite();
public function Main():void {
addChild(canvas);
canvas.graphics.lineStyle(5);
stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed);
stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoved);
stage.addEventListener(MouseEvent.MOUSE_UP,mouseReleased);
addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed);
// BOX2D
addChild(debugSprite);
debugDraw();
// NAPE
addChild(napeDebugSprite);
napeDebugSprite.addChild(debug.display);
// BOX2D;
var bodyDef:b2BodyDef= new b2BodyDef();
bodyDef.type=b2Body.b2_dynamicBody;
bodyDef.position.Set(20/worldScale,20/worldScale);
var circleShape:b2CircleShape = new b2CircleShape(15/worldScale);
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.density=1;
fixtureDef.friction=0.5;
fixtureDef.restitution=0.5;
fixtureDef.shape=circleShape;
var body:b2Body=world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
// NAPE
var napeBody:Body=new Body(BodyType.DYNAMIC,new Vec2(20,20));
var circle:Circle=new Circle(15);
circle.material.elasticity=0.5;
circle.material.density=1;
circle.material.staticFriction=0.5;
napeBody.shapes.add(circle);
napeBody.space=napeWorld;
}
private function mousePressed(e:MouseEvent):void {
drawing=true;
canvas.graphics.moveTo(mouseX,mouseY);
pointsArray=new Array();
savedX=mouseX;
savedY=mouseY;
pointsArray.push(savedX);
pointsArray.push(savedY);
}
private function mouseMoved(e:MouseEvent):void {
if (drawing) {
var distX:int=mouseX-savedX;
var distY:int=mouseY-savedY;
if (distX*distX+distY*distY>pixelDist*pixelDist) {
canvas.graphics.lineTo(mouseX,mouseY);
savedX=mouseX;
savedY=mouseY;
pointsArray.push(savedX);
pointsArray.push(savedY);
}
}
}
// BOX2D
private function debugDraw():void {
var debugDraw:b2DebugDraw=new b2DebugDraw();
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);
debugDraw.SetFillAlpha(0.5);
world.SetDebugDraw(debugDraw);
}
private function mouseReleased(e:MouseEvent):void {
drawing=false;
var sx:int;
var ex:int;
var sy:int;
var ey:int;
var distX:int;
var distY:int;
var dist:Number;
var angle:Number;
var segments:int=pointsArray.length/2-1;
for (var i:int=0; i0) {
for (var i:int = 0; i < bodies.length; i++) {
var body:Body=bodies.at(i);
if (body.type==BodyType.STATIC) {
napeWorld.bodies.remove(body);
}
}
}
}
}
private function addPath(pX:Number,pY:Number,w:Number,h:Number,angle:Number):void {
// BOX2D
var bodyDef:b2BodyDef= new b2BodyDef();
var polygonShape:b2PolygonShape = new b2PolygonShape();
polygonShape.SetAsOrientedBox(w/2/worldScale, h/2/worldScale, new b2Vec2(pX/worldScale,pY/worldScale),angle);
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.density=1;
fixtureDef.friction=0.5;
fixtureDef.restitution=0.5;
fixtureDef.shape=polygonShape;
var body:b2Body=world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
// NAPE
var napeBody:Body=new Body(BodyType.STATIC,new Vec2(pX,pY));
var polygon:Polygon=new Polygon(Polygon.box(w,h));
polygon.rotate(angle);
polygon.material.elasticity=0.5;
polygon.material.density=1;
polygon.material.staticFriction=0.5;
napeBody.shapes.add(polygon);
napeBody.space=napeWorld;
}
// BOX2D
private function queryCallback(fixture:b2Fixture):Boolean {
var touchedBody:b2Body=fixture.GetBody();
for (var f:b2Fixture=touchedBody.GetFixtureList(); f; f=f.GetNext()) {
if (touchedBody.GetType()==b2Body.b2_staticBody) {
world.DestroyBody(touchedBody);
}
}
return false;
}
private function update(e:Event):void {
if (timeStep) {
// BOX2D
world.Step(1/30,10,10);
world.ClearForces();
// NAPE
napeWorld.step(1/30,10,10);
}
// BOX2D
world.DrawDebugData();
// NAPE
debug.clear();
debug.draw(napeWorld);
debug.flush();
}
}
}
It would be interesting to know if you ever used Nape in some of your projects, meanwhile download the full source code of the prototype.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.