Murayama blog.

AIの民主化。

Box2D始めました。


ASのライブラリ、Box2Dが面白いです。

Box2Dとは,複雑な物理計算を一手に引き受けてくれるライブラリです。こういったライブラリは物理エンジンと呼ばれています。


僕もまだ触ってみて1時間程度なんで、細かいことは全然です。
とりあえず技評さんのサイトの連載を参考にちょろっと遊んでみました。


それで作ったのがこちら。
マウスでクリックすると、箱が落ちてきます。
#ほとんどサンプルのままですけど。。


箱が全部落ちたあなたはラッキーだ。たぶん。



Box2Dは衝突(跳ね返り)とか落下とか上手いことやってくれるみたいですね。
もうちょっと使いこなせれば、面白い何かが作れそう、な気がする。


コードはこちら。

package
{
  import Box2D.Collision.Shapes.b2PolygonDef;
  import Box2D.Collision.b2AABB;
  import Box2D.Common.Math.b2Vec2;
  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;
  
  public class HelloBox2D extends Sprite
  {
    private var world:b2World;
    
    public function HelloBox2D()
    {
      init();
    }
    
    private function init():void
    {
      stage.addEventListener(MouseEvent.CLICK, onClick_stage);
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
 
    private function onClick_stage(evt:MouseEvent):void
    {
      // 物理エンジンの影響範囲 縦横200メートルになる ----------------
      var worldAABB:b2AABB = new b2AABB();
      worldAABB.lowerBound.Set(-100, -100);
      worldAABB.upperBound.Set(100, 100)
 
      // 重力の指定 (X=0, Y=10) 9.81 ----------------
      var gravity:b2Vec2 = new b2Vec2(0, 10);
 
      // 物理エンジン全体のセットアップ ----------------
      world = new b2World(worldAABB, gravity, true);
 
      // 床の設定 ----------------
      var floorBodyDef:b2BodyDef = new b2BodyDef();
      floorBodyDef.position.Set(2.5, 3);
      
      var floorShapeDef:b2PolygonDef = new b2PolygonDef();
      floorShapeDef.SetAsBox(2, 0.1);
      
      var floor:b2Body = world.CreateBody(floorBodyDef);
      floor.CreateShape(floorShapeDef);
 
      // 箱の設定 ----------------
      var boxBodyDef:b2BodyDef = new b2BodyDef();
      boxBodyDef.position.Set(1.5, 1);
      
      var boxShapeDef:b2PolygonDef = new b2PolygonDef();
      boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), Math.random());
      boxShapeDef.density = 1;
      boxShapeDef.restitution = Math.random();
      
      var box:b2Body = world.CreateBody(boxBodyDef);
      box.CreateShape(boxShapeDef);
      box.SetMassFromShapes();
 
      // 箱の設定2 ----------------
      var boxBodyDef2:b2BodyDef = new b2BodyDef();
      boxBodyDef2.position.Set(2.5, 1);
      
      var boxShapeDef2:b2PolygonDef = new b2PolygonDef();
      boxShapeDef2.SetAsOrientedBox(0.2, 0.2, new b2Vec2(0, 0), Math.random());
      boxShapeDef2.density = 1;
      boxShapeDef2.restitution = Math.random();
      
      var box2:b2Body = world.CreateBody(boxBodyDef2);
      box2.CreateShape(boxShapeDef2);
      box2.SetMassFromShapes();
 
      // 箱の設定3 ----------------
      var boxBodyDef3:b2BodyDef = new b2BodyDef();
      boxBodyDef3.position.Set(3.5, 1);
      
      var boxShapeDef3:b2PolygonDef = new b2PolygonDef();
      boxShapeDef3.SetAsOrientedBox(0.2, 0.2, new b2Vec2(0, 0), Math.random());
      boxShapeDef3.density = 1;
      boxShapeDef3.restitution = Math.random();
 
      var box3:b2Body = world.CreateBody(boxBodyDef3);
      box3.CreateShape(boxShapeDef3);
      box3.SetMassFromShapes();
      
      // 画面描画の設定
      var debugDraw:b2DebugDraw = new b2DebugDraw();
      debugDraw.m_sprite = this;
      debugDraw.m_drawScale = 100;
      debugDraw.m_fillAlpha = 0.3;
      debugDraw.m_lineThickness = 1;
      debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
      world.SetDebugDraw(debugDraw);
    }
 
    private function onEnterFrame(evt:Event):void
    {
      if (world == null) {
        return;
      }
      world.Step(1 / 24, 10);
    }
  }
}