<Emanuele Feronato/>
home

Shrink it Box2D prototype

Finally the Shrink it prototype is ready.

Shrink it

This post continues Scaling objects with Box2D and Scaling objects with Box2D – part 2, with these features:

1) You can’t modify static objects

2) You can shrink objects with left mouse button, and expand them with left mouse button + SPACE, as in the original game

3) You can shrink/expand any polygon thanks to Ilya‘s suggestion made in this post.

Now in the stage we have four objects: a circle, a square, a triangle and a custom shape. Refer to Understanding custom polygons in Box2D for more information about custom shapes.

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.KeyboardEvent;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	public class shrink extends Sprite {
		var body:b2Body;
		public var m_world:b2World;
		public var m_iterations:int=10;
		public var m_timeStep:Number=1.0/30.0;
		public var mousePVec:b2Vec2 = new b2Vec2();
		// variable to store if the player is pressing SPACE
		public var space_pressed:Boolean=false;
		public function shrink() {
			var worldAABB:b2AABB = new b2AABB();
			var bodyDef:b2BodyDef = new b2BodyDef();
			var polygon:b2PolygonDef = new b2PolygonDef();
			var circleDef:b2CircleDef= new b2CircleDef();
			worldAABB.lowerBound.Set(-100.0, -100.0);
			worldAABB.upperBound.Set(100.0, 100.0);
			m_world=new b2World(worldAABB,new b2Vec2(0,10),true);
			// debug draw start
			var m_sprite:Sprite;
			m_sprite = new Sprite();
			addChild(m_sprite);
			var dbgDraw:b2DebugDraw = new b2DebugDraw();
			var dbgSprite:Sprite = new Sprite();
			m_sprite.addChild(dbgSprite);
			dbgDraw.m_sprite=m_sprite;
			dbgDraw.m_drawScale=30;
			dbgDraw.m_alpha=1;
			dbgDraw.m_fillAlpha=0.5;
			dbgDraw.m_lineThickness=1;
			dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit;
			m_world.SetDebugDraw(dbgDraw);
			// debug draw end
			// ground
			bodyDef.position.Set(10, 12);
			polygon.SetAsBox(30, 3);
			polygon.density=0;
			polygon.friction=0.3;
			polygon.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(polygon);
			body.SetMassFromShapes();
			// circle
			bodyDef.position.Set(3,5);
			circleDef.radius=2;
			circleDef.density=1;
			circleDef.friction=0.5;
			circleDef.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(circleDef);
			body.SetMassFromShapes();
			// box
			bodyDef.position.Set(13, 5);
			polygon.SetAsBox(2, 2);
			polygon.density=1;
			polygon.friction=0.5;
			polygon.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(polygon);
			body.SetMassFromShapes();
			// triangle
			bodyDef.position.Set(13,3);
			polygon.vertexCount=3;
			polygon.vertices[0].Set(0,-2);
			polygon.vertices[1].Set(2,2);
			polygon.vertices[2].Set(-2,2);
			polygon.density=1;
			polygon.friction=0.5;
			polygon.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(polygon);
			body.SetMassFromShapes();
			// custom shape
			bodyDef.position.Set(8,4);
			polygon.vertexCount=5;
			polygon.vertices[0].Set(0,-2);
			polygon.vertices[1].Set(2,0);
			polygon.vertices[2].Set(1,2);
			polygon.vertices[3].Set(-1,2);
			polygon.vertices[4].Set(-2,0);
			polygon.density=1;
			polygon.friction=0.5;
			polygon.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(polygon);
			body.SetMassFromShapes();
			//
			addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down);
			stage.addEventListener( KeyboardEvent.KEY_UP, key_up);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, GetBodyAtMouse);
		}
		// detecting if the player pressed SPACE
		public function key_down(event:KeyboardEvent):void {
			if (event.keyCode==32) {
				space_pressed=true;
			}
		}
		// detecting if the player released SPACE
		public function key_up(event:KeyboardEvent):void {
			if (event.keyCode==32) {
				space_pressed=false;
			}
		}
		//
		public function GetBodyAtMouse(e:MouseEvent):b2Body {
			var mult:Number=0.9;
			if (space_pressed) {
				mult=1.1;
			}
			var mouseXWorldPhys = (mouseX)/30;
			var mouseYWorldPhys = (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=m_world.Query(aabb,shapes,k_maxCount);
			var body:b2Body=null;
			for (var i:int = 0; i < count; ++i) {
				var tShape:b2Shape=shapes[i] as b2Shape;
				var inside:Boolean=tShape.TestPoint(tShape.GetBody().GetXForm(),mousePVec);
				if (inside) {
					body=tShape.GetBody();
					break;
				}
			}
			// if I selected a STATIC body...
			if (body&&! body.IsStatic()) {
				var s:b2Shape=body.GetShapeList();
				var type:int=s.GetType();
				switch (type) {
					case 0 :
						// I know it's a circle, so I am creating a b2CircleShape variable
						var circle:b2CircleShape=body.GetShapeList() as b2CircleShape;
						// getting the radius..
						var r=circle.GetRadius();
						// removing the circle shape from the body
						body.DestroyShape(circle);
						// creating a new circle shape
						var circleDef:b2CircleDef;
						circleDef = new b2CircleDef();
						// calculating new radius
						circleDef.radius=r*mult;
						circleDef.density=1.0;
						circleDef.friction=0.5;
						circleDef.restitution=0.2;
						// attach the shape to the body
						body.CreateShape(circleDef);
						// determine new body mass
						body.SetMassFromShapes();
						break;
					case 1 :
						// now I know it's a polygon
						var poly:b2PolygonShape=body.GetShapeList() as b2PolygonShape;
						// UNIVERSAL POLYGON SCALING ROUTINE THANX TO ILYA
						var vertex_num:int=poly.GetVertexCount();
						var vertex_array:Array=poly.GetVertices();
						for each (var vert:b2Vec2 in vertex_array) {
							vert.Multiply(mult);
						}
						body.DestroyShape(poly);
						var new_shape:b2PolygonDef = new b2PolygonDef();
						new_shape.vertexCount=vertex_num;
						new_shape.vertices=vertex_array;
						new_shape.friction=0.5;
						new_shape.density=1;
						new_shape.restitution=0.2;
						body.CreateShape(new_shape);
						body.SetMassFromShapes();
						break;
				}
			}
			return body;
		}
		public function Update(e:Event):void {
			m_world.Step(m_timeStep, m_iterations);
		}
	}
}

And this is the result:

Left click on a static body with the mouse to shrink it, left click + SPACE to expand it.

Download the source code.

Next time... player, goal and "mass energy".

230 games covered