四角をつまんだり、まわしたりforked from: forked from: [Box2D]ダンボー遊び!
四角形の端をつまんで立たせたり、まわしたり
package {
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Collision.Shapes.b2Shape;
import Box2D.Collision.b2AABB;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.Joints.b2MouseJoint;
import Box2D.Dynamics.Joints.b2MouseJointDef;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* 四角形の端をつまんで立たせたり、まわしたり
*/
[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
public class SimpleBox2D extends Sprite
{
// 物理エンジンのクラス
private var world:b2World;
private var DRAW_SCALE:Number = 100;
private var body:b2Body; //オブジェクト
//マウスジョイント定義
private var mouseJointDef:b2MouseJointDef;
//マウスジョイント
private var mouseJoint:b2MouseJoint;
static public var mouseXWorldPhys:Number;
static public var mouseYWorldPhys:Number;
static public var mouseXWorld:Number;
static public var mouseYWorld:Number;
private var mouseDown:Boolean = false;
public var m_timeStep:Number = 1.0/30.0;
private var mousePVec:b2Vec2 = new b2Vec2();
public function SimpleBox2D()
{
addEventListener(Event.ADDED_TO_STAGE, addStageHandler);
}
private function addStageHandler(e:Event):void
{
setField();
}
//物理フィールドの定義
private function setField():void
{
//------------設定
//外枠
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-100, -100);
worldAABB.upperBound.Set(100,100);
//重力
var gravity:b2Vec2 = new b2Vec2(0,10);
world = new b2World(worldAABB, gravity, true);
//------床
var floor1BodyDef:b2BodyDef = new b2BodyDef();
floor1BodyDef.position.Set(465*0.5/DRAW_SCALE, 465/DRAW_SCALE); //床位置
var floor1ShapeDef:b2PolygonDef = new b2PolygonDef(); //床形
floor1ShapeDef.SetAsBox(465*0.5/DRAW_SCALE,0.1); //ステージ幅におさまるように
var floor1:b2Body = world.CreateBody(floor1BodyDef); //床定義
floor1.CreateShape(floor1ShapeDef);
//------------時計体
//時計位置
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.position.Set(2.5, 2);
//時計形
var bodyShape:b2PolygonDef = new b2PolygonDef();
bodyShape.SetAsOrientedBox(0.5, 0.3, new b2Vec2(0,0),0);
bodyShape.density = 1; //重さ
bodyShape.restitution = 0.8; //反発係数
//時計定義
body = world.CreateBody(bodyDef);
body.CreateShape( bodyShape );
body.SetMassFromShapes();
//------------描画設定
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = this;
debugDraw.m_drawScale = DRAW_SCALE; //1mを100ピクセル
debugDraw.m_fillAlpha = 0.8;
debugDraw.m_lineThickness = 1;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
world.SetDebugDraw(debugDraw);
addEventListener(Event.ENTER_FRAME, handleEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
// don't take a capture
Wonderfl.disable_capture();
// take a capture after 1 sec
Wonderfl.capture_delay( 1 );
}
private function handleEnterFrame(e:Event):void
{
world.Step(1 / 24, 10);
UpdateMouseWorld();
MouseDrag();
for (var b:b2Body = world.GetBodyList(); b; b = b.GetNext()) {
if (b.GetUserData() is Sprite) {
b.GetUserData().x = b.GetWorldCenter().x * DRAW_SCALE;
b.GetUserData().y = b.GetWorldCenter().y * DRAW_SCALE;
b.GetUserData().rotation = b.GetAngle() * 180 / Math.PI;
}
}
}
public function UpdateMouseWorld():void {
mouseXWorldPhys = (mouseX)/DRAW_SCALE;
mouseYWorldPhys = (mouseY)/DRAW_SCALE;
mouseXWorld = (mouseX);
mouseYWorld = (mouseY);
}
private function mouseLeaveHandler(e:Event):void
{
mouseDown = false;
MouseDrag();
}
private function mouseMoveHandler(e:MouseEvent):void
{
if (mouseDown != e.buttonDown){
mouseDown = e.buttonDown;
}
}
public function GetBodyAtMouse(includeStatic:Boolean = false):b2Body {
// Make a small box.
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);
// Query the world for overlapping shapes.
var k_maxCount:int = 1;
var shapes:Array = new Array();
var count:int = world.Query(aabb, shapes, k_maxCount);
var body:b2Body = null;
for (var i:int = 0; i < count; ++i)
{
if (shapes[i].GetBody().IsStatic() == false || includeStatic)
{
var tShape:b2Shape = shapes[i] as b2Shape;
var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
if (inside)
{
body = tShape.GetBody();
break;
}
}
}
return body;
}
private function mouseDownHandler(e:MouseEvent):void
{
mouseDown = true;
}
private function mouseUpHandler(e:MouseEvent):void
{
//マウス切り離し
mouseDown = false;
}
public function MouseDrag():void {
// mouse press
if (mouseDown && !mouseJoint){
var body:b2Body = GetBodyAtMouse();
if (body)
{
var md:b2MouseJointDef = new b2MouseJointDef();
md.body1 = world.GetGroundBody();
md.body2 = body;
md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
md.maxForce = 300.0 * body.GetMass();
md.timeStep = m_timeStep;
mouseJoint = world.CreateJoint(md) as b2MouseJoint;
body.WakeUp();
}
}
// mouse release
if (!mouseDown){
if (mouseJoint) {
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
// mouse move
if (mouseJoint)
{
var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
mouseJoint.SetTarget(p2);
}
}
}
}