はじめに
久しぶりにCocos2d-JS + chipmunkを使ったプロトタイプを作ろうとした時に、
いろいろ忘れてたので、自分用の備忘として残しておきます。
chipmunkとは
物理演算をシュミレートするための2D物理演算のエンジン。
モンストや蹴り姫みたいなゲームが作れますというと一番伝わる気がします(笑)。
Chipmunk vs Box2D
よく話題に出るのがこの2つの物理エンジンです。
細かいことはさておき、Chipmunkの方が先にCocos2dに組み込まれたっぽい記述がありましたが、
Cocos2dの3.0以上であれば、どちらもコアライブラリに機能として組み込まれているので、どちらを使っても良さそうです。今回はchipmunk使います。
オブジェクトの作り方
1つのオブジェクトに対して、こんな流れになります。
1.sprite作る->2.body作る->3.Shape作る
1のspriteは通常のspriteと同じで、絵などを貼り付けたりなど描画する部分について。
2のbodyは位置や、動的/静的などを指定できたり、貼り付けるspriteを指定するなど。
3.のshapeはもっと細かな、形や密度、摩擦係数、反発係数などを指定し、
1~3を合体することで、1つの物理演算ルールに則ったオブジェクトを作成できます^^
shapeのいろいろ
自作ゲームの中ではbox型地のshapeしか作ったことがなかったのですが、
いろいろ用意されているようです。
cp.CircleShape(Body, 半径, オフセット)
cp.SegmentShape(Body, 始点, 終点, 線の太さ)
cp.PolyShape(Body, ポリゴンの頂点の配列, オフセット)
cp.BoxShape(Body, 幅, 高さ)
実際の書き方
何はともあれ、project.jsonで読み込んでおきます。
"modules" : ["cocos2d","chipmunk"],
物理演算を行うspaceをinitの中で作成します。
initSpace: function() {
//物理演算する空間を作る
this.space = new cp.Space();
//重力がある場合はgravityを設定する
//this.space.gravity = cp.v(0, -980);
//shapeを可視化する(デバッグ用)
this.addChild(new cc.PhysicsDebugNode(this.space));
this.scheduleUpdate();
},
次にupdateでは下記のように指定します。
update: function(dt) {
// 物理エンジンの更新
this.space.step(dt);
},
いよいよオブジェクトの作成はこのような感じ。先に説明した通りに、1.sprite作る->2.body作る->3.Shape作るの順番で作っていきます。
addTank:function(posX,posY){
// 物理スプライト
this.tankSprite = new cc.PhysicsSprite("res/tank.png");
// 質量、慣性モーメントを設定
this.weight = 100;
this.tankBody = new cp.Body(this.weight, cp.momentForBox(this.weight, this.tankSprite.getContentSize().width, this.tankSprite.getContentSize().height));
this.space.addBody(this.tankBody);
// 形状、摩擦係数、反発係数を設定
this.tankShape = new cp.BoxShape(this.tankBody, this.tankSprite.getContentSize().width, this.tankSprite.getContentSize().height);
this.tankShape.setFriction(1);//摩擦係数
this.tankShape.setElasticity(0.5); //弾性係数を設定
this.space.addShape(this.tankShape);
this.tankSprite.setBody(this.tankBody);
this.tankSprite.setPosition(posX, posY);
this.addChild(this.tankSprite);
},
このまま実行すると、重力の設定などによっては画面外に飛び出しちゃうので、
とりあえず床などを作っておきます。
createFloor: function() {
// 床を静的剛体として作る
var floorThickness = 10;
var bottomBar = new cp.SegmentShape(this.space.staticBody, cp.v(0, 50), cp.v(640,50), floorThickness);
bottomBar.setFriction(1); //摩擦係数
bottomBar.setElasticity(0.3); //弾性
this.space.addShape(bottomBar);
var topBar = new cp.SegmentShape(this.space.staticBody, cp.v(0,1100), cp.v(640,1100), floorThickness);
topBar.setFriction(1);
topBar.setElasticity(0.3);
this.space.addShape(topBar);
var leftBar = new cp.SegmentShape(this.space.staticBody, cp.v(0,1100), cp.v(0,50), floorThickness);
leftBar.setFriction(1);
leftBar.setElasticity(0.3);
this.space.addShape(leftBar);
var rightBar = new cp.SegmentShape(this.space.staticBody, cp.v(640,1100), cp.v(640,50), floorThickness);
rightBar.setFriction(1);
rightBar.setElasticity(0.3);
this.space.addShape(rightBar);
},
初速を与えたい場合..
作ったオブジェクトに対して、初速を与えたい場合は(例えば、ピンボールの玉のような感じ)下記のようにして初速を与えることができます。
this.bulletBody.applyImpulse(cp.v(this.weight * 150, 0), cp.v(0, 0)); // 右向き
this.bulletBody.applyImpulse(cp.v(0, this.weight * 1500), cp.v(0, 0)); // 上向き