Box2dWebで複雑な衝突オブジェクトを作成してみる

今回は複雑な衝突オブジェクトを作成します
といっても簡単です。
・Fixtureを作成する
・Bodyに複数のFixtureを追加していく
これだけです

今回のスクリーンショットです。

![a.png](https://qiita-image-store.s3.amazonaws.com/0/55077/6bb9a2cd-ca5a-2d5b-d113-0d21a1ea379b.png)

今回の全ソースコードです。

```js:test.html
<canvas id="canvas" width="600px" height="420px" style="background-color:#333333;"></canvas>

<script type="text/javascript" src="Box2dWeb-2.1.a.3.min.js"></script>
<script type="text/javascript">
      
    // Box2Dオブジェクトを取得
    var b2Vec2 = Box2D.Common.Math.b2Vec2 // 2Dベクトル
     ,  b2BodyDef = Box2D.Dynamics.b2BodyDef // Body定義
     ,  b2Body = Box2D.Dynamics.b2Body // Body
     ,  b2FixtureDef = Box2D.Dynamics.b2FixtureDef // Fixture定義
     ,  b2Fixture = Box2D.Dynamics.b2Fixture // Fixture
     ,  b2World = Box2D.Dynamics.b2World // 物理世界
     ,  b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape // 衝突オブジェクトの形状（ポリゴン）
     ,  b2CircleShape = Box2D.Collision.Shapes.b2CircleShape  // 衝突オブジェクトの形状（円）
     ,  b2DebugDraw = Box2D.Dynamics.b2DebugDraw // デバッグ描画
 
 
    // 世界を作る
    var world = new b2World(new b2Vec2(0,10), true);
      
    // 動的衝突オブジェクト生成      
    var bodyDef = new b2BodyDef;
    bodyDef.type = b2Body.b2_dynamicBody;
    bodyDef.position.Set(4,8);
    bodyDef.userData = 'obj';
      
    // 材質と形状
    var fixDef = new b2FixtureDef;
    fixDef.density = 10.0;
    fixDef.friction = .9;
    fixDef.restitution = .4; 
    fixDef.shape = new b2CircleShape(1); // 円形状

    // 円
    var wheel = world.CreateBody(bodyDef);
    wheel.CreateFixture(fixDef);
    fixDef.shape.m_p.Set(0,1);
    wheel.CreateFixture(fixDef);

      
    // 角速度（回転速度）指定
    wheel.SetAngularVelocity(Math.PI*2);
    // 位置と角度指定 
    wheel.SetPositionAndAngle(new b2Vec2(15,-3),-20*(Math.PI/180));
 
    // 静的衝突オブジェクト
    var bodyDef = new b2BodyDef;
    bodyDef.type = b2Body.b2_staticBody;
    bodyDef.position.Set(10,12);
      
    // 材質と形状
    var fd = new b2FixtureDef;
    fd.shape = new b2PolygonShape;
        
    // 地面
    var holder = world.CreateBody(bodyDef);
  
 
    fd.shape.SetAsBox(10, 1);
    holder.CreateFixture(fd);
    fd.shape.SetAsOrientedBox(1, 10,new b2Vec2(5,0),Math.PI/6);
    holder.CreateFixture(fd);
 
    // デバッグ描画の設定      
    var debugDraw = new b2DebugDraw();
    debugDraw.SetSprite ( document.getElementById ("canvas").getContext ("2d"));
    debugDraw.SetDrawScale(30);     //描画スケール
    debugDraw.SetFillAlpha(0.3);    //半透明値
    debugDraw.SetLineThickness(1.0);//線の太さ
    debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);// 何をデバッグ描画するか
    world.SetDebugDraw(debugDraw);
      
    window.setInterval(update,1000/60);
      
    function update() {
        world.Step(1 / 60, 10, 10); // 物理世界を更新する
        world.DrawDebugData(); // デバック描画
        world.ClearForces(); // 物理世界上の力をリセットする
    };
      
</script>
```

形状に関しては下記のオブジェクトが用意されています
・b2CircleShape（円）
・b2PolygonShape（多角形）
・b2EdgeShape（線分）
これらの基本形状を組み合わせることで複雑な衝突オブジェクトを作成できます

形状を組み合わせるには
次のように１つのBodyに対し、複数のFixtureを生成します。

```
    // 円
    var wheel = world.CreateBody(bodyDef);
    wheel.CreateFixture(fixDef);
    fixDef.shape.m_p.Set(0,1);
    wheel.CreateFixture(fixDef);
```

今回のキモです
m_p.Setメソッドで中心位置をずらしてBodyに２つめの円を登録します
余談ですが、左上が原点で右方向がx軸のプラス方向で下方向がy軸のプラス方向であることに注意してください
（y軸が上下逆です）
また、１つのBodyに対して、はね返り係数や摩擦力が異なるFixtureを追加することも可能です。

```
b2CircleShape.shape.m_p.Set(中心からズラすxの値、中心からズラすyの値)
```

多角形のb2PolygonShapeは１つずつ頂点を定義するやりかたもあるのですが
四角形であれば、SetAsBox関数やSetAsOrientedBox関数で簡単に生成することができます。

```
    fd.shape.SetAsBox(10, 1);
    holder.CreateFixture(fd);
    fd.shape.SetAsOrientedBox(1, 10,new b2Vec2(5,0),Math.PI/6);
    holder.CreateFixture(fd);
```

SetAsOrientedBoxを使えば
四角形の中心位置や向きをずらせます

```
b2PolygonShape.shape.SetAsOrientedBox(幅,高さ,中心位置,回転角度)
```

次回からは衝突オブジェクト同士を関連づけるジョイントをやります
ジョイントを使うことでより複雑な動作を衝突オブジェクトに持たせることができます