{"id":776,"date":"2012-10-26T15:06:05","date_gmt":"2012-10-26T14:06:05","guid":{"rendered":"http:\/\/www.aymericlamboley.fr\/blog\/?p=776"},"modified":"2014-11-01T14:49:00","modified_gmt":"2014-11-01T13:49:00","slug":"moved-from-box2d-alchemy-to-box2d-as3","status":"publish","type":"post","link":"http:\/\/www.aymericlamboley.fr\/blog\/moved-from-box2d-alchemy-to-box2d-as3\/","title":{"rendered":"Moved from Box2D Alchemy to Box2D AS3"},"content":{"rendered":"<p>In the <a href=\"http:\/\/citrusengine.com\/\" target=\"_blank\">Citrus Engine<\/a>, people knows that I&#8217;m very attached to the Box2D Alchemy version. Thanks to Alchemy we should have better performance than the pure AS3 version. Also this Alchemy version had some cool features mostly on the way you could manage collision : you don&#8217;t use a gobal contact listener like in any Box2D version, you use something very closer to AS3 event management. Example :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">override protected function createFixture():void\r\n{\r\n\tsuper.createFixture();\r\n\t\r\n\t_fixture.m_reportBeginContact = true;\r\n\t_fixture.addEventListener(ContactEvent.BEGIN_CONTACT, handleBeginContact);\r\n}\r\n\r\nprotected function handleBeginContact(e:ContactEvent):void\r\n{\r\n\t_contact = e.other.GetBody().GetUserData() as Box2DPhysicsObject;\r\n\tif (!e.other.IsSensor())\r\n\t\texplode();\r\n}<\/pre>\n<p>I love this way. Anyway, many users ask me to change it&#8230; let&#8217;s go!<\/p>\n<p><!--more--><\/p>\n<p><strong>Box2D AS3<\/strong><br \/>\nThis is the contact listener class :<\/p>\n<pre lang=\"actionscript3\">package com.citrusengine.physics.box2d {\r\n\r\n\timport Box2D.Dynamics.b2ContactImpulse;\r\n\timport Box2D.Collision.b2Manifold;\r\n\timport Box2D.Dynamics.Contacts.b2Contact;\r\n\timport Box2D.Dynamics.b2ContactListener;\r\n\r\n\t\/**\r\n\t * Used to report the contact's interaction between object.\r\n\t *\/\r\n\tpublic class Box2DContactListener extends b2ContactListener {\r\n\r\n\t\tpublic function Box2DContactListener() {\r\n\t\t}\r\n\r\n\t\toverride public function BeginContact(contact:b2Contact):void {\r\n\t\t\t\r\n\t\t\tcontact.GetFixtureA().GetBody().GetUserData().handleBeginContact(contact);\r\n\t\t\tcontact.GetFixtureB().GetBody().GetUserData().handleBeginContact(contact);\r\n\t\t}\r\n\t\t\t\r\n\t\toverride public function EndContact(contact:b2Contact):void {\r\n\t\t\t\r\n\t\t\tcontact.GetFixtureA().GetBody().GetUserData().handleEndContact(contact);\r\n\t\t\tcontact.GetFixtureB().GetBody().GetUserData().handleEndContact(contact);\r\n\t\t}\r\n\r\n\t\toverride public function PreSolve(contact:b2Contact, oldManifold:b2Manifold):void {\r\n\t\t\t\r\n\t\t\tcontact.GetFixtureA().GetBody().GetUserData().handlePreSolve(contact, oldManifold);\r\n\t\t\tcontact.GetFixtureB().GetBody().GetUserData().handlePreSolve(contact, oldManifold);\r\n\t\t}\r\n\r\n\t\toverride public function PostSolve(contact:b2Contact, impulse:b2ContactImpulse):void {\r\n\t\t\t\r\n\t\t\tcontact.GetFixtureA().GetBody().GetUserData().handlePostSolve(contact, impulse);\r\n\t\t\tcontact.GetFixtureB().GetBody().GetUserData().handlePostSolve(contact, impulse);\r\n\t\t}\r\n\r\n\t}\r\n}<\/pre>\n<p>And then I override this function <em>handleBeginContact, handleEndContact, handlePreSolve, handlePostSolve<\/em> with what I need. And I use two very useful function to work the same way that I used to do with the Alchemy version :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">\/**\r\n * In Box2D we are blind concerning the collision, we are never sure which body is the collider. This function should help.\r\n * Call this function to obtain the colliding physics object.\r\n * @param self : in CE's code, we give this. In your code it will be your hero, a sensor, ...\r\n * @param the contact\r\n * @return the collider\r\n *\/\r\nstatic public function CollisionGetOther(self:Box2DPhysicsObject, contact:b2Contact):Box2DPhysicsObject {\r\n\treturn self == contact.GetFixtureA().GetBody().GetUserData() ? contact.GetFixtureB().GetBody().GetUserData() : contact.GetFixtureA().GetBody().GetUserData();\r\n}\r\n\r\n\/**\r\n * In Box2D we are blind concerning the collision, we are never sure which body is the collider. This function should help.\r\n * Call this function to obtain the collided physics object.\r\n * @param self : in CE's code, we give this. In your code it will be your hero, a sensor, ...\r\n * @param the contact\r\n * @return the collided\r\n *\/\r\nstatic public function CollisionGetSelf(self:Box2DPhysicsObject, contact:b2Contact):Box2DPhysicsObject {\r\n\treturn self == contact.GetFixtureA().GetBody().GetUserData() ? contact.GetFixtureA().GetBody().GetUserData() : contact.GetFixtureB().GetBody().GetUserData();\r\n}<\/pre>\n<p>And finally an example how it is used :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">override public function handlePreSolve(contact:b2Contact, oldManifold:b2Manifold):void {\r\n\t\r\n\tif (!_ducking)\r\n\t\treturn;\r\n\t\t\r\n\tvar other:Box2DPhysicsObject = Box2DPhysicsObject.CollisionGetOther(this, contact);\r\n\t\r\n\tvar heroTop:Number = y;\r\n\tvar objectBottom:Number = other.y + (other.height \/ 2);\r\n\t\r\n\tif (objectBottom < heroTop)\r\n\t\tcontact.SetEnabled(false);\r\n}<\/pre>\n<p>Pretty cool, isn't it? I know it will be a problem to upgrade on this last version, but it will not be as hard as it sounds since 99% of the code are similar. Just take a look on this new way to handle events.<\/p>\n<p><strong>Performance<\/strong><br \/>\nWhen I made the transition, I told myself : \"We shouldn't see a big difference on a browser version, and if it sucks more than Alchemy on mobile we don't care since there is Nape\"! So I made a test with my quick demo : <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/live4sales-a-plant-vs-zombies-clone\/\" target=\"_blank\">Live4Sales<\/a> game. And this is the result on a iPad3 :<br \/>\n<iframe loading=\"lazy\" src=\"http:\/\/player.vimeo.com\/video\/52216233?badge=0\" width=\"500\" height=\"281\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen><\/iframe><br \/>\nCompare now to the Box2D Alchemy & Nape versions : <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/box2d-alchemy-vs-nape-performance-test-on-ipad3\/\" target=\"_blank\">in this previous stress test<\/a>. Holy s***! Box2D AS3 is very quicker than Alchemy version, really close to Nape in fact. So much close that we should make other tests with different mobiles and other type of games. Nape is always faster, but the difference is small. No more tax, better performances : definitely a good move!<br \/>\nAll the demos have been updated on the <a href=\"https:\/\/github.com\/alamboley\/Citrus-Engine\" target=\"_blank\">GitHub<\/a>.<\/p>\n<p><strong>Version 3?<\/strong><br \/>\nWe've never been so close to the final release, it should be in November. I would like to emphasize two points :<br \/>\n- the 3D part (handled with Away3D & AwayPhysics) is a sandbox for me. I never pretend to offer the best 3D game engine like you can have with <a href=\"http:\/\/unity3d.com\/\" target=\"_blank\">Unity3D<\/a>, how could I compare with them?, but just a good engine where you could create quiclky some 3d physics with a character, sensors... It could be used for simple games or for interactive websites. This 3D part will evolve along the Citrus Engine V3.<br \/>\n- the entity\/component system is not bad, but not as useful as I would. Since some time, it is in stand by. It is not the main features wished by members, so I will refocus on it after. At the moment, use it at your own risk!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Citrus Engine, people knows that I&#8217;m very attached to the Box2D Alchemy version. Thanks to Alchemy we should have better performance than the pure AS3 version. Also this Alchemy version had some cool features mostly on the way you could manage collision : you don&#8217;t use a gobal contact listener like in any &hellip; <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/moved-from-box2d-alchemy-to-box2d-as3\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Moved from Box2D Alchemy to Box2D AS3<\/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,145,114],"tags":[15,27,50,34,26,146],"_links":{"self":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/776"}],"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=776"}],"version-history":[{"count":9,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/776\/revisions"}],"predecessor-version":[{"id":1265,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/776\/revisions\/1265"}],"wp:attachment":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/media?parent=776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/categories?post=776"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/tags?post=776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}