Box2D 2.1a触ってみた


久しぶりにBox2Dでも触ろうと思ったらバージョンが2.1aに。
2.0.2から結構変わってたので備忘録として。

とりあえずこの記事と同じものを2.1aで作ってみました。
2.1aからPlayer9と10でわかれたっぽい。ライブラリはこちらから。
今回はPlayer9の方で作りました。

ご覧になるには最新のFlashPlayerが必要です。

2.0.2と見比べながら。まずは2.0.2ではあったb2AABBクラスが不要に。
b2Worldのコンストラクタの第一引数にいれてたけどそれもなくなりました。

//2.0.2
var worldAABB : b2AABB = new b2AABB();
worldAABB.lowerBound.Set( -100, -100);
worldAABB.upperBound.Set(100, 100);

var world : b2World = new b2World(worldAABB, gravity, true);

//2.1a
var world : b2World = new b2World(gravity, true);

2.1aで重要になってくるのがb2FixtureDefクラス。ドキュメントには

A fixture definition is used to create a fixture. This class defines an abstract fixture definition. You can reuse fixture definitions safely.

と書いてある。fixtureは【固定具・固定】とかいう意味。このクラスは再利用できて固定具の定義に使うよって意味であってるかな。
上のFlashでいう固定具ってのは壁とかCircleとかBoxとかのオブジェクト。

また、b2Bodyクラスも再利用する。

A body definition holds all the data needed to construct a rigid body. You can safely re-use body definitions.

rigid bodyもここでいう壁やCircleなどのオブジェクトととらえていいと思う。そういうオブジェクト全てを管理する。

例えばCircleを一つ定義するとなるとこんな感じ。

//2.0.2
var circleBodyDef:b2BodyDef = new b2BodyDef();
circleBodyDef.position.Set(100 / m_physScale, 20 / m_physScale);

var circleShapeDef:b2CircleDef = new b2CircleDef();
circleShapeDef.radius = 50 / m_phyScale ;
circleShapeDef.density = 1;             //密度
circleShapeDef.friction = 0.2;          //摩擦
circleShapeDef.restitution = 0.1;     //反発係数

var circleBody:b2Body = world.CreateBody(circleBodyDef);
circleBody.CreateShape(circleShapeDef);
circleBody.SetMassFromShapes();

//2.1a
var bodyDef : b2BodyDef = new b2BodyDef();
var fixtureDef : b2FixtureDef = new b2FixtureDef();
var circleDef : b2CircleShape = new b2CircleShape();
fixtureDef.density = 1;
fixtureDef.friction = 0.2;
fixtureDef.restitution = 0.1;
fixtureDef.shape = circleDef;
bodyDef.type = b2Body.b2_dynamicBody;

circleDef.SetRadius(radius / m_physScale);
bodyDef.position.Set(100 / m_physScale, 20 / m_physScale);
var circleBody : b2Body = world.CreateBody(bodyDef);
circleBody.CreateFixture(fixtureDef);

b2FixtureDefインスタンスとb2Bodyインスタンスは再利用ができる。最後にソース全部のっけるのでそこ参照。
またここでいうCircleやBoxなど動かしたいものはb2BodyDefインスタンスのtypeプロパティにb2Body.b2_dynamicBodyを代入する。
uint型なので2を代入してもいい。静的なものはb2_staticBodyか0、kinematicはb2_kinematicBodyか1。
dynamicBodyを代入したあと静的なものを作る場合はちゃんとstaticBodyを代入するのを忘れずに。

あとb2DebugDrawのm_fillAlphaやm_drawScaleプロパティが全てメソッド定義に変わっている。

//2.0.2
var m_sprite : Sprite = new Sprite();
addChild(m_sprite);
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_fillAlpha = 0.3;
debugDraw.m_drawScale = m_physScale;
debugDraw.m_lineThickness = 1;
debugDraw.m_sprite = m_sprite;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
world.SetDebugDraw(debugDraw);

//2.1a
var m_sprite : Sprite = new Sprite();
addChild(m_sprite);
var debugDraw : b2DebugDraw = new b2DebugDraw();
debugDraw.SetFillAlpha(0.3);
debugDraw.SetDrawScale(m_physScale);
debugDraw.SetLineThickness(1);
debugDraw.SetSprite(m_sprite);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
world.SetDebugDraw(debugDraw);

以下全ソースです。ちょっと触ってみただけなので間違いなどあれば指摘ください

package
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2FixtureDef;
	import Box2D.Dynamics.b2World;

	import fl.controls.Button;

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	/**
	 * @author laqu
	 */
	public class Index extends Sprite
	{
		const WIDTH : uint = 400;
		const HEIGHT : uint = 300;
		const OBJ_NUM : uint = 20;

		private var _world : b2World;
		private var _fixtureDef : b2FixtureDef;
		private var _m_physScale : uint = 100;
		private var _m_sprite : Sprite;
		private var _m_iterations : int = 10;
		private var _m_timeStep : Number = 1 / 30;
		private var _m_positionIterations : uint = 10;
		private var _objArr : Array = [];
		private var _btn:Button;

		public function Index()
		{
			init();
		}

		private function init() : void
		{
			var i : uint;
			var gravity : b2Vec2 = new b2Vec2(0, 10);

			_world = new b2World(gravity, true);
			_fixtureDef = new b2FixtureDef();

			var bodyDef : b2BodyDef = new b2BodyDef();

			//壁・上下左右
			var wallBody : b2Body;
			var wallDef : b2PolygonShape = new b2PolygonShape();
			var wallWidth : Array = [WIDTH / 2,5];
			var wallHeight : Array = [5,HEIGHT / 2];
			var wallX : Array = [WIDTH / 2,0 ,WIDTH / 2,WIDTH];
			var wallY : Array = [0,HEIGHT / 2,HEIGHT,HEIGHT / 2];
			_fixtureDef.density = 1;
			_fixtureDef.friction = 1;
			_fixtureDef.shape = wallDef;

			for(i = 0;i < 4;i++)
			{
				bodyDef.position.Set(wallX[i] / _m_physScale, wallY[i] / _m_physScale);
				wallDef.SetAsBox(wallWidth[i % 2] / _m_physScale, wallHeight[i % 2] / _m_physScale);
				wallBody = _world.CreateBody(bodyDef);
				wallBody.CreateFixture(_fixtureDef);
			}

			//Circle
			var circleDef : b2CircleShape = new b2CircleShape();
			_fixtureDef.friction = 10;
			_fixtureDef.density = 10;
			_fixtureDef.restitution = 0.9;
			_fixtureDef.shape = circleDef;
			bodyDef.type = b2Body.b2_dynamicBody;

			for(i = 0;i < OBJ_NUM;i++)
			{
				var radius : uint = Math.random() * 20 + 10;
				circleDef.SetRadius(radius / _m_physScale);
				bodyDef.position.Set(Math.random() * WIDTH / _m_physScale, Math.random() * HEIGHT / _m_physScale);
				var circleBody : b2Body = _world.CreateBody(bodyDef);
				circleBody.CreateFixture(_fixtureDef);
				_objArr.push(circleBody);
			}

			//Box
			var boxDef : b2PolygonShape = new b2PolygonShape();
			_fixtureDef.friction = 1;
			_fixtureDef.density = 1;
			_fixtureDef.restitution = 0.1;
			_fixtureDef.shape = boxDef;
			bodyDef.type = b2Body.b2_dynamicBody;

			for(i = 0;i < OBJ_NUM;i++)
			{
				var boxWidth : uint = Math.random() * 20 + 5;
				var boxHeight : uint = Math.random() * 20 + 5;
				boxDef.SetAsBox(boxWidth / _m_physScale, boxHeight / _m_physScale);
				bodyDef.position.Set(Math.random() * WIDTH / _m_physScale,Math.random() * HEIGHT / _m_physScale);
				var boxBody:b2Body = _world.CreateBody(bodyDef);
				boxBody.CreateFixture(_fixtureDef);
				_objArr.push(boxBody);
			}

			//DebugDraw
			_m_sprite = new Sprite();
			addChild(_m_sprite);

			var debugDraw : b2DebugDraw = new b2DebugDraw();
			debugDraw.SetSprite(_m_sprite);
			debugDraw.SetFillAlpha(0.3);
			debugDraw.SetDrawScale(_m_physScale);
			debugDraw.SetLineThickness(1);
			debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
			_world.SetDebugDraw(debugDraw);

			addEventListener(Event.ENTER_FRAME, update);

			//Btn
			_btn = new Button();
			_btn.label = "Button";
			_btn.x = _btn.y = 20;
			_btn.addEventListener(MouseEvent.CLICK, btnClick);
			addChild(_btn);
		}

		//ボタンをクリックしたら上方向に力を加える
		private function btnClick(e : MouseEvent) : void
		{
			for(var  i : uint = 0;i < OBJ_NUM*2;i++)
			{
				var body:b2Body = _objArr[i] as b2Body;
				body.SetLinearVelocity(new b2Vec2(0,-Math.random()*10));
				//SetAwakeしないと全てのオブジェクトが静止した場合に動かない
				body.SetAwake(true);
			}
		}

		//レンダリング
		private function update(e : Event) : void
		{
			_world.Step(_m_timeStep, _m_iterations, _m_positionIterations);
			_world.ClearForces();
			_world.DrawDebugData();
		}
	}
}

Tags: , ,

Similar Posts

Leave a Reply