Box2Dの導入ログ
ということで、別の物理エンジンとしてBox2Dをさわってみることにした。
導入
Box2DFlashAS3 download | SourceForge.netのDownloadから、下の〜.zipを選んで解凍。
いつものごとく「flex_sdk_2\frameworks\source」に「Box2D」のフォルダをコピー。
付属のサンプルは「General」フォルダとかも必要そうなので、それとは別にBox2DFlashAS3 の単純なサンプルと使い方 - てっく煮ブログ 跡地を参考にサンプル作成。
ひとまず、床と球は作れたが、球が跳ねないのと、まだ意味(必要性)がわかってない変数(m_physScale)があるので、もう少し調査することにする。
コード
参考にさせてもらったサンプルを半分くらい流用。Box2D内のサンプルの円の描画が独特だったのは、描画の高速化と関連するんだろうか。
このサンプルだと球が跳ねないが、アクションゲームに使う場合はむしろ跳ねない方がうれしい。
package { import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import flash.events.Event import flash.display.*; import flash.text.TextField; [SWF(backgroundColor="#ffffff", width="350", height="200")] public class Main extends Sprite { private var m_world:b2World; private var m_physScale:Number = 10; public function Main() { stage.scaleMode = "noScale"; stage.align = "TL"; {//Init Box2D {//Common //AABB var worldAABB:b2AABB = new b2AABB(); worldAABB.minVertex.Set(-100.0, -100.0); worldAABB.maxVertex.Set(100.0, 100.0); //Gravity var gravity:b2Vec2 = new b2Vec2(0.0, 10.0); //World m_world = new b2World(worldAABB, gravity, true); } {//Floor //Shape var wallSd:b2BoxDef = new b2BoxDef(); { wallSd.extents.Set(300 / m_physScale / 2, 10 / m_physScale); // wallSd.localRotation = Math.random() * Math.PI / 8; wallSd.restitution = 0.5; } //Body var wallBd:b2BodyDef = new b2BodyDef(); { wallBd.position.Set(300 / m_physScale / 2, 250 / m_physScale); wallBd.AddShape(wallSd); } //Create m_world.CreateBody(wallBd); } {//Sphere //Shape var ballSd:b2CircleDef = new b2CircleDef(); { ballSd.radius = 30 / m_physScale; // ballSd.localRotation = Math.random() * Math.PI / 8; ballSd.density = 1; ballSd.friction = 0.2; ballSd.restitution = 0.8; } //Body var ballBd:b2BodyDef = new b2BodyDef(); { ballBd.position.Set(300 / m_physScale / 2, 20 / m_physScale); ballBd.AddShape(ballSd); } //Create m_world.CreateBody(ballBd); } } addEventListener("enterFrame", function(event:Event):void { Update(); }); } public function Update():void { if(!m_world) { return; } m_world.Step(1 / 30, 10); // Render graphics.clear(); for (var bb:b2Body = m_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 { //box if(shape.m_type == b2Shape.e_polyShape) { var drawBox:Function = function():void{ var poly:b2PolyShape = shape as b2PolyShape; var tV:b2Vec2 = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i])); graphics.beginFill(0x999999, 1); graphics.lineStyle(1,0xffffff,1); graphics.moveTo(tV.x * m_physScale, tV.y * m_physScale); for (var i:int = 0; i < poly.m_vertexCount; ++i) { var v:b2Vec2 = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i])); graphics.lineTo(v.x * m_physScale, v.y * m_physScale); } graphics.lineTo(tV.x * m_physScale, tV.y * m_physScale); graphics.endFill(); }; drawBox(); } //circle if(shape.m_type == b2Shape.e_circleShape) { var drawCircle:Function = function():void{ var circle:b2CircleShape = shape as b2CircleShape; var pos:b2Vec2 = circle.m_position; var r:Number = circle.m_radius; graphics.beginFill(0x999999, 1); graphics.lineStyle(1,0xaaaaaa,1); graphics.drawCircle(pos.x * m_physScale, pos.y * m_physScale, r * m_physScale); graphics.endFill(); }; drawCircle(); } } } }