お遊びゲーム開発その１１

今回は
box2dwebを使って
①物理世界の作成
②動的衝突オブジェクトの作成
③静的衝突オブジェクトの作成
④デバッグ描画
を一気にやりたいと思います。

今回のスクリーンショットです
ボールが地面に落ちて転がります
![名称未設定.png](https://qiita-image-store.s3.amazonaws.com/0/55077/852c50b9-42cf-efc4-3ce5-d189719656db.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 = .2; // はね返り係数
    fixDef.shape = new b2CircleShape(1); // 円形状
        
    // 円作成
    var wheel = world.CreateBody(bodyDef);
    wheel.CreateFixture(fixDef);
      
    // 角速度（回転速度）指定
    wheel.SetAngularVelocity(Math.PI*2);
    // 位置と角度指定 
    wheel.SetPositionAndAngle(new b2Vec2(2,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;
    fd.shape.SetAsBox(10,1); // 箱型形状
        
    // 地面作成
    var holder = world.CreateBody(bodyDef);
    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>
```


以下、解説です。

まず、Box2Dのオブジェクトは長ったらしいので
最初に略称名を変数に取得しておきます。

```
    // 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 // デバッグ描画
```

衝突オブジェクトを作成するには
BodyとFixtureが必要です。

Bodyは衝突オブジェクトの物理世界上の動きの振る舞いを決めます。
Fixtureは材質と形状を決めます。

動的ボディは物理世界上で衝突判定ありで動くオブジェクトです

```   
 bodyDef.type = b2Body.b2_dynamicBody;
```

静的ボディは物理世界上で衝突判定ありで動かないオブジェクトです

```
 bodyDef.type = b2Body.b2_staticBody;
```

BodyとFixtureができたら円と地面を物理世界上に生成します。

```
    // 円作成
    var wheel = world.CreateBody(bodyDef);
    wheel.CreateFixture(fixDef);

    ...

    // 地面作成
    var holder = world.CreateBody(bodyDef);
    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);
```

準備ができたら定期的に次の処理を呼び出すことで
物理世界上での処理が進みます

```
     world.Step(1 / 60, 10, 10); // 物理世界を更新する
     world.DrawDebugData(); // デバック描画
     world.ClearForces(); // 物理世界上の力をリセットする
```

・はね返り係数
・摩擦力
・角速度
当たりのパラメータをいじると遊べると思います

次回は複雑な形状の衝突オブジェクトをやります