package {
import Box2D.Collision.Shapes.b2BoxDef;
import Box2D.Collision.Shapes.b2CircleShape;
import Box2D.Collision.Shapes.b2PolyShape;
import Box2D.Collision.Shapes.b2Shape;
import Box2D.Collision.b2AABB;
import Box2D.Common.Math.b2Math;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.Joints.b2DistanceJointDef;
import Box2D.Dynamics.Joints.b2Joint;
import Box2D.Dynamics.Joints.b2PrismaticJointDef;
import Box2D.Dynamics.Joints.b2PulleyJoint;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.getTimer;
[SWF(width=640,height=360,backgroundColor=0x404040,frameRate=120)]
public class Box2dAttractTest extends Sprite {
public static const m_iterations:int = 10;
public static const m_timeStep:Number = 1 / 30;
private var _canvas:Sprite;
private var _world:b2World;
private var _targets:Array;
private var _mouseDown:Boolean;
public function Box2dAttractTest() {
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.quality = StageQuality.LOW;
this._canvas = new Sprite();
this.addChild(this._canvas);
this.buildWorld();
this.addEventListener(Event.ENTER_FRAME, update, false, 0, true);
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, function (e:MouseEvent):void {
_mouseDown = true;
});
this.stage.addEventListener(MouseEvent.MOUSE_UP, function (e:MouseEvent):void {
_mouseDown = false;
});
}
public function buildWorld():void {
var worldAABB:b2AABB = new b2AABB();
worldAABB.minVertex.Set(-1000.0, -1000.0);
worldAABB.maxVertex.Set(1000.0, 1000.0);
var gravity:b2Vec2 = new b2Vec2(0.0, 100.0);
var doSleep:Boolean = false;
this._world = new b2World(worldAABB, gravity, doSleep);
var wallSd:b2BoxDef = new b2BoxDef();
var wallBd:b2BodyDef = new b2BodyDef();
wallBd.AddShape(wallSd);
wallSd.extents.Set(100, 400 / 2);
wallBd.position.Set(-95, 360 / 2);
this._world.CreateBody(wallBd);
wallBd.position.Set(640 + 95, 360 / 2);
this._world.CreateBody(wallBd);
wallSd.extents.Set(680/2, 100);
wallBd.position.Set(640/2, -95);
this._world.CreateBody(wallBd);
wallBd.position.Set(640/2, (360+95));
this._world.CreateBody(wallBd);
this._targets = [];
const n:int = 50;
while (n--) {
wallSd.extents.Set(Math.random() * 10 + 2, Math.random() * 30 + 5);
wallSd.density = 1;
wallSd.restitution = 0.3;
wallBd.position.Set(320 + (Math.random() - 0.5) * 200, 180 + (Math.random() - 0.5) * 200);
wallBd.rotation = Math.random() * Math.PI;
this._targets.push(this._world.CreateBody(wallBd));
}
}
public function update(e:Event):void {
this._canvas.graphics.clear()
if (this._mouseDown) {
var mp:b2Vec2;
for each (var t:b2Body in this._targets) {
mp = new b2Vec2(this.mouseX, this.mouseY)
mp.Subtract(t.m_position);
var d:Number = mp.Length();
d = Math.max(20, Math.min(300, d));
var f:Number = -1 / (d * d) * (-d / 300 + 1) * 1e+9;
mp.Normalize();
mp.Multiply(f);
t.ApplyForce(mp, t.m_position);
t.WakeUp();
}
}
var physStart:uint = getTimer();
this._world.Step(m_timeStep, m_iterations);
for (var jj:b2Joint = this._world.m_jointList; jj; jj = jj.m_next){
DrawJoint(jj);
}
for (var bb:b2Body = this._world.m_bodyList; bb; bb = bb.m_next){
for (var s:b2Shape = bb.GetShapeList(); s != null; s = s.GetNext()){
DrawShape(s);
}
}
}
public function DrawShape(shape:b2Shape):void{
switch (shape.m_type)
{
case b2Shape.e_circleShape:
{
var circle:b2CircleShape = shape as b2CircleShape;
var pos:b2Vec2 = circle.m_position;
var r:Number = circle.m_radius;
var k_segments:Number = 16.0;
var k_increment:Number = 2.0 * Math.PI / k_segments;
this._canvas.graphics.lineStyle(1,0xffffff,1);
this._canvas.graphics.moveTo((pos.x + r), (pos.y));
var theta:Number = 0.0;
for (var i:int = 0; i < k_segments; ++i)
{
var d:b2Vec2 = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta));
var v:b2Vec2 = b2Math.AddVV(pos , d);
this._canvas.graphics.lineTo((v.x), (v.y));
theta += k_increment;
}
this._canvas.graphics.lineTo((pos.x + r), (pos.y));
this._canvas.graphics.moveTo((pos.x), (pos.y));
var ax:b2Vec2 = circle.m_R.col1;
var pos2:b2Vec2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y);
this._canvas.graphics.lineTo((pos2.x), (pos2.y));
}
break;
case b2Shape.e_polyShape:
{
var poly:b2PolyShape = shape as b2PolyShape;
var tV:b2Vec2 = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
this._canvas.graphics.lineStyle(1,0xffffff,1);
this._canvas.graphics.moveTo(tV.x, tV.y);
for (i = 0; i < poly.m_vertexCount; ++i)
{
v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
this._canvas.graphics.lineTo(v.x, v.y);
}
this._canvas.graphics.lineTo(tV.x, tV.y);
}
break;
}
}
public function DrawJoint(joint:b2Joint):void
{
var b1:b2Body = joint.m_body1;
var b2:b2Body = joint.m_body2;
var x1:b2Vec2 = b1.m_position;
var x2:b2Vec2 = b2.m_position;
var p1:b2Vec2 = joint.GetAnchor1();
var p2:b2Vec2 = joint.GetAnchor2();
this._canvas.graphics.lineStyle(1,0x44aaff,1/1);
switch (joint.m_type)
{
case b2Joint.e_distanceJoint:
case b2Joint.e_mouseJoint:
this._canvas.graphics.moveTo(p1.x, p1.y);
this._canvas.graphics.lineTo(p2.x, p2.y);
break;
case b2Joint.e_pulleyJoint:
var pulley:b2PulleyJoint = joint as b2PulleyJoint;
var s1:b2Vec2 = pulley.GetGroundPoint1();
var s2:b2Vec2 = pulley.GetGroundPoint2();
this._canvas.graphics.moveTo(s1.x, s1.y);
this._canvas.graphics.lineTo(p1.x, p1.y);
this._canvas.graphics.moveTo(s2.x, s2.y);
this._canvas.graphics.lineTo(p2.x, p2.y);
break;
default:
if (b1 == this._world.m_groundBody){
this._canvas.graphics.moveTo(p1.x, p1.y);
this._canvas.graphics.lineTo(x2.x, x2.y);
}
else if (b2 == this._world.m_groundBody){
this._canvas.graphics.moveTo(p1.x, p1.y);
this._canvas.graphics.lineTo(x1.x, x1.y);
}
else{
this._canvas.graphics.moveTo(x1.x, x1.y);
this._canvas.graphics.lineTo(p1.x, p1.y);
this._canvas.graphics.lineTo(x2.x, x2.y);
this._canvas.graphics.lineTo(p2.x, p2.y);
}
}
}
}
}