Box2D Shortcuts (Round 1)

Since leaving Hunt & Gather, I’ve been (besides relishing the peace and quiet a bit) playing around with some of those Flash libraries I hadn’t had time for. Most tantalizing of which is the Box2D library. I’d attempted to use it for this auto layout class for LDa Architects, but because of time constraints ended up settling for APE which as you can see is a bit out of date at this point. Anyway APE is fine if the number of bodies is small and you only need very basic simulation capabilities (boxes don’t rotate unless they are attached to 2 or more wheels for instance…), but once you wanna do more advanced things, like robots or buoyancy you’ll need a faster more complete engine.

Box2D seems to be the fastest and most current option out there, but it’s got kind of a funky API due in part to being a fairly direct port from C++. The complicated setup is in fact what had kept me from using it for so long, but some better documentation and turorial files available on the Box2D Wiki is making getting started easier. And to make things even simpler to play with, I’m creating a series of wrapper classes that reduce the amount of code needed to get things started.

World.world

?View Code ACTIONSCRIPT
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
package com.paperclipped.physics
{
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2World;
 
	import flash.display.Sprite;
 
	/**
	 * This is a container class to make the creation of Box2D World simpler.
	 * Box2D r47 or greater required.
	 * (c) 2009 Collin Reisdorf MIT License
	 * 
	 * @author Collin Reisodrf
	 */	
	public class World
	{
//-----------------------------------------Variables-----------------------------------------//
		private var _scale:Number;
		private var _world:b2World;
//-------------------------------------------------------------------------------------------//
 
//------------------------------------------Getters------------------------------------------//
		/**
		 * @return Scale set by the user when the world is constructed.
		 */				
		public function get scale():Number		{ return _scale;	}
		/**
		 * @return The world object made by the constructor.
		 */		
		public function get world():b2World		{ return _world;	}
//-------------------------------------------------------------------------------------------//
 
//----------------------------------------Constructor----------------------------------------//		
		public function World(width:uint, height:uint, debugSprite:Sprite=null, showCenterOfMass:Boolean=false, gravity:b2Vec2=null, scale:Number=30, padding:uint=1000, doSleep:Boolean=true)
		{
			var worldAABB:b2AABB = new b2AABB();
				worldAABB.lowerBound.Set(-padding, -padding);
				worldAABB.upperBound.Set(width+padding, width+padding);
 
			gravity = (gravity)? gravity:new b2Vec2(0, 10.0);
			_world = new b2World(worldAABB, gravity, doSleep);
 
			if(debugSprite)
			{
				var	debugDraw:b2DebugDraw = new b2DebugDraw();
					debugDraw.SetSprite(debugSprite);
					debugDraw.SetDrawScale(scale);
					debugDraw.SetFillAlpha(0.3);
					debugDraw.SetLineThickness(1.0);
					debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit | uint((showCenterOfMass)? b2DebugDraw.e_centerOfMassBit:0));
				_world.SetDebugDraw(debugDraw);
			}
		}
//-------------------------------------------------------------------------------------------//
 
//--------------------------------------Private Methods--------------------------------------//
//-------------------------------------------------------------------------------------------//
 
//--------------------------------------Public  Methods--------------------------------------//
//-------------------------------------------------------------------------------------------//
	}
}

Chain

?View Code ACTIONSCRIPT
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
package com.paperclipped.physics
{
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.Joints.b2Joint;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2World;
 
	/**
	 * This is a container class to make the creation of a chain simpler
	 * Box2D r47 or greater required.
	 * (c) 2009 Collin Reisdorf MIT License
	 * 
	 * @author Collin Reisodrf
	 */	
	public class Chain
	{
//-----------------------------------------Variables-----------------------------------------//
		public static const HORIZONTAL:String = 'h';
		public static const VERTICAL:String = 'v'; // not supported yet
 
		private var _bodies:Array;
		private var _joints:Array;
//		private var _parent:
		private var _world:b2World;
//-------------------------------------------------------------------------------------------//
 
//------------------------------------------Getters------------------------------------------//
		public function get bodies():Array 	{ return _bodies;								}
		public function get end():b2Body 	{ return _bodies[_bodies.length-1] as b2Body;	}
		public function get joints():Array	{ return _joints;								}
		public function get start():b2Body	{ return _bodies[0] as b2Body;					}
//-------------------------------------------------------------------------------------------//
 
//------------------------------------------Setters------------------------------------------//
//-------------------------------------------------------------------------------------------//
 
//----------------------------------------Constructor----------------------------------------//
		public function Chain(world:b2World, numLinks:uint=3, anchorX:int=0, anchorY:int=0, direction:String="h", swingLimit:uint=0, /*parent=null,*/ scale:uint=30)
		{
			_world = world;
			_bodies = new Array();
			_joints = new Array();
//			_parent = parent; // not sure what/how to attach this to yet...
 
			var ground:b2Body = world.GetGroundBody();
			var i:int;
			var anchor:b2Vec2 = new b2Vec2();
			var body:b2Body;
			var joint:b2Joint;
 
			var sd:b2PolygonDef = new b2PolygonDef();
			sd.SetAsBox(24 / scale, 5 / scale);
			sd.density = 100.0;
			sd.friction = 0.8;
 
			var bd:b2BodyDef = new b2BodyDef();
 
			var jd:b2RevoluteJointDef = new b2RevoluteJointDef();
			if(swingLimit > 0)
			{
				jd.lowerAngle = -swingLimit / (180/Math.PI);
				jd.upperAngle = swingLimit / (180/Math.PI);
				jd.enableLimit = true;
			}else
			{
				jd.enableLimit = false;
			}
 
			var prevBody:b2Body = ground;
			for (i = 0; i < 3; ++i)
			{
//				if(i == 0)
//				{
//				trace("enabled motor damnit");
//					jd.enableMotor = true;
//					jd.motorSpeed = 1;
//					jd.maxMotorTorque = 100;
//				}else
//				{
//					jd.enableMotor = false;
//
//				}
 
				bd.position.Set((anchorX + 22 + 44 * i) / scale, anchorY / scale);
				body = world.CreateBody(bd);
				body.CreateShape(sd);
				body.SetMassFromShapes();
 
				anchor.Set((anchorX + 44 * i) / scale, anchorY / scale);
				jd.Initialize(prevBody, body, anchor);
				joint = world.CreateJoint(jd);
 
				prevBody = body;
				_bodies.push(body);
				_joints.push(joint);
			}
		}
//-------------------------------------------------------------------------------------------//
 
//--------------------------------------Private Methods--------------------------------------//
//-------------------------------------------------------------------------------------------//
 
//--------------------------------------Public  Methods--------------------------------------//
//-------------------------------------------------------------------------------------------//
	}
}

Keep an eye out for more, I’m working on robot leg linkages next. And also trying to get a new job 😉