PhysicsJSを試してみる


PhysicsJSはJavaScriptで実装された物理エンジンライブラリです。
公式ページは
http://wellcaffeinated.net/PhysicsJS/
にあります。
GitHubはここ
https://github.com/wellcaffeinated/PhysicsJS

あんまり日本語の情報がないっぽいので、
ちょといじったときのメモをのせておきます。

# PhysicsJSを取ってくる

とりあえず

```shell-session:
$ bower install PhysicsJS
```

でとってくる

http://wellcaffeinated.net/PhysicsJS/installation
にはrequireJSうんぬんとかいてあるけど、とりあえずつかわないでやってみる



# とりあえず円を書く

Canvasを使うので、
RendererにCanvasを指定してあげて、
幅と高さと追加する要素のスタイルを指定してRendererをつくります。
作ったRendererはworldにaddします。
あとは実際のObjectをくわえてあげればよいので、
今回はcircleを加えて上げます。
これで円が描画できます。


````index.html
<html>
<body>
<script type="text/javascript" src="./bower_components/PhysicsJS/dist/physicsjs-full-0.6.0.min.js"></script>
<script type="text/javascript">
Physics(function(world) {
    var viewWidth = 500;
    var viewHeight = 300;
    //描画のためのRenderer追加
    var renderer = Physics.renderer('canvas', {
        width: viewWidth,
        height: viewHeight,
        styles: {
            'circle' : {
                srrokeStyle : '#00FF00',
                lineWidth: 1,
                fillStyle: '#FF0000',
                angleIndicator: '#0000FF'
            }
        }
    });
    world.add(renderer);

    //円を追加してあげる
    world.add(
        Physics.body('circle', {
            x: 50,
            y: 50,
            radius: 20
        })
    );
    world.render();        
});
</script>
</body>
</html>
````

![PhysicsJS.png](https://qiita-image-store.s3.amazonaws.com/0/4044/fba14139-a5a5-98c9-aebe-fdd884e76097.png "PhysicsJS.png")


# 円を動かす

tickerを動かして円を動かしてみます。

circleには速度vx,vyを指定してあげます。
あとはtickerを動かします。

```js:
    Physics.util.ticker.on(function(time, dt) {
        world.step(time);
    });
    Physics.util.ticker.start();
```

でtickerが動くのと時間が進むごとにstepイベントが発生するので、
stepイベント毎にrender()を呼んで描画してあげればよいです。


```test.js
Physics(function(world) {
    var viewWidth = 500;
    var viewHeight = 300;
    var renderer = Physics.renderer('canvas', {
        width: viewWidth,
        height: viewHeight,
        styles: {
            'circle' : {
                srrokeStyle : '#00FF00',
                lineWidth: 1,
                fillStyle: '#FF0000',
                angleIndicator: '#0000FF'
            }
        }
    });
    world.add(renderer);

    world.add(
        Physics.body('circle', {
            x: 50,
            y: 50,
            vx: 0.2,
            vy: 0.2,
            radius: 20
        })
    );

    world.on('step', function() {
        world.render();        
    });

    Physics.util.ticker.on(function(time, dt) {
        world.step(time);
    });
    Physics.util.ticker.start();

});
```

# 振る舞いを指定する
Physics.behavior()で振る舞いが指定できるので、
指定してあげます。

今回は
等加速度をあたえる constant-acceleration
境界での衝突を検出する edge-collision-detection
衝突したら反発する body-impulse-response
を与えてみます。

```test.js
Physics(function(world) {
    var viewWidth = 500;
    var viewHeight = 300;
    var renderer = Physics.renderer('canvas', {
        width: viewWidth,
        height: viewHeight,
        styles: {
            'circle' : {
                srrokeStyle : '#00FF00',
                lineWidth: 1,
                fillStyle: '#FF0000',
                angleIndicator: '#0000FF'
            }
        }
    });
    world.add(renderer);

    world.add(
        Physics.body('circle', {
            x: 50,
            y: 50,
            vx: 0.2,
            vy: 0.2,
            radius: 20
        })
    );

    //重力加速度を与える
    world.add(Physics.behavior('constant-acceleration'));

    //境界を加えてそれを検出
    var viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight);
    world.add(Physics.behavior('edge-collision-detection', {
        aabb: viewportBounds,
        restitution: 0.99,
        cof: 0.99
    }));

    //衝突したら反発
    world.add(Physics.behavior('body-impulse-response'));

    world.on('step', function() {
        world.render();
    });

    Physics.util.ticker.on(function(time, dt) {
        world.step(time);
    });
    Physics.util.ticker.start();
});
```

実際に動かしてみるとcanvasの境界にぶつかるとバウンドする円が描画されます。


# API
APIは
http://wellcaffeinated.net/PhysicsJS/docs/
にあるので、
いろんなbody(rectangleとかconvex-polygonとか)を追加してみたり、
いろんなbehaviorを指定したりして遊んでみたいと思います。