“Hundreds” Flash game prototype using Box2D – handling collisions
Welcome to the second part of the Box2D Hundreds prototype.
In this second part I am going to add some features which will make the prototype looking more like the original game, while having something different, just to make a new concept.
So the game now works this way:
* You can make a circle grow endlessly as long as you stay with the mouse over it
* The circle will stop growing, and will never grow again, if you leave the mouse from over it
* If a growing circle hits any other circle, both circles won’t be able to grow anymore and the size of the currently growing circle will be reduced by half.
Give it a try:
This is the commented source code for the main class:
|
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 110 111 112 113 114 115 116 117 118 119 120 121 |
package { import flash.display.Sprite; import flash.events.Event; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; public class Main extends Sprite { // world definition private var world:b2World=new b2World(new b2Vec2(0,0),true); private var worldScale:Number=30; // custom contact listener private var customContact=new CustomContactListener(); // speed of circles private var circleSpeed:Number=5; // body currently being touched private var currentBody:b2Body=null; // check if the mouse was over something private var overSomething:Boolean; public function Main() { // setting the custom contact listener world.SetContactListener(customContact); debugDraw(); // adding 10 random circles for (var i:Number=1; i<=10; i++) { addCircle(); } // adding boundary walls addWall(320,0,640,10); addWall(320,480,640,10); addWall(0,240,10,480); addWall(640,240,10,480); addEventListener(Event.ENTER_FRAME,update); } private function debugDraw():void { var debugDraw:b2DebugDraw=new b2DebugDraw(); var debugSprite:Sprite=new Sprite(); addChild(debugSprite); debugDraw.SetSprite(debugSprite); debugDraw.SetDrawScale(worldScale); debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit); debugDraw.SetFillAlpha(0.5); world.SetDebugDraw(debugDraw); } private function addCircle():void { var bodyDef:b2BodyDef= new b2BodyDef(); bodyDef.type=b2Body.b2_dynamicBody; bodyDef.position.Set(Math.round(Math.random()*600+20)/worldScale,Math.round(Math.random()*440+20)/worldScale); bodyDef.userData={name:"sphere",canGrow:true,isGroving:false}; var circleShape:b2CircleShape = new b2CircleShape(10/worldScale); var fixtureDef:b2FixtureDef = new b2FixtureDef(); fixtureDef.density=1; fixtureDef.friction=0; fixtureDef.restitution=0.5; fixtureDef.shape=circleShape; var body:b2Body=world.CreateBody(bodyDef); body.CreateFixture(fixtureDef); // giving the circle a random direction var randomAngle:Number=Math.random()*2*Math.PI; body.SetLinearVelocity(new b2Vec2(circleSpeed*Math.cos(randomAngle),circleSpeed*Math.sin(randomAngle))); } private function addWall(pX:Number,pY:Number,w:Number,h:Number):void { var bodyDef:b2BodyDef=new b2BodyDef(); bodyDef.position.Set(pX/worldScale,pY/worldScale); var polygonShape:b2PolygonShape=new b2PolygonShape(); polygonShape.SetAsBox(w/2/worldScale,h/2/worldScale); var fixtureDef:b2FixtureDef=new b2FixtureDef(); fixtureDef.shape=polygonShape; fixtureDef.density=1; fixtureDef.restitution=0.5; fixtureDef.friction=0; var theWall:b2Body=world.CreateBody(bodyDef); theWall.CreateFixture(fixtureDef); } // the core of the script, looking for the body touched and // increasing the size of the circle shape private function queryCallback(fixture:b2Fixture):Boolean { var touchedBody:b2Body=fixture.GetBody(); if (touchedBody.GetUserData()!=null) { overSomething=true; if (touchedBody!=currentBody) { if (currentBody!=null) { currentBody.GetUserData().isGroving=false; currentBody.GetUserData().canGrow=false; } currentBody=touchedBody; } if (touchedBody.GetUserData().canGrow) { touchedBody.GetUserData().isGrowing=true; var fixture:b2Fixture=touchedBody.GetFixtureList(); var circleDef:b2CircleShape=fixture.GetShape() as b2CircleShape; var radius:Number=circleDef.GetRadius(); circleDef.SetRadius(radius+1/worldScale); } } return false; } private function update(e:Event):void { world.Step(1/30,10,10); world.ClearForces(); // checking for bodies under the mouse overSomething=false; world.QueryPoint(queryCallback,new b2Vec2(mouseX/worldScale,mouseY/worldScale)); for (var b:b2Body=world.GetBodyList(); b; b=b.GetNext()) { if (b.GetUserData()!=null) { if (! overSomething&&b.GetUserData().isGrowing) { b.GetUserData().isGrowing=false; b.GetUserData().canGrow=false; } // keep moving circles at a constant speed var velocity:b2Vec2=b.GetLinearVelocity(); var speed:Number=velocity.Length(); var ratio:Number=circleSpeed/speed; velocity.Multiply(ratio); b.SetLinearVelocity(velocity); } } world.DrawDebugData(); } } } |
and for the contact listener:
|
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 |
package { import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Dynamics.Joints.*; import Box2D.Dynamics.Contacts.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.b2Vec2; class CustomContactListener extends b2ContactListener { override public function PreSolve(contact:b2Contact, oldManifold:b2Manifold):void { // is the contact touching? if (contact.IsTouching()) { // getting the bodies involved var bodyA:b2Body=contact.GetFixtureA().GetBody(); var bodyB:b2Body=contact.GetFixtureB().GetBody(); // retrieving their user data objects var objA:Object=bodyA.GetUserData(); var objB:Object=bodyB.GetUserData(); var fixture:b2Fixture; var circleDef:b2CircleShape; var radius:Number; if (objA!=null && objB!=null) { if (objA.isGrowing) { objA.isGroving=false; objA.canGrow=false; fixture=bodyA.GetFixtureList(); circleDef=fixture.GetShape() as b2CircleShape; radius=circleDef.GetRadius(); circleDef.SetRadius(radius/2); } if (objB.isGrowing) { objB.isGroving=false; objB.canGrow=false; fixture=bodyB.GetFixtureList(); circleDef=fixture.GetShape() as b2CircleShape; radius=circleDef.GetRadius(); circleDef.SetRadius(radius/2); } } } } } } |
Download the source code. Next time, Nape version.
They can be easily customized to meet the unique requirements of your project.












This post has one comment
Lim Fhiau
it’s hard to play this game when using touchpad :D