Box2dWebでオブジェクトに力を加えて動かしてみる

今回もbox2dwebやります
キーでオブジェクトをいろいろ制御します。

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

![スクリーンショット 2014-10-14 0.52.38.png](https://qiita-image-store.s3.amazonaws.com/0/55077/428e36c3-8527-58f2-fd61-1682aa69e120.png)

全ソースコードです。
キー操作をするためにjQueryも使ってます。

```js:test.html
<canvas id="canvas" width="600px" height="420px" style="background-color:#333333;"></canvas>
<pre>
fキー：力をかける
iキー：衝撃を与える
vキー：一定速度を与える
tキー：瞬間移動させる
</pre>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>

<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);
      
    ////////////////////////////////////
 
    //box
    var bodyDef = new b2BodyDef;
    bodyDef.type = b2Body.b2_dynamicBody;
    bodyDef.position.Set(2,1);
    bodyDef.fixedRotation = true;
		
    var fixDef = new b2FixtureDef;
    fixDef.density = 1.0;
    fixDef.friction = 0.4;
    fixDef.restitution = .5;
		
    fixDef.shape = new b2PolygonShape;
    fixDef.shape.SetAsBox(.5,1);
		
    var box = world.CreateBody(bodyDef);
    box.CreateFixture(fixDef);
			 
    //地面
    var holderDef = new b2BodyDef;
    holderDef.type = b2Body.b2_staticBody;
    holderDef.position.Set(8, 14);
		 
    var fd = new b2FixtureDef;
    fd.shape = new b2PolygonShape;
    fd.shape.SetAsBox(8,1);
		  
    var ground = world.CreateBody(holderDef);
    ground.CreateFixture(fd);
    
    
    var keydown = 0;
    // 力
    function push(c) {
        if(c==1)	
            box.ApplyForce(new b2Vec2(0,-300),  box.GetWorldCenter());
    }
    // 衝撃
    function hit(c) {
        if(c==1)	
            box.ApplyImpulse(new b2Vec2(5,0), box.GetWorldCenter());
    }
    // 速度
    function speed(c) {
        if(c==1){
            box.SetAwake(true);
            box.SetLinearVelocity(new b2Vec2(4,0));
        }
    }
    // テレポート
    function teleport(c) {
        if(c==1){
            box.SetAwake(true);
            box.SetPositionAndAngle(new b2Vec2(10,0),Math.PI/3);
        }
    }
    $(window).keydown(function(key) {
        keydown++;
        var code = key.keyCode;
        if(code == 102 || code == 70)	push(keydown); // fキー
        if(code == 105 || code == 73)	hit(keydown); // iキー
        if(code == 118 || code == 86)	speed(keydown); // vキー
        if(code == 116 || code == 84)	teleport(keydown); // tキー
    });
    $(window).keyup(function(e) {
        keydown=0;
    });
    
   
    ////////////////////////////////////
 
 
    // デバッグ描画の設定      
    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>
```

今回はBodyが回転しないように
fixedRotationフラグをtrueにして
向きを固定します

```
    bodyDef.fixedRotation = true;
```

このフラグを入れないとボックスが転んでしまうので
アクションゲームのキャラクターとかだと必須です。

今回は次の４つの制御を行ってみます
①オブジェクトに力を加える
②オブジェクトに衝撃を加える
③オブジェクトの速度を指定する
④オブジェクトの位置、向きを指定する

①ApplyForceメソッドでオブジェクトに力を加えることが出来ます。
第１引数には力ベクトル
第２引数には力を加える位置を指定します

```
box.ApplyForce(new b2Vec2(0,-300),  box.GetWorldCenter());
```

②ApplyImpulseメソッドでオブジェクトに衝撃を加えることが出来ます。
ApplyForceメソッドと引数は同じですが、
計算式が違います。
こちらは瞬間的な力を加えます

```
box.ApplyImpulse(new b2Vec2(5,0), box.GetWorldCenter());
```

③SetLinearVelocityメソッドで平行移動速度を指定します。
力を加えている訳ではないのでスリープ状態で
判定されずにめり込んだりする場合があるので
SetAwakeでアクティブにしておいた方がよいです

```
box.SetAwake(true);
box.SetLinearVelocity(new b2Vec2(4,0));
```

④SetPositionAndAngleメソッドで位置と向きの指定が出来ます。
こちらもSetAwakeしておいた方がよいです

```
box.SetAwake(true);
box.SetPositionAndAngle(new b2Vec2(10,0),Math.PI/3);
```

次回は衝突判定の取得をやります。