{"id":793,"date":"2012-11-02T20:53:11","date_gmt":"2012-11-02T19:53:11","guid":{"rendered":"http:\/\/www.aymericlamboley.fr\/blog\/?p=793"},"modified":"2014-11-01T14:47:42","modified_gmt":"2014-11-01T13:47:42","slug":"create-combination-of-physics-objects-in-citrus-engine","status":"publish","type":"post","link":"http:\/\/www.aymericlamboley.fr\/blog\/create-combination-of-physics-objects-in-citrus-engine\/","title":{"rendered":"Create combination of physics objects in Citrus Engine"},"content":{"rendered":"<p>Some days ago, I said that November will be an awesome month for the <a href=\"http:\/\/citrusengine.com\/\" target=\"_blank\">Citrus Engine<\/a>. So what is coming?<\/p>\n<p>We&#8217;re the 2nd, November is already here and something huge is already happened to the CE : a <a href=\"http:\/\/www.gotoandlearn.com\/play.php?id=171\" target=\"_blank\">tutorial on gotoandlearn<\/a> made by <a href=\"https:\/\/twitter.com\/leebrimelow\" target=\"_blank\">Lee Brimelow<\/a>, an Adobe Game Developer Evangelist! Definitely, an excellent tutorial to get start with the Citrus Engine. There&#8217;ll be other tutorials later, a new website and the forum&#8217;ll move on <a href=\"http:\/\/gamua.com\/starling\/\" target=\"_blank\">Starling <\/a>website. Most of the future game will use Starling so that&#8217;s a good move! We&#8217;re not forgetting the 3D part, don&#8217;t worry \ud83d\ude09<\/p>\n<p>Everything should be ready for the next <a href=\"http:\/\/www.flashrealtime.com\/adobe-game-jam-chicago\/\" target=\"_blank\">Adobe Game Jam<\/a> in Chicago. So that&#8217;s the plan. Now let&#8217;s go for a small tutorial.<\/p>\n<p><!--more--><\/p>\n<p>Someone asked me what is the best way to create a combination of physics objects in CE, like this <a href=\"http:\/\/www.emanueleferonato.com\/2012\/03\/19\/basic-box2d-rope-chain-2-1a-version\/\" target=\"_blank\">one<\/a>. You have to create the Box2D physics bodies and associate arts. Firstly, don&#8217;t forget that view can lies, but never physics. For example, on the CE&#8217;s demo on the actual website the mill&#8217;s arms are one Box2D object (with two bodies) and a single picture.<br \/>\nExample :<br \/>\n<a href=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/blade.png\"><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/blade.png\" alt=\"\" title=\"blade\" width=\"263\" height=\"263\" class=\"alignleft size-full wp-image-794\" srcset=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/blade.png 263w, http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/blade-150x150.png 150w, http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/blade-48x48.png 48w\" sizes=\"(max-width: 263px) 100vw, 263px\" \/><\/a><br \/>\nThe Box2D Alchemy code :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package\r\n{\r\n\timport Box2DAS.Collision.Shapes.b2PolygonShape;\r\n\timport Box2DAS.Common.V2;\r\n\timport Box2DAS.Dynamics.Joints.b2RevoluteJoint;\r\n\timport Box2DAS.Dynamics.Joints.b2RevoluteJointDef;\r\n\timport Box2DAS.Dynamics.b2Body;\r\n\timport Box2DAS.Dynamics.b2BodyDef;\r\n\timport Box2DAS.Dynamics.b2Fixture;\r\n\timport Box2DAS.Dynamics.b2FixtureDef;\r\n\t\r\n\timport com.citrusengine.objects.PhysicsObject;\r\n\t\r\n\tpublic class WindmillArms extends PhysicsObject\r\n\t{\r\n\t\tprivate var _hingeBodyDef:b2BodyDef;\r\n\t\tprivate var _hingeBody:b2Body;\r\n\t\tprivate var _shape2:b2PolygonShape;\r\n\t\tprivate var _fixtureDef2:b2FixtureDef;\r\n\t\tprivate var _fixture2:b2Fixture;\r\n\t\tprivate var _jointDef:b2RevoluteJointDef;\r\n\t\tprivate var _joint:b2RevoluteJoint;\r\n\t\t\r\n\t\tpublic function WindmillArms(name:String, params:Object=null)\r\n\t\t{\r\n\t\t\tsuper(name, params);\r\n\t\t}\r\n\t\t\r\n\t\toverride public function destroy():void\r\n\t\t{\r\n\t\t\t_hingeBody.destroy();\r\n\t\t\t_hingeBodyDef.destroy();\r\n\t\t\t_fixtureDef2.destroy();\r\n\t\t\tsuper.destroy();\r\n\t\t}\r\n\t\t\r\n\t\toverride public function set x(value:Number):void\r\n\t\t{\r\n\t\t\tsuper.x = value;\r\n\t\t\t\r\n\t\t\tif (_hingeBody)\r\n\t\t\t{\r\n\t\t\t\tvar pos:V2 = _hingeBody.GetPosition();\r\n\t\t\t\tpos.x = _x;\r\n\t\t\t\t_hingeBody.SetTransform(pos, _hingeBody.GetAngle());\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\toverride public function set y(value:Number):void\r\n\t\t{\r\n\t\t\tsuper.y = value;\r\n\t\t\t\r\n\t\t\tif (_hingeBody)\r\n\t\t\t{\r\n\t\t\t\tvar pos:V2 = _hingeBody.GetPosition();\r\n\t\t\t\tpos.y = _y;\r\n\t\t\t\t_hingeBody.SetTransform(pos, _hingeBody.GetAngle());\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function defineBody():void\r\n\t\t{\r\n\t\t\tsuper.defineBody();\r\n\t\t\t\r\n\t\t\t_hingeBodyDef = new b2BodyDef();\r\n\t\t\t_hingeBodyDef.type = b2Body.b2_staticBody;\r\n\t\t\t_hingeBodyDef.position.v2 = new V2(_x, _y);\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function createBody():void\r\n\t\t{\r\n\t\t\tsuper.createBody();\r\n\t\t\t\r\n\t\t\t_hingeBody = _box2D.world.CreateBody(_hingeBodyDef);\r\n\t\t\t_hingeBody.SetUserData(this);\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function createShape():void\r\n\t\t{\r\n\t\t\tsuper.createShape();\r\n\t\t\t\r\n\t\t\t_shape2 = new b2PolygonShape();\r\n\t\t\t_shape2.SetAsBox(_width \/ 2, _height \/ 2, null, _rotation + (Math.PI \/ 2));\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function defineFixture():void\r\n\t\t{\r\n\t\t\tsuper.defineFixture();\r\n\t\t\t\r\n\t\t\t_fixtureDef2 = new b2FixtureDef();\r\n\t\t\t_fixtureDef2.shape = _shape2;\r\n\t\t\t_fixtureDef2.density = _fixtureDef.density;\r\n\t\t\t_fixtureDef2.friction = _fixtureDef.friction;\r\n\t\t\t_fixtureDef2.restitution = _fixtureDef.restitution;\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function createFixture():void\r\n\t\t{\r\n\t\t\tsuper.createFixture();\r\n\t\t\t_fixture2 = _body.CreateFixture(_fixtureDef2);\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function defineJoint():void\r\n\t\t{\r\n\t\t\tsuper.defineJoint();\r\n\t\t\t\r\n\t\t\t_jointDef = new b2RevoluteJointDef();\r\n\t\t\t_jointDef.bodyA = _hingeBody;\r\n\t\t\t_jointDef.bodyB = _body;\r\n\t\t\t_jointDef.enableMotor = true;\r\n\t\t\t_jointDef.maxMotorTorque = 6\r\n\t\t\t_jointDef.motorSpeed = 0;\r\n\t\t\t_jointDef.localAnchorA.v2 = new V2();\r\n\t\t\t_jointDef.localAnchorB.v2 = new V2();\r\n\t\t}\r\n\t\t\r\n\t\toverride protected function createJoint():void\r\n\t\t{\r\n\t\t\tsuper.createJoint();\r\n\t\t\t\r\n\t\t\t_joint = _box2D.world.CreateJoint(_jointDef) as b2RevoluteJoint;\r\n\t\t\t_joint.SetUserData(this);\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>Easier than it sounds, right? The key is to override defined methods and add your new boddie.<\/p>\n<p>Let&#8217;s go back to the first example on <a href=\"http:\/\/www.emanueleferonato.com\/2012\/03\/19\/basic-box2d-rope-chain-2-1a-version\/\" target=\"_blank\">Emanuele&#8217;s website<\/a>.<br \/>\nClick <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2012\/11\/index.html\" target=\"_blank\">here for the web demo<\/a>.<br \/>\nAs usal, all the source code is available on the CE&#8217;s<a href=\"https:\/\/github.com\/alamboley\/Citrus-Engine-Examples\/tree\/master\/src\/complexbox2dobject\" target=\"_blank\"> GitHub dedicated to examples<\/a>.<br \/>\nActually, you see the Box2D debug view, to see arts use the console :<br \/>\nPress <em>tab<\/em> key, write :<\/p>\n<pre>set box2D visible false<\/pre>\n<p>And press <em>enter<\/em>.<\/p>\n<p>There are two ways to achieve it, one is not better than the other, it&#8217;s just different. You will certainly prefer one depending what you&#8217;re trying to achieve.<\/p>\n<p><strong>Create lots of CE&#8217;s object<\/strong><br \/>\nThis is the game state :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport com.citrusengine.core.State;\r\n\timport com.citrusengine.objects.platformer.box2d.Platform;\r\n\timport com.citrusengine.physics.box2d.Box2D;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class ComplexBox2DObjectGameState extends State {\r\n\r\n\t\tpublic function ComplexBox2DObjectGameState() {\r\n\t\t\tsuper();\r\n\t\t}\r\n\r\n\t\toverride public function initialize():void {\r\n\r\n\t\t\tsuper.initialize();\r\n\r\n\t\t\tvar box2D:Box2D = new Box2D(\"box2D\");\r\n\t\t\tbox2D.visible = true;\r\n\t\t\tadd(box2D);\r\n\r\n\t\t\tvar platTop:Platform = new Platform(\"platTop\", {x:stage.stageWidth \/ 2, width:stage.stageWidth, y:20});\r\n\t\t\tadd(platTop);\r\n\r\n\t\t\tvar chain:Chain;\r\n\t\t\tvar vecChain:Vector.<Chain> = new Vector.<Chain>();\r\n\t\t\tfor (var i:uint = 0; i < 4; ++i) {\r\n\r\n\t\t\t\tif (i == 0)\r\n\t\t\t\t\tchain = new Chain(\"chain\" + i, {x:stage.stageWidth \/ 2, y:70 + i * 40, width:15, hangTo:platTop, distance:i, view:new ChainGraphic()});\r\n\t\t\t\telse\r\n\t\t\t\t\tchain = new Chain(\"chain\" + i, {x:stage.stageWidth \/ 2, y:70 + i * 40, width:15, hangTo:vecChain[i - 1], distance:i, view:new ChainGraphic()});\r\n\r\n\t\t\t\tvecChain.push(chain);\r\n\t\t\t\tadd(chain);\r\n\t\t\t}\r\n\r\n\t\t\tchain = new Chain(\"chain\" + i, {x:2, y:70 + (i + 1) * 40, radius:15, hangTo:vecChain[i - 1], distance:i + 1, last:true, registration:\"topLeft\", view:new ChainGraphic(15)});\r\n\t\t\tadd(chain);\r\n\t\t\tvecChain.push(chain);\r\n\t\t}\r\n\r\n\t}\r\n}<\/pre>\n<p>Here we create many CE objects, with lots of similar informations. The good thing is all the arts are managed by SpriteView and SpriteArt classes.<br \/>\nThe Box2D Chain class :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport Box2D.Common.Math.b2Vec2;\r\n\timport Box2D.Dynamics.Joints.b2RevoluteJointDef;\r\n\r\n\timport com.citrusengine.objects.Box2DPhysicsObject;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class Chain extends Box2DPhysicsObject {\r\n\r\n\t\tpublic var hangTo:Box2DPhysicsObject;\r\n\t\tpublic var distance:uint;\r\n\t\tpublic var last:Boolean = false;\r\n\r\n\t\tprivate var _revoluteJointDef:b2RevoluteJointDef;\r\n\r\n\t\tpublic function Chain(name:String, params:Object) {\r\n\t\t\tsuper(name, params);\r\n\t\t}\r\n\r\n\t\toverride protected function defineJoint():void {\r\n\r\n\t\t\t_revoluteJointDef = new b2RevoluteJointDef();\r\n\r\n\t\t\tif (last) {\r\n\t\t\t\t_revoluteJointDef.localAnchorA.Set(0, (distance + 75) \/ _box2D.scale);\r\n\t\t\t\t_revoluteJointDef.localAnchorB.Set(0, 0);\r\n\t\t\t\t_revoluteJointDef.bodyA = hangTo.body;\r\n\t\t\t\t_revoluteJointDef.bodyB = _body;\r\n\t\t\t} else\r\n\t\t\t\t_revoluteJointDef.Initialize(hangTo.body, _body, new b2Vec2(275 \/ _box2D.scale, (70 + distance * 40) \/ _box2D.scale));\r\n\t\t}\r\n\r\n\t\toverride protected function createJoint():void {\r\n\r\n\t\t\t_box2D.world.CreateJoint(_revoluteJointDef);\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>Nothing too complex, we just create a joint in the right method.<\/p>\n<p>And finally the ChainGraphic class :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport flash.display.Sprite;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class ChainGraphic extends Sprite {\r\n\r\n\t\tpublic function ChainGraphic(radius:uint = 0) {\r\n\t\t\t\r\n\t\t\tthis.graphics.beginFill(Math.random() * 0xFFFFFF);\r\n\t\t\t\r\n\t\t\tif (radius != 0)\r\n\t\t\t\tthis.graphics.drawCircle(0, 0, radius);\r\n\t\t\telse\r\n\t\t\t\tthis.graphics.drawRect(0, 0, 15, 30);\r\n\t\t\t\t\r\n\t\t\tthis.graphics.endFill();\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>That's it for the first method, the most obvious.<\/p>\n<p><strong>Only one complex Box2D and art classes<\/strong><\/p>\n<p>For the second method, like the mill's arms we create several Box2D bodies in one Box2DPhysicsObject class.<br \/>\nThe GameState :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport com.citrusengine.core.State;\r\n\timport com.citrusengine.objects.platformer.box2d.Platform;\r\n\timport com.citrusengine.physics.box2d.Box2D;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class ComplexBox2DObjectGameState extends State {\r\n\r\n\t\tpublic function ComplexBox2DObjectGameState() {\r\n\t\t\tsuper();\r\n\t\t}\r\n\r\n\t\toverride public function initialize():void {\r\n\r\n\t\t\tsuper.initialize();\r\n\r\n\t\t\tvar box2D:Box2D = new Box2D(\"box2D\");\r\n\t\t\tbox2D.visible = true;\r\n\t\t\tadd(box2D);\r\n\r\n\t\t\tvar platTop:Platform = new Platform(\"platTop\", {x:stage.stageWidth \/ 2, width:stage.stageWidth, y:20});\r\n\t\t\tadd(platTop);\r\n\r\n\t\t\tvar ropeChain:RopeChain = new RopeChain(\"ropeChain\", {hangTo:platTop, radius:15, y:150, x:30, view:new RopeChainGraphics(), registration:\"topLeft\"});\r\n\t\t\tadd(ropeChain);\r\n\t\t}\r\n\r\n\t}\r\n}<\/pre>\n<p>The object created there is basically a circle hang to the platform top with several chains.<br \/>\nThe RopeChain class :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport Box2D.Collision.Shapes.b2PolygonShape;\r\n\timport Box2D.Collision.Shapes.b2Shape;\r\n\timport Box2D.Common.Math.b2Vec2;\r\n\timport Box2D.Dynamics.Joints.b2RevoluteJointDef;\r\n\timport Box2D.Dynamics.b2Body;\r\n\timport Box2D.Dynamics.b2BodyDef;\r\n\timport Box2D.Dynamics.b2FixtureDef;\r\n\r\n\timport com.citrusengine.objects.Box2DPhysicsObject;\r\n\timport com.citrusengine.physics.PhysicsCollisionCategories;\r\n\r\n\timport flash.geom.Point;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class RopeChain extends Box2DPhysicsObject {\r\n\r\n\t\tpublic var hangTo:Box2DPhysicsObject;\r\n\r\n\t\tpublic var numChain:uint = 5;\r\n\t\tpublic var widthChain:uint = 15;\r\n\t\tpublic var heightChain:uint = 30;\r\n\t\tpublic var attach:Point = new Point(275, 60);\r\n\t\tpublic var distance:uint = 32;\r\n\r\n\t\tprivate var _vecBodyDefChain:Vector.<b2BodyDef>;\r\n\t\tprivate var _vecBodyChain:Vector.<b2Body>;\r\n\t\tprivate var _vecFixtureDefChain:Vector.<b2FixtureDef>;\r\n\t\tprivate var _vecRevoluteJointDef:Vector.<b2RevoluteJointDef>;\r\n\t\tprivate var _shapeChain:b2Shape;\r\n\r\n\t\tpublic function RopeChain(name:String, params:Object = null) {\r\n\t\t\tsuper(name, params);\r\n\t\t}\r\n\t\t\t\r\n\t\toverride public function initialize(poolObjectParams:Object = null):void {\r\n\t\t\tsuper.initialize(poolObjectParams);\r\n\t\t\t\r\n\t\t\tif (view)\r\n\t\t\t\t(view as RopeChainGraphics).init(numChain, widthChain, heightChain);\r\n\t\t}\r\n\t\t\t\r\n\t\toverride public function update(timeDelta:Number):void {\r\n\t\t\tsuper.update(timeDelta);\r\n\t\t\t\r\n\t\t\tif (view)\r\n\t\t\t\t(view as RopeChainGraphics).update(_vecBodyChain, _box2D.scale);\r\n\t\t}\r\n\r\n\t\toverride protected function defineBody():void {\r\n\t\t\tsuper.defineBody();\r\n\t\t\r\n\t\t\t_vecBodyDefChain = new Vector.<b2BodyDef>();\r\n\t\t\tvar bodyDefChain:b2BodyDef;\r\n\t\t\t\r\n\t\t\tfor (var i:uint = 0; i < numChain; ++i) {\r\n\t\t\t\r\n\t\t\t\tbodyDefChain = new b2BodyDef();\r\n\t\t\t\tbodyDefChain = new b2BodyDef();\r\n\t\t\t\tbodyDefChain.type = b2Body.b2_dynamicBody;\r\n\t\t\t\tbodyDefChain.position = new b2Vec2(attach.x \/ _box2D.scale, (attach.y + i * distance) \/ _box2D.scale);\r\n\t\t\t\tbodyDefChain.angle = _rotation;\r\n\t\t\t\r\n\t\t\t\t_vecBodyDefChain.push(bodyDefChain);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toverride protected function createBody():void {\r\n\t\t\tsuper.createBody();\r\n\r\n\t\t\t_vecBodyChain = new Vector.<b2Body>();\r\n\t\t\tvar bodyChain:b2Body;\r\n\r\n\t\t\tfor each (var bodyDefChain:b2BodyDef in _vecBodyDefChain) {\r\n\r\n\t\t\t\tbodyChain = _box2D.world.CreateBody(bodyDefChain);\r\n\t\t\t\tbodyChain.SetUserData(this);\r\n\t\t\t\t\r\n\t\t\t\t_vecBodyChain.push(bodyChain);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\toverride protected function createShape():void {\r\n\t\t\tsuper.createShape();\r\n\r\n\t\t\t_shapeChain = new b2PolygonShape();\r\n\t\t\tb2PolygonShape(_shapeChain).SetAsBox(widthChain \/ 2 \/ _box2D.scale, heightChain \/ 2 \/ _box2D.scale);\r\n\t\t}\r\n\r\n\t\toverride protected function defineFixture():void {\r\n\t\t\tsuper.defineFixture();\r\n\r\n\t\t\t_vecFixtureDefChain = new Vector.<b2FixtureDef>();\r\n\t\t\tvar fixtureDefChain:b2FixtureDef;\r\n\r\n\t\t\tfor (var i:uint = 0; i < numChain; ++i) {\r\n\r\n\t\t\t\tfixtureDefChain = new b2FixtureDef();\r\n\t\t\t\tfixtureDefChain.shape = _shapeChain;\r\n\t\t\t\tfixtureDefChain.density = 1;\r\n\t\t\t\tfixtureDefChain.friction = 0.6;\r\n\t\t\t\tfixtureDefChain.restitution = 0.3;\r\n\t\t\t\tfixtureDefChain.filter.categoryBits = PhysicsCollisionCategories.Get(\"Level\");\r\n\t\t\t\tfixtureDefChain.filter.maskBits = PhysicsCollisionCategories.GetAll();\r\n\r\n\t\t\t\t_vecFixtureDefChain.push(fixtureDefChain);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toverride protected function createFixture():void {\r\n\t\t\tsuper.createFixture();\r\n\r\n\t\t\tvar i:uint = 0;\r\n\r\n\t\t\tfor each (var fixtureDefChain:b2FixtureDef in _vecFixtureDefChain) {\r\n\t\t\t\t_vecBodyChain[i].CreateFixture(fixtureDefChain);\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\toverride protected function defineJoint():void {\r\n\r\n\t\t\t_vecRevoluteJointDef = new Vector.<b2RevoluteJointDef>();\r\n\t\t\tvar revoluteJointDef:b2RevoluteJointDef;\r\n\r\n\t\t\tfor (var i:uint = 0; i < numChain; ++i) {\r\n\r\n\t\t\t\trevoluteJointDef = new b2RevoluteJointDef();\r\n\r\n\t\t\t\tif (i == 0)\r\n\t\t\t\t\trevoluteJointDef.Initialize(hangTo.body, _vecBodyChain[i], new b2Vec2(attach.x \/ _box2D.scale, (attach.y + i * distance) \/ _box2D.scale));\r\n\t\t\t\telse\r\n\t\t\t\t\trevoluteJointDef.Initialize(_vecBodyChain[i - 1], _vecBodyChain[i], new b2Vec2(attach.x \/ _box2D.scale, (attach.y + i * distance) \/ _box2D.scale));\r\n\t\t\t\t\r\n\t\t\t\t_vecRevoluteJointDef.push(revoluteJointDef);\r\n\t\t\t}\r\n\r\n\t\t\t\r\n\t\t\trevoluteJointDef = new b2RevoluteJointDef();\r\n\t\t\trevoluteJointDef.localAnchorA.Set(0, distance \/ _box2D.scale);\r\n\t\t\trevoluteJointDef.localAnchorB.Set(0, 0);\r\n\t\t\trevoluteJointDef.bodyA = _vecBodyChain[numChain - 1];\r\n\t\t\trevoluteJointDef.bodyB = _body;\r\n\r\n\t\t\t_vecRevoluteJointDef.push(revoluteJointDef);\r\n\t\t}\r\n\r\n\t\toverride protected function createJoint():void {\r\n\r\n\t\t\tfor each (var revoluteJointDef:b2RevoluteJointDef in _vecRevoluteJointDef) {\r\n\t\t\t\t_box2D.world.CreateJoint(revoluteJointDef);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t}\r\n}<\/pre>\n<p>We create Vectors with all our new chains' bodies.<\/p>\n<p>And finally the most complex part on this second way, the graphic class :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package complexbox2dobject{\r\n\r\n\timport Box2D.Dynamics.b2Body;\r\n\r\n\timport com.citrusengine.math.MathUtils;\r\n\r\n\timport flash.display.Sprite;\r\n\timport flash.geom.Point;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class RopeChainGraphics extends Sprite {\r\n\r\n\t\tprivate var _numChain:uint;\r\n\t\tprivate var _vecSprites:Vector.<Sprite>;\r\n\t\tprivate var _width:uint;\r\n\t\tprivate var _height:uint;\r\n\r\n\t\tpublic function RopeChainGraphics() {\r\n\r\n\t\t\tthis.graphics.beginFill(0xFF0000);\r\n\t\t\tthis.graphics.drawCircle(0, 0, 15);\r\n\t\t\tthis.graphics.endFill();\r\n\t\t}\r\n\r\n\t\tpublic function init(numChain:uint, width:uint, height:uint):void {\r\n\r\n\t\t\t_numChain = numChain;\r\n\t\t\t_width = width;\r\n\t\t\t_height = height;\r\n\r\n\t\t\t_vecSprites = new Vector.<Sprite>();\r\n\t\t\tvar sprite:Sprite;\r\n\r\n\t\t\tfor (var i:uint = 0; i < _numChain; ++i) {\r\n\r\n\t\t\t\tsprite = new Sprite();\r\n\t\t\t\tsprite.graphics.beginFill(Math.random() * 0xFFFFFF);\r\n\t\t\t\tsprite.graphics.drawRect(0, 0, _width, _height);\r\n\t\t\t\tsprite.graphics.endFill();\r\n\r\n\t\t\t\taddChild(sprite);\r\n\t\t\t\t_vecSprites.push(sprite);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tpublic function update(vecBodyChain:Vector.<b2Body>, box2DScale:Number):void {\r\n\r\n\t\t\tvar i:uint = 0;\r\n\t\t\t\r\n\t\t\tfor each (var body:b2Body in vecBodyChain) {\r\n\r\n\t\t\t\t_vecSprites[i].x = body.GetPosition().x * box2DScale - this.parent.x - _width * 0.5;\r\n\t\t\t\t_vecSprites[i].y = body.GetPosition().y * box2DScale - this.parent.y - _height * 0.5;\r\n\t\t\t\t\r\n\t\t\t\tMathUtils.RotateAroundExternalPoint(_vecSprites[i], new Point(_width * 0.5 + _vecSprites[i].x, _height * 0.5 + _vecSprites[i].y), body.GetAngle() * 180 \/ Math.PI - _vecSprites[i].rotation - this.parent.rotation);\r\n\t\t\t\t\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>Since chains' graphics aren't managed by SpriteView and the SpriteArt (only the circle), we have to update them manually! Note that there is a little bug on the rotation, I'm missing something here but can't find the issue... Damn math knowledge \ud83d\ude00 Anyway it shouldn't prevent you to use this method!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some days ago, I said that November will be an awesome month for the Citrus Engine. So what is coming? We&#8217;re the 2nd, November is already here and something huge is already happened to the CE : a tutorial on gotoandlearn made by Lee Brimelow, an Adobe Game Developer Evangelist! Definitely, an excellent tutorial to &hellip; <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/create-combination-of-physics-objects-in-citrus-engine\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Create combination of physics objects in Citrus Engine<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[4,115,51,33,11,114],"tags":[15,27,50,34,26],"_links":{"self":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/793"}],"collection":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/comments?post=793"}],"version-history":[{"count":5,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/793\/revisions"}],"predecessor-version":[{"id":1261,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/793\/revisions\/1261"}],"wp:attachment":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/media?parent=793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/categories?post=793"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/tags?post=793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}