このコンテンツをご覧いただくには「javascriptをON」「flash player9以上」が必須環境となります。 / RSSリーダーで読んでいる方は、本記事に移動してごらんください。
Box2DFlashAS3 Study#1 「ぽとぽと落ちてくる」の続き。今回は「JOINT」の学習。とりいそぎ、デバッグモードで公開。Box2DFlashAS3をダウンロードするとおまけで付いてくるサンプルを参考にした。
ゴンドラの数に合わせて、ゴンドラの位置が自動的に決まるよう三角関数を使った。数学を学んでおいて、楽ができた。よかった。
package {
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Dynamics.Joints.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Common.*;
import Box2D.Common.Math.*;
import General.Input;
import flash.display.*;
import flash.events.Event;
public class FerrisWheel extends Sprite {
//Box2D variables
public var m_sprite:Sprite;
public var m_world:b2World;
public var m_iterations:int;
public var m_timeStep:Number;
public var m_physScale:Number;
public var m_mouseJoint:b2MouseJoint;
// world mouse position
static public var mouseXWorldPhys:Number;
static public var mouseYWorldPhys:Number;
static public var mouseXWorld:Number;
static public var mouseYWorld:Number;
private var mousePVec:b2Vec2;
// input
public var m_input:Input;
//constructor
public function FerrisWheel() {
{
m_sprite = new Sprite();
addChild(m_sprite);
m_iterations=10;//計算精度
m_timeStep=1 / 30;//1meter=30pixels
m_physScale=30;
m_input = new Input(m_sprite);
mousePVec = new b2Vec2();
};
// make base world
{
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-1000.0, -1000.0);
worldAABB.upperBound.Set(1000.0, 1000.0);
var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);//重力(x方向,y方向)
var doSleep:Boolean = true;
m_world = new b2World(worldAABB, gravity, doSleep);
};
// Def
var bd:b2BodyDef;
var circ:b2CircleDef = new b2CircleDef();
var box:b2PolygonDef = new b2PolygonDef();
var Djd:b2DistanceJointDef = new b2DistanceJointDef();
var Rjd:b2RevoluteJointDef = new b2RevoluteJointDef();
//------------------------------------------------------------
// 観覧車
//------------------------------------------------------------
//回転軸
var RotationAxisX:Number = 250;//回転軸のx座標
var RotationAxisY:Number = 220;//回転軸のy座標
circ.radius = 10.0 / m_physScale;
circ.density = 1.0;
circ.friction = 0.4;
circ.restitution = 0.3;
bd = new b2BodyDef();
bd.position.Set(RotationAxisX / m_physScale, RotationAxisY / m_physScale);
var RotationAxis:b2Body = m_world.CreateStaticBody(bd);
RotationAxis.CreateShape(circ);
RotationAxis.SetMassFromShapes();
//ゴンドラまとめて生成
var gNum:int=16;//ゴンドラの数
for (var i:int = 0; i < gNum; i++) {
//ぷらんぷらん点(ゴンドラをつり下げる点)
circ.radius = 10.0 / m_physScale;
circ.density = 0.2;
bd = new b2BodyDef();
var gR:Number=180;//回転軸からぷらんぷらん点までの距離
var gX:Number=gR*Math.cos(i*360/gNum*Math.PI/180);//ぷらんぷらん点のx座標
var gY:Number=-1*gR*Math.sin(i*360/gNum*Math.PI/180);//ぷらんぷらん点のy座標
bd.position.Set((gX+RotationAxisX) / m_physScale, (gY+RotationAxisY) / m_physScale);
var connect:b2Body = m_world.CreateDynamicBody(bd);
connect.CreateShape(circ);
connect.SetMassFromShapes();
// ゴンドラ
box.SetAsBox(15/ m_physScale, 20 / m_physScale);
box.density = 0.01;
box.friction = 0.4;
box.restitution = 0.9;
bd = new b2BodyDef();
bd.position.Set((gX+RotationAxisX) / m_physScale, (gY+RotationAxisY+30) / m_physScale);
var gondola:b2Body = m_world.CreateDynamicBody(bd);
gondola.CreateShape(box);
gondola.SetMassFromShapes();
//------------------------------------------------------------
// JOINT
//------------------------------------------------------------
//回転軸とぷらんぷらん点
Rjd.enableMotor = true;
Rjd.motorSpeed = 0.2;
Rjd.maxMotorTorque = 10000;
Rjd.Initialize(RotationAxis,connect,RotationAxis.GetPosition());
m_world.CreateJoint(Rjd);
//ぷらんぷらん点とゴンドラ
Djd.Initialize(connect, gondola, connect.GetPosition(),new b2Vec2((gX+RotationAxisX) / m_physScale, (gY+RotationAxisY+30-20) / m_physScale));
m_world.CreateJoint(Djd);
}
setDebug();
this.addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
}
//------------------------------------------------------------
// debug mode
//------------------------------------------------------------
public function setDebug():void {
var dbgDraw:b2DebugDraw = new b2DebugDraw();//デバッグオブジェクトを生成
var dbgSprite:Sprite = new Sprite();//デバッグ用オブジェクトの表示用sprite
addChild(dbgSprite);//表示用スプライトを表示
dbgDraw.m_sprite = dbgSprite;//これはお決まり。
dbgDraw.m_drawScale = m_physScale;//ここでm_physScaleと違う値を入れると思わぬ表示になってしまう。
dbgDraw.m_fillAlpha = 0.5;//デバッグ用オブジェクトの透明度。表示されるオブジェクト全体に設定される。
dbgDraw.m_lineThickness = 1;//デバッグ用オブジェクトのライン。
dbgDraw.m_drawFlags = 0xFFFFFFFF;//デバッグ用オブジェクトの色指定。
m_world.SetDebugDraw(dbgDraw);//Box2Dのworldに追加。
}
//------------------------------------------------------------
// update every frame
//------------------------------------------------------------
public function Update(e:Event):void {
m_world.Step(m_timeStep,m_iterations);
UpdateMouseWorld();
MouseDrag();
Input.update();
}
//------------------------------------------------------------
// Update mouseWorld
//------------------------------------------------------------
public function UpdateMouseWorld():void {
mouseXWorldPhys = (Input.mouseX)/m_physScale;
mouseYWorldPhys = (Input.mouseY)/m_physScale;
mouseXWorld = (Input.mouseX);
mouseYWorld = (Input.mouseY);
}
//------------------------------------------------------------
// Mouse Drag
//------------------------------------------------------------
public function MouseDrag():void {
// mouse press
if (Input.mouseDown && !m_mouseJoint) {
buttonMode = true;
var body:b2Body = GetBodyAtMouse();
if (body) {
var md:b2MouseJointDef = new b2MouseJointDef();
md.body1 = m_world.m_groundBody;
md.body2 = body;
md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
md.maxForce = 300.0 * body.m_mass;
md.timeStep = m_timeStep;
m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint;
body.WakeUp();
}
}
// mouse release
if (!Input.mouseDown) {
if (m_mouseJoint) {
m_world.DestroyJoint(m_mouseJoint);
m_mouseJoint = null;
}
}
// mouse move
if (m_mouseJoint) {
var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
m_mouseJoint.SetTarget(p2);
}
}
//------------------------------------------------------------
// GetBodyAtMouse
//------------------------------------------------------------
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 = 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) {
if (shapes[i].m_body.IsStatic() == false || includeStatic) {
var tShape:b2Shape = shapes[i] as b2Shape;
var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), mousePVec);
if (inside) {
body = tShape.m_body;
break;
}
}
}
return body;
}
}
}
コメントする