package com.actionsnippet.qbox{ import flash.utils.*; import flash.display.* import flash.events.*; import com.actionsnippet.qbox.objects.*; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.Joints.*; /** In order to make use of this library you'll need to instantiate a QuickBox2D instance. What does the QuickBox2D class do? It instantiates the main classes that Box2D needs to run (b2World and b2AABB). It manages the Box2D simulation via start() and stop() methods. It contains methods for creating rigid bodies and joints - such as addCircle(), addBox() and addPoly() It contains a few additional methods for debugging and mouse interaction. @author Zevan Rosser @version alpha 108 */ public class QuickBox2D extends EventDispatcher{ /** The Box2D b2AABB instance. */ public var worldAABB:b2AABB; private var _gravity:b2Vec2; /** The world gravity vector. This can be changed during runtime. */ public function set gravity(v:b2Vec2):void{ _gravity = v; w.SetGravity(_gravity); } public function get gravity():b2Vec2{ return _gravity; } /** The Box2D b2World instance. */ public var w:b2World; /** The Box2D iterations. */ public var iterations:int = 20; /** The Box2D time step. */ public var timeStep:Number = 1 / 60.0; /** The MovieClip containing the Box2D world. */ public var main:MovieClip; /** Toggles FRIM (frame rate independent movement). By default this is set to true. Turning it off will cause the stage.frameRate (the frame rate of the swf) to effect the speed of the Box2D simulation.*/ public var frim:Boolean; internal var debug:Boolean; private var _simpleRender:Boolean = true; private var _renderJoints:Boolean = true; private var _defaults:Object = new Object(); private var _mouseJoint:b2MouseJoint; private var _mousePVec:b2Vec2 = new b2Vec2(); private var _quickObjects:Dictionary = new Dictionary(true); /** * Creates a new QuickBox2D instance. * * @param main The MovieClip to render the Box2D world into. * @param params An Object containing settings for QuickBox2D and the Box2D world. See below for details. * * All params Object Properties:
debug: : false - If set to true, QuickBox2D will use the Box2D debug renderer to draw the world. gravityX : 0 - The x component of the gravity vector for the Box2D world. gravityY: 20 - The y component of the gravity vector for the Box2D world. timeStep: 1 / 60 - The Box2D time step. iterations: 20 - The Box2D iterations. frim: true - Toggles FRIM (frame rate independent movement). bounds: [-100, -100, 100, 100] - Defines the bounding box for the Box2D world. renderJoints: true - Toggles the rendering of joints for the simple renderer. simpleRender: true - Toggles the QuickBox2D simple renderer. Set this to false if you don’t want to utilize any of the QuickBox2D rigid body skinning.
*/ public function QuickBox2D(main:MovieClip, params:Object=null){ this.main = main; init(params); } private function init(p:Object=null):void{ var defaults:Object = {gravityX:0.0, gravityY:20.0, iterations: iterations, timeStep: timeStep, bounds: [-100, -100, 100, 100], debug:false, simpleRender:_simpleRender, renderJoints:true, frim:true}; if (p == null){ p = new Object(); } for (var key:String in defaults){ if (p[key] == null){ p[key] = defaults[key]; } } frim = p.frim; _simpleRender = p.simpleRender; _renderJoints = p.renderJoints; iterations = p.iterations; timeStep = p.timeStep debug = p.debug; var bg:Sprite = new Sprite(); main.addChild(bg); if (debug){ bg.graphics.beginFill(0x333333); bg.graphics.drawRect(0,0, main.stage.stageWidth, main.stage.stageHeight); } worldAABB = new b2AABB(); worldAABB.lowerBound.Set(p.bounds[0], p.bounds[1]) worldAABB.upperBound.Set(p.bounds[2], p.bounds[3]); _gravity = new b2Vec2(p.gravityX, p.gravityY); w=new b2World(worldAABB, _gravity, true); if (debug){ var dbgDraw:b2DebugDraw = new b2DebugDraw(); var dbgSprite:Sprite = new Sprite(); main.addChild(dbgSprite); dbgDraw.m_sprite = dbgSprite; dbgDraw.m_drawScale = 30.0; dbgDraw.m_fillAlpha = .5; dbgDraw.m_alpha = .5; dbgDraw.m_lineThickness = 1.0; dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;//0xFFFFFFFF; w.SetDebugDraw(dbgDraw); } } /** Draws a grid for testing/debugging purposes only. @param size The width and height of the grid squares. The default size is 30 because with QuickBox2D default settings 30 pixels = 1 meter. @param lineColor The line color. @param lineAlpha The line alpha. */ public function grid(size:int=30, lineColor:uint=0xFFFF00, lineAlpha:Number=1):void{ //main.graphics.clear(); var g:Sprite = new Sprite(); main.addChild(g); g.graphics.lineStyle(0, lineColor, lineAlpha); for (var i:int = 0; ienterframe event. */ private var _prevTime:Number = 0; private var _currTime:Number; private var _elapsedTime:Number; private var _accumulator:Number = 0; public var totalTimeSteps:Number = 0; protected function onRender(evt:Event):void{ var i:int, leng:int, ts:TimeStepCallback if (frim == true){ //from here https://developer.playfirst.com/node/860 _currTime = getTimer(); _elapsedTime = (_currTime - _prevTime) * 0.001; _prevTime = _currTime; if (_elapsedTime > 0.25){ _elapsedTime = 0.25; } _accumulator += _elapsedTime; while(_accumulator >= timeStep){ w.Step(timeStep, iterations); _accumulator -= timeStep; totalTimeSteps++; leng = timeStepCallbacks.length; for (i = 0; iSee below for a full list of valid properties.
Nearly all of these properties come straight from the Box2D b2ShapeDef and b2BodyDef (and subclasses). QuickBox2D puts them all in one place for easy rigid body instantiation. Common Properties: x: 3.0 - The x location in meters. y: 3.0 - The y location in meters. points: null - An array describing the contour of the polygon. QuickBox2D will triangulate the verts array automatically if this property is set. verts: [[-.5, -1, 1, -1, 1, 1, -1, 1]] - A two dimensional array of vertices describing the polygon. angle: 0.0 - The angle in radians. draggable: true - Enable or disable dragging if the {@link #mouseDrag()} method has been called. Rendering Properties: (These are used with QuickBox2D's simpleRenderer) skin: null - Set this to the name of a linkage class from your library if you'd like to use a graphics created in flash for your rigid body skin. The following properties will not do anything if you have set the skin property or if you have set simpleRender to false. lineColor: 0x000000 - Line color. lineAlpha: 1.0 - Line alpha. lineThickness: 0.0 - Line thickness. fillColor: 0xCCCCCC - Fill color. fillAlpha: 1.0 - Fill alpha. Additional Properties: density: 1.0 - The density in kg/m^2. friction: 0.5 - The friction coefficient. Normally ranges from 0 - 1. restitution: 0.2 - The restitution of the rigid body. This is like elasticity or bounciness. Normally ranges from 0 - 1. linearDamping: 0.0 - Linear damping. angularDamping: 0.0 - Angular damping. isBullet: false - uses CCD (continuous collision detection) to prevent fast moving object from moving through other objects. fixedRotation: false - If set to true the rigid body will not rotate. allowSleep: true - If set to false the rigid body will never sleep. isSleeping: false - If set to true the rigid body will start off sleeping. This can be useful for creating breakable objects. mass: - The mass of the rigid body. This is usually set automatically - setting it on polygons may cause unexpected results. maskBits: - 0xFFFF - Collision mask bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 categoryBits: 1 - Category bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 groupIndex: 0 - Group index.See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845
@return {@link com.actionsnippet.qbox.QuickObject} */ public function addPoly(params:Object):QuickObject{ return create("poly", params); } /** Adds a box to the world. @param params An Object containing properties that describe all aspects of the box. See below for a full list of valid properties.
Nearly all of these properties come straight from the Box2D b2ShapeDef and b2BodyDef (and subclasses). QuickBox2D puts them all in one place for easy rigid body instantiation. Common Properties: x: 3.0 - The x location in meters. y: 3.0 - The y location in meters. width: 1.0 - The width in meters. height: 1.0 - The height in meters. angle: 0.0 - The angle in radians. draggable: true - Enable or disable dragging if the {@link #mouseDrag()} method has been called. Rendering Properties: (These are used with QuickBox2D's simpleRenderer) skin: null - Set this to the name of a linkage class from your library if you'd like to use a graphics created in flash for your rigid body skin. The following properties will not do anything if you have set the skin property or if you have set simpleRender to false. lineColor: 0x000000 - Line color. lineAlpha: 1.0 - Line alpha. lineThickness: 0.0 - Line thickness. fillColor: 0xCCCCCC - Fill color. fillAlpha: 1.0 - Fill alpha. Additional Properties: density: 1.0 - The density in kg/m^2. friction: 0.5 - The friction coefficient. Normally ranges from 0 - 1. restitution: 0.2 - The restitution of the rigid body. This is like elasticity or bounciness. Normally ranges from 0 - 1. linearDamping: 0.0 - Linear damping. angularDamping: 0.0 - Angular damping. isBullet: false - uses CCD (continuous collision detection) to prevent fast moving object from moving through other objects. fixedRotation: false - If set to true the rigid body will not rotate. allowSleep: true - If set to false the rigid body will never sleep. isSleeping: false - If set to true the rigid body will start off sleeping. This can be useful for creating breakable objects. mass: - The mass of the rigid body. This is usually set automatically - setting it on polygons may cause unexpected results. maskBits: - 0xFFFF - Collision mask bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 categoryBits: 1 - Category bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 groupIndex: 0 - Group index.See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845
@return {@link com.actionsnippet.qbox.QuickObject} */ public function addBox(params:Object):QuickObject{ return create("box", params); } /** Adds a circle to the world. @param params An Object containing properties that describe all aspects of the circle. See below for a full list of valid properties.
Nearly all of these properties come straight from the Box2D b2ShapeDef and b2BodyDef (and subclasses). QuickBox2D puts them all in one place for easy rigid body instantiation. Common Properties: x: 3.0 - The x location in meters. y: 3.0 - The x location in meters. radius: 1.0 - The radius in meters. angle: 0.0 - The angle in radians. draggable: true - Enable or disable dragging if the {@link #mouseDrag()} method has been called. Rendering Properties: (These are used with QuickBox2D's simpleRenderer) skin: null - Set this to the name of a linkage class from your library if you'd like to use a graphics created in flash for your rigid body skin. The following properties will not do anything if you have set the skin property or if you have set simpleRender to false. lineColor: 0x000000 - Line color. lineAlpha: 1.0 - Line alpha. lineThickness: 0.0 - Line thickness. fillColor: 0xCCCCCC - Fill color. fillAlpha: 1.0 - Fill alpha. Additional Properties: density: 1.0 - The density in kg/m^2. friction: 0.5 - The friction coefficient. Normally ranges from 0 - 1. restitution: 0.2 - The restitution of the rigid body. This is like elasticity or bounciness. Normally ranges from 0 - 1. linearDamping: 0.0 - Linear damping. angularDamping: 0.0 - Angular damping. isBullet: false - uses CCD (continuous collision detection) to prevent fast moving object from moving through other objects. fixedRotation: false - If set to true the rigid body will not rotate. allowSleep: true - If set to false the rigid body will never sleep. isSleeping: false - If set to true the rigid body will start off sleeping. This can be useful for creating breakable objects. mass: - The mass of the rigid body. This is usually set automatically - setting it on polygons may cause unexpected results. maskBits: - 0xFFFF - Collision mask bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 categoryBits: 1 - Category bits. See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845 groupIndex: 0 - Group index.See Box2D manual for a description of this http://www.box2d.org/manual.html#d0e845
@return {@link com.actionsnippet.qbox.QuickObject} */ public function addCircle(params:Object):QuickObject { return create("circle", params); } /** Adds a joint to the world. @param params An Object containing properties that describe all aspects of the joint. See below for a full list of valid properties
Common Properties: a: null - A {@link com.actionsnippet.qbox.QuickObject#body} property to attach one end of the joint to. b: null - A {@link com.actionsnippet.qbox.QuickObject#body} property to attach the other end of the joint to. if the below propertyes (x1, y1, x2, y2) are not set they will be calculated based on the center points of a and b. x1: null - The x location for the end of the joint anchored to body a. y1: null - The y location for the end of the joint anchored to body a. x2: null - The x location for the end of the joint anchored to body b. y2: null - The y location for the end of the joint anchored to body b. Rendering Properties: (These are used with QuickBox2D's simpleRenderer) skin: null - Set this to the name of a linkage class from your library if you'd like to use a graphics created in flash for your joint. This class must be dynamic. If you are trying to use a Sprite here, just use a MovieClip instead. Currently DisplayObject/Class skins only work for b2DistanceJoints. The following properties will not do anything if you have set the skin property or if you have set simpleRender to false. lineColor: 0x000000 - Line color. lineAlpha: 1.0 - Line alpha. lineThickness: 0.0 - Line thickness. Properties for all joints: type: - The type of joint, either distance, prismatic, revolute, pulley or gear. collideConnected: true - If set to false, the two bodies attached to this joint will not collide. Properties for distance joints: frequencyHz: 0 - The response speed. Using numbers above zero will cause the joint to act more like a rubber band. dampingRatio: 0 - The damping ratio. 0 = no damping, 1 = critical damping. length: 0 - The equilibrium length between the anchor points. If not set, this will automatically be calculated based on the distance between (x1, y1) and (x2, y2). Properties for some joints (revolute, prismatic) enableLimit false - Enable joint limits (constraints on angle and translation). enableMotor: false - Toggle joint motor. motorSpeed: 0 - Set motor speed referenceAngle 0 - p.referenceAngle; Properties for revolute joints: upperAngle: 0 - p.upperAngle; lowerAngle: 0 - p.lowerAngle; maxMotorTorque: 0 - p.maxMotorTorque; Properties for prismatic joints: axis: null - Axis b2Vec2, must be set. anchor: null - Anchor b2Vec2, must be set. upperTranslation: 0 - Upper limit b2Vec2 in local coordinates. lowerTranslation: 0 - Upper limit b2Vec2 in local coordinates. maxMotorForce: 0 - Max force for motor. Properties for pulley joints: groundAnchor1: (0,a.x) - Ground anchor for body a b2Vec2; groundAnchor2: (0,b.x) - Ground anchor for body b b2Vec2; anchor1: (a.x, b.x) - Anchor for body a; anchor2: (a.x, b.x) - Anchor for body b; ratio: 1 - This causes one side of the pulley to extend faster than the other when not set to 1. Properties for gear joints: joint1: null - Either revolute or prismatic joint tied to the groundBody and a, must be set. joint2: null - Either revolute or prismatic joint tied to the groundBody and b, must be set. ratio: 1 - This causes one of the gears to move more/less than the other when not set to 1. @return {@link com.actionsnippet.qbox.QuickObject} */ public function addJoint(params:Object):QuickObject { return create("joint", params); } /** Creates a group out of existing QuickObject instances. This is usually reffered to as a compound shape. @param params An Object containing properties that describe all aspects of the group. See below for a full list of valid properties.
Nearly all of these properties come straight from the Box2D b2ShapeDef and b2BodyDef (and subclasses). QuickBox2D puts them all in one place for easy rigid body instantiation. Common Properties: x: 3.0 - The x location in meters. y: 3.0 - The y location in meters. objects: null - An array of {@link com.actionsnippet.qbox.QuickObject} instances to group together. angle: 0.0 - The angle in radians. draggable: true - Enable or disable dragging if the {@link #mouseDrag()} method has been called. Rendering Properties: (These are used with QuickBox2D's simpleRenderer) skin: null - Set this to the name of a linkage class from your library if you'd like to use a graphics created in flash for your rigid body skin. This can also be set to a DisplayObject instance on the stage - currently boxes and circles x,y and angle values are reset based on the DisplayObject instance's x,y and rotation properties. Additional Properties: linearDamping: 0.0 - Linear damping. angularDamping: 0.0 - Angular damping. isBullet: false - uses CCD (continuous collision detection) to prevent fast moving object from moving through other objects. fixedRotation: false - If set to true the rigid body will not rotate. allowSleep: true - If set to false the rigid body will never sleep. isSleeping: false - If set to true the rigid body will start off sleeping. This can be useful for creating breakable objects.
@return {@link com.actionsnippet.qbox.QuickObject} */ public function addGroup(params:Object):QuickObject { return create("group", params); } /** Can create any type of QuickObject. @param type The type of QuickObject to create, either "box", "circle", "poly" or "joint". For a list of possible params see any of the below methods: {@link #addBox()} {@link #addCircle()} {@link #addPoly()} {@link #addJoint()} @return {@link com.actionsnippet.qbox.QuickObject} */ public function create(type:String, params:Object):QuickObject{ var quickObject:QuickObject; if (type == "box"){ quickObject = new BoxObject(this, params); _quickObjects[quickObject.body] = quickObject; }else if (type == "circle"){ quickObject = new CircleObject(this, params); _quickObjects[quickObject.body] = quickObject; }else if (type == "poly"){ quickObject = new PolyObject(this, params); _quickObjects[quickObject.body] = quickObject; }else if (type == "joint"){ quickObject = new JointObject(this, params); _quickObjects[quickObject.joint] = quickObject; }else if (type == "group"){ quickObject = new GroupObject(this, params); _quickObjects[quickObject.body] = quickObject; }else{ throw new Error("QuickBox2D: Sorry, there is no QuickObject subclass for " + type + " types."); } return quickObject; } /** Sets some default params for all QuickObjects. This can be useful for setting default rendering styles - but can contain any default properties for any type of object - box, circle, poly or joint. @param params For a full list of possible params see any of the below methods: {@link #addBox()} {@link #addCircle()} {@link #addPoly()} {@link #addJoint()} */ public function setDefault(params:Object=null):void{ _defaults = params; } /* Traces the properties of the QuickBox2D internal default Object. public function traceDefault():void{ trace("DEFAULTS:"); for (var k:String in _defaults){ if (k == "lineColor" || k == "fillColor"){ trace("- ",k, " = ", "0x"+_defaults[k].toString(16)); }else{ trace("- ",k, " = ", _defaults[k], " = "); } } }*/ /** @exclude */ internal function defaultParams(params:Object):void{ if (params==null) { params = new Object(); } for (var key:String in _defaults) { if (params[key]==null) { params[key]=_defaults[key]; } } } // // -- mouse drag stuff (from the testbed code) // public function updateMouse():void{ if (_mouseJoint) { var p2:b2Vec2=new b2Vec2(main.mouseX/30 ,main.mouseY/30); _mouseJoint.SetTarget(p2); } } public function createMouse(evt:MouseEvent):void { var body:b2Body=GetBodyAtMouse(); var _mouseJointDef:b2MouseJointDef if (_quickObjects[body]){ if (body && _quickObjects[body].params.draggable == true) { _mouseJointDef=new b2MouseJointDef(); _mouseJointDef.body1=w.GetGroundBody(); _mouseJointDef.body2=body; _mouseJointDef.target.Set(main.mouseX/30, main.mouseY/30); _mouseJointDef.maxForce=3000; _mouseJointDef.timeStep=timeStep; _mouseJoint=w.CreateJoint(_mouseJointDef) as b2MouseJoint; } }else{ if (body){ _mouseJointDef=new b2MouseJointDef(); _mouseJointDef.body1=w.GetGroundBody(); _mouseJointDef.body2=body; _mouseJointDef.target.Set(main.mouseX/30, main.mouseY/30); _mouseJointDef.maxForce=3000; _mouseJointDef.timeStep=timeStep; _mouseJoint=w.CreateJoint(_mouseJointDef) as b2MouseJoint; } } } private function destroyMouse(evt:MouseEvent):void { if (_mouseJoint) { w.DestroyJoint(_mouseJoint); _mouseJoint=null; } } private function GetBodyAtMouse(includeStatic:Boolean=false):b2Body { var mouseXWorldPhys:Number = (main.mouseX)/30; var mouseYWorldPhys:Number = (main.mouseY)/30; _mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001); aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001); var k_maxCount:int=10; var shapes:Array = new Array(); var count:int=w.Query(aabb,shapes,k_maxCount); var body:b2Body=null; for (var i:int = 0; i < count; ++i) { if (shapes[i].GetBody().IsStatic()==false||includeStatic) { var tShape:b2Shape=shapes[i] as b2Shape; var inside:Boolean=tShape.TestPoint(tShape.GetBody().GetXForm(),_mousePVec); if (inside) { body=tShape.GetBody(); break; } } } return body; } } } class TimeStepCallback{ public var time:int; public var callback:Function; public var args:Array; public function TimeStepCallback(t:int, f:Function, ar:Array){ time = t ; callback = f; args = ar; } }