-
[SWF(backgroundColor = 0x333333)]
-
-
import com.actionsnippet.qbox.*;
-
-
// setting debug = true, will use the Box2D debug rendering
-
var sim:QuickBox2D=new QuickBox2D(this, {debug:false, gravityY:10});
-
-
// creates static boxes on all sides of the screen
-
sim.createStageWalls({lineAlpha:0, fillColor:0xFF9900});
-
-
// add 25 boxes
-
for (var i:int = 0; i<25; i++){
-
var xp:Number = 3 + (i % 5);
-
var yp:Number = 1 + int( i / 5);
-
sim.addBox({x:xp, y:yp, width:1, height:1, fillColor: i * 10 <<16, lineAlpha:0, angularDamping:5});
-
}
-
-
sim.addBox({x:7, y:10, width:3, height:.2, angle:-.3, density:0,lineAlpha:0, fillColor:0xFF9900});
-
-
sim.addCircle({x:3, y:14, radius:2, fillColor:0xCC0000, lineColor:0x333333});
-
-
sim.addPoly({x:13, y:5, verts:[[1,0,2,2,1,1.33],[1,0,1,1.33,0,2]], angle: .4, density:1});
-
-
// begins the simulation
-
sim.start();
-
-
// all non-static objects can be dragged
-
sim.mouseDrag();
I've been messing with Box2D for the past few weeks - I decided to create a library (QuickBox2D) for quick prototyping. This snippet makes use of this library, so in order to run it you'll need to download the zip included at the end of this post...
If you don't already know, Box2D is a great physics library created by Erin Catto. It was ported to AS3 by Matthew Bush and John Nesky. You can download the AS3 version of the library here.
Today's snippet creates this swf (click any image to view demo):
QuickBox2D
QuickBox2D simplifies Box2D instantiation and makes it easy to skin rigid bodies with Library assets... normally you need to do something like this to create a box in Box2D:
-
var bodyDef:b2BodyDef = new b2BodyDef();
-
bodyDef.position.Set(3, 3);
-
var boxDef:b2PolygonDef = new b2PolygonDef();
-
boxDef.SetAsBox(1, 1);
-
boxDef.density = 1;
-
var body:b2Body = w.CreateBody(bodyDef);
-
body.CreateShape(boxDef);
-
body.SetMassFromShapes();
and this doesn't include setting up the physics world and the main loop to run the simulation... after writing a good deal of repetitive code I decided to make QuickBox2D. After writing lots of QuickBox2D style instantiation I decided to create an editor so that I could just draw circles, boxes, polygons and joints and then test and save them in real time (will be posting this editor in the near future). The next few posts will be about this mini-library and I'll be writing up some real documentation for it... as of now, it doesn't have any...
You can download Box2D here
You can download QuickBox2D here
and you can view some AS3 Box2D demos here
13 Comments
Thanks ! I have something I quickly put together here:
http://yourcall.ribbit.com/
it’s kinda crummy ( my first Box2D project ) but I have a lot of love for the library!
thanks for this…
b
cool! Yeah, Box2D is just plain awesome
Quick Question -
I am trying to add a feature to your framework to move the “simulation boundary” boxes on stage resize firing.
I can think of two options, the better ( in my opinion) being just physically moving them or affecting width | height on them on RESIZE ( them being the stage walls )
How does this affect the Box2D world? It seems to not acknowledge when I move the boundaries … I guess I don’t know enough about it to know if this is breaking the simulation or not.
It was also really hackish for me to crack into the y / x / width / height properties, if you might be able to suggest a better way, im all ears.
*** WARNING THIS IS SUPER HACK CODE, I WAS JUST TRYING TO ACCESS THE PROPERTIES ****
package util {
import com.actionsnippet.qbox.*;
import flash.display.*;
public class DyBox2D extends QuickBox2D {
// Constants:
// Public Properties:
// Private Properties:
// Initialization:
private var ceiling:QuickObject;
private var rightwall:QuickObject;
private var leftwall:QuickObject;
private var floor:QuickObject;
public function DyBox2D(main:MovieClip, param:Object=null)
{
super(main, param);
}
override public function createStageWalls(p:Object=null):void{
var defaults:Object = {lineColor:0×000000, lineAlpha:1, fillColor:0xCCCCCC, fillAlpha:1};
if (p == null){
p = new Object();
}
for (var key:String in defaults){
if (p[key] == null){
p[key] = defaults[key];
}
}
var sw:Number = main.stage.stageWidth / 30;
var sh:Number = main.stage.stageHeight / 30;
floor=addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
leftwall=addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
ceiling=addBox({x:0, y:sh / 2, width:1, height:sh , density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
rightwall=addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0, lineColor: p.lineColor, lineAlpha: p.lineAlpha, fillColor: p.fillColor, fillAlpha: p.fillAllpha});
}
public function moveStageWalls():void
{
var sw:Number = main.stage.stageWidth / 30;
var sh:Number = main.stage.stageHeight / 30;
//ceiling
ceiling.bodyDef.position.y = sh / 2;
ceiling.bodyDef.position.x = 0;
ceiling.bodyDef.userData.width = 1;
ceiling.bodyDef.userData.height = sh;
//leftwall
leftwall.bodyDef.position.y = 0;
leftwall.bodyDef.position.x = sw / 2;
leftwall.bodyDef.userData.width = sw - 1;
leftwall.bodyDef.userData.height = 1;
rightwall.bodyDef.position.y = sh/2;
rightwall.bodyDef.position.x = sw;
rightwall.bodyDef.userData.width = 1;
rightwall.bodyDef.userData.height = sh;
floor.bodyDef.position.y = sh;
floor.bodyDef.position.x = sw / 2;
floor.bodyDef.userData.width = sw - 1;
floor.bodyDef.userData.height = 1;
}
// Public Methods:
// Protected Methods:
}
}
*** AND HERE IS HOW IM CALLING IT ***
private function resizeHandler(event:Event):void {
//trace(”resizeHandler: ” + event);
//trace(”stageWidth: ” + stage.stageWidth + ” stageHeight: ” + stage.stageHeight);
sim.moveStageWalls();
}
sorry if this seems spammy, any advice is much appreciated -
b
This should do the trick. Problem is that as far as I know you can’t resize rigid bodies in Box2D you need to destroy and recreate them:
import com.actionsnippet.qbox.*;
// setting debug:true, will use the Box2D debug rendering
var sim:QuickBox2D = new QuickBox2D(this, {debug:true, gravityY:10});
var box:QuickObject = sim.addBox({x:3, y:3, width:1, height:1});
var resizing:Boolean = false;
var walls:Array = new Array();
stage.align=StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, onResizeStage);
onResizeStage();
function onResizeStage(evt:Event=null):void{
var sw:Number = stage.stageWidth / 30;
var sh:Number = stage.stageHeight / 30;
// you could also stop the simulation sim.stop()
// and only draw the walls once rather than over and over
updateWalls();
// you’ll need to loop through and do this to all bodies
if (box.x > sw){
box.x = sw - .5;
}
if (box.y > sh){
box.y = sh - .5;
}
}
function updateWalls():void{
if (walls[i]){
for (var i:int = 0; i
walls[i].destroy();
}
}
var sw:Number = stage.stageWidth / 30;
var sh:Number = stage.stageHeight / 30;
walls[0] = sim.addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0});
walls[1] = sim.addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0});
walls[2] = sim.addBox({x:0, y:sh / 2, width:1, height:sh , density:.0});
walls[3] = sim.addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0});
}
// begins the simulation
sim.start();
sim.mouseDrag();
Thanks Zevan !
* as a ” further reading ” resource for anyone that happens upon this thread -
http://www.box2d.org/wiki/index.php?title=Manual/AS3
thanks for you help, I used if for a super simple site for a very subtle effect, check out the results:
http://brendanlee.org/
No problem. Nice work. Cool site.
This is the kind of wrapper that you keep doing again and again every time you start a project that uses box2D. Good idea to get done with a reusable one!
Having said that, a very interesting feature this could have would be to be able to turn the simulation in realtime mode.
Usually the problem with box2d is that the same simulation will go faster or slower depending of the cpu power. Making it go realtime would be to keep it synchronised with the timer, doing as many world.steps as needed to catch up on the desired simulation. And interpolate the positions if needed. This will make all simulations run at the same time in any machine, but only the fps will change.
That’s a good idea - I’ll give it a try… I think I recall seeing something about this on the Box2D forums…. (googling)
Yeah, here it is. Thanks for the suggestion
Hi there,
is it possible to scaleUp or scaleDown the created QuickObjects at runtime.
When I start my application all QuickObjects should growUp to a bigger size.
Thanks for any suggestions…
Hey Larsen,
Unfortunately the only way to scale Box2D objects is to destroy them and re-create them…. have a look at some of the comments above and that should help..
This should do the trick. Problem is that as far as I know you can’t resize rigid bodies in Box2D you need to destroy and recreate them:
import com.actionsnippet.qbox.*;
// setting debug:true, will use the Box2D debug rendering
var sim:QuickBox2D = new QuickBox2D(this, {debug:true, gravityY:10});
var box:QuickObject = sim.addBox({x:3, y:3, width:1, height:1});
var resizing:Boolean = false;
var walls:Array = new Array();
stage.align=StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, onResizeStage);
onResizeStage();
function onResizeStage(evt:Event=null):void{
var sw:Number = stage.stageWidth / 30;
var sh:Number = stage.stageHeight / 30;
// you could also stop the simulation sim.stop()
// and only draw the walls once rather than over and over
updateWalls();
// you’ll need to loop through and do this to all bodies
if (box.x > sw){
box.x = sw - .5;
}
if (box.y > sh){
box.y = sh - .5;
}
}
function updateWalls():void{
for (var i:int = 0; i if (walls[i]){
walls[i].destroy();
}
}
var sw:Number = stage.stageWidth / 30;
var sh:Number = stage.stageHeight / 30;
walls[0] = sim.addBox({x:sw / 2, y:sh, width:sw - 1, height:1, density:.0});
walls[1] = sim.addBox({x:sw / 2, y:0, width:sw - 1, height:1, density:.0});
walls[2] = sim.addBox({x:0, y:sh / 2, width:1, height:sh , density:.0});
walls[3] = sim.addBox({x:sw, y:sh / 2, width:1, height:sh , density:.0});
}
// begins the simulation
sim.start();
sim.mouseDrag();
……………………………………………………………………………………………
function updateWalls():void{
for (var i:int = 0; i if (walls[i]){
walls[i].destroy();
}
}
……………………………………………………………………………………………
i canot work it out.is that wrong?
thanks, looking forward to trying it out - appreciate it.
d