Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Hundreds game, Actionscript 3, Box2D, Flash and Game development.

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:

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:

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.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.