Finally the Shrink it prototype is ready.
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.
Next time... player, goal and "mass energy".