- 2010-02-09 (火) 13:10
- Box2D
Box2DFlashAS3(ver2.0.2)で物体をマウス操作する
Box2DFlashAS3 を使ってみる[Box2D-1]ではBox2Dの物理エンジンを体験しましたが、今回は落下物を掴む動きを追加したいと思います。
ちょっと訳がわからくなって気がちですが、自分の作業メモ的に説明していきます。
Box2Dにはマウス処理をするにあたりマウスジョイントと言うプログラムが初めから使えるようになっています。
マウスジョイントとは物体とマウスをジョイント(付ける)処理と考えると分かりやすいかもしれません・・・
Box2DFlashAS3 を使ってみる[Box2D-1]をベースにまずはマウスジョントを宣言します。
private var mouseJointDef:b2MouseJointDef; // マウスジョイントの定義 private var mouseJoint:b2MouseJoint; // マウスジョイント
あとインポートにマウスイベントを指定も忘れずにお願いします。
次にマウス操作のイベントリスナーとそのメソッドを追加します。
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
マウスが押された時
private function mouseDownHandler(event:MouseEvent):void {
var body : b2Body = GetBodyAtMouse(event.stageX, event.stageY);
if (body) {
var md : b2MouseJointDef = new b2MouseJointDef();
md.body1 = world.m_groundBody;
md.body2 = body;
md.target.Set(event.stageX / SCALE, event.stageY / SCALE);
md.maxForce = 500.0 * body.m_mass;
md.timeStep = 1 / 24;
mouseJoint = world.CreateJoint(md) as b2MouseJoint;
body.WakeUp();
}
}
ここで重要になるのが、GetBodyAtMouseです。
マウスダウンした時に該当する物体があるかを判定していますが詳しく説明ができないので、もっと理解してからと言うことでお願いします。
//該当オブジェクトがあるかの判定
private function GetBodyAtMouse(stageX : Number, stageY : Number) : b2Body {
// Make a small box.
var mousePVec : b2Vec2 = new b2Vec2();
var mouseXWorldPhys : Number = stageX / SCALE;
var mouseYWorldPhys : Number = stageY / SCALE;
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 = 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) {
var tShape : b2Shape = shapes[i] as b2Shape;
var inside : Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), mousePVec);
if (inside) {
body = tShape.m_body;
break;
}
}
}
}
あとはマウスを動かした時とマウスを離した時の処理を追加するだけです。
//mouseUphandler
private function mouseUpHandler(event:MouseEvent):void {
if(mouseJoint){
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
//mouseMoveHandler
private function mouseMoveHandler(event:MouseEvent):void {
if (mouseJoint) {
var p2 : b2Vec2 = new b2Vec2(event.stageX / SCALE, event.stageY / SCALE);
mouseJoint.SetTarget(p2);
}
}
マウス操作を追加しただけですが、何か色々とイメージが膨らみ遊び心を感じると思います。
こうやって物理エンジンBox2Dを体験して、ちょこっとプログラムを追加しすだけで遊び心がわきますね!
どんどんプログラムを追加して自分なりに色々と遊びたいと思います。
package {
//インポート
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Dynamics.Joints.*;
import General.*;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**************************
* ADD CHILD = AS3
* http://www.addchild.net/
* Tatsuya Nishino
***************************/
//コンスラクタ
public class Box2D2 extends Sprite {
//インスタンスプロパティー
private const SCALE:Number = 100; // 物理エンジン内の1mを表すためのピクセル数
private var world:b2World; // 物理エンジンの管理クラス
private var body:b2Body; // 本体
private var mouseJointDef:b2MouseJointDef; // マウスジョイントの定義
private var mouseJoint:b2MouseJoint; // マウスジョイント
// メソッド
public function Box2D2() {
// 初期化
init();
createObject();
// 毎フレームの処理
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
// init
private function init():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 floorBodyDef:b2BodyDef = new b2BodyDef();
floorBodyDef.position.Set(2.5, 3); // 床の位置
floorBodyDef.angle = Math.PI / 24; //角度を指定
//物体の形の定義
var floorShapeDef:b2PolygonDef = new b2PolygonDef();
floorShapeDef.SetAsBox(3, 0.1); //物体のサイズ
floorShapeDef.friction = 0.3;
floorShapeDef.density = 0;
//物体を作る
var floor:b2Body = world.CreateBody(floorBodyDef);
floor.CreateShape(floorShapeDef);
/*************************
*DebugDraw を有効にする
**************************/
var m_sprite:Sprite = new Sprite();
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = m_sprite;
debugDraw.m_drawScale = SCALE;
debugDraw.m_fillAlpha = 0.5;
debugDraw.m_lineThickness = 1;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
world.SetDebugDraw(debugDraw);
addChild(m_sprite);
}
private function createObject():void {
/*************************
*落下物のセットアップ
**************************/
for (var i:uint = 0; i < 20; i++) {
// 物体の定義を作る (x 座標と角度はランダム)
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.position.Set((300 * Math.random()) / SCALE, 0);
bodyDef.angle = Math.PI / 2 * Math.random();
// 物体を作る
body = world.CreateBody(bodyDef);
// 形の定義を作る
var bodyShape:b2CircleDef = new b2CircleDef();
bodyShape.radius = Math.random()*0.3+0.05;
bodyShape.density = 0.5;
bodyShape.friction = 1;
bodyShape.restitution = 0.3;
// 形を物体に追加する
body.CreateShape(bodyShape);
// 重さ・重心を計算する
body.SetMassFromShapes();
}
}
//mouseDownHandler
private function mouseDownHandler(event:MouseEvent):void {
var body : b2Body = GetBodyAtMouse(event.stageX, event.stageY);
if (body) {
var md : b2MouseJointDef = new b2MouseJointDef();
md.body1 = world.m_groundBody;
md.body2 = body;
md.target.Set(event.stageX / SCALE, event.stageY / SCALE);
md.maxForce = 500.0 * body.m_mass;
md.timeStep = 1 / 24;
mouseJoint = world.CreateJoint(md) as b2MouseJoint;
body.WakeUp();
}
}
//該当オブジェクトがあるかの判定
private function GetBodyAtMouse(stageX : Number, stageY : Number) : b2Body {
// Make a small box.
var mousePVec : b2Vec2 = new b2Vec2();
var mouseXWorldPhys : Number = stageX / SCALE;
var mouseYWorldPhys : Number = stageY / SCALE;
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 = 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) {
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;
}
//mouseUphandler
private function mouseUpHandler(event:MouseEvent):void {
if(mouseJoint){
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
//mouseMoveHandler
private function mouseMoveHandler(event:MouseEvent):void {
if (mouseJoint) {
var p2 : b2Vec2 = new b2Vec2(event.stageX / SCALE, event.stageY / SCALE);
mouseJoint.SetTarget(p2);
}
}
//enterFrameHandler
private function enterFrameHandler(event:Event):void {
world.Step(1 / 24, 10);
}
}
}
- Older: Box2DFlashAS3を使ってみる[Box2D-1]
Comments:0
Trackbacks:0
- Trackback URL for this entry
- http://www.addchild.net/as3-middle/box2d-as3-middle/411.html/trackback
- Listed below are links to weblogs that reference
- Box2DFlashAS3を使ってマウス操作する[Box2D-2] from ADD CHILD = AS3