「box2d.enchant.js」で、2D物理エンジンを使って遊んでみた!

1

久しぶりに「enchant.js」をいじっていたら、「リアルな動き」が欲しくなったので、物理エンジンを簡単に使えるプラグイン「box2d.enchant.js」を使ってみました。

今さらですが、めっちゃ簡単です。コレ…。

物理エンジンを使ったゲーム作りは、何だか難しいイメージがあったのですが、わりと簡単に「アングリーバード」的なデモも作れるので感心しました。

そこで、基本的な使い方を、ログ代わりにまとめておきます。


事前に準備すること!

普通に「enchant.js」で簡単なコードを書いた経験のある人なら、ほぼ同じような感覚で物理エンジンが利用できるようになっています。

そこで、まずは基本となる「HTMLファイル」と「JSファイル」の骨組みを、以下のように用意しておきます。

index.html
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>物理エンジンのサンプル</title>
<script src="js/enchant.js"></script>
<script src="js/main.js"></script>
</head>
<body>
</body>
</html>

 

main.js
1
2
3
4
5
6
7
8
9
10
enchant()

window.onload = function() {
var game = new Core();

game.onload = function() {
//ここに処理を書く
}
game.start();
}

HTMLファイルに、基本となる「enchant.js」ファイルと、メインの処理を書く「main.js」ファイルを読み込ませておきます。

「main.js」の中身は、「box2d」を使う、使わないに関わらず、最低限必要なコードの骨組みを用意しています。

上記ファイルの準備が出来たら、通常のゲーム作りはすぐに始めることができます。

ただ、今回は「box2d.enchant.js」を使って物理エンジンを利用するため、HTMLファイルにあと2つファイルを読み込ませておきましょう。

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>物理エンジンのサンプル</title>
<script src="js/enchant.js"></script>
<script src="js/Box2dWeb-2.1.a.3.js"></script>
<script src="js/box2d.enchant.js"></script>
<script src="js/main.js"></script>
</head>
<body>
</body>
</html>

追加したのは、「Box2dWeb-2.1.a.3.js」と「box2d.enchant.js」です。

どちらのファイルも、公式サイトから「enchant.js」をダウンロードすれば、解凍したフォルダの中に入っています。

(参考)
以下のフォルダ内にあるファイルです。
「libs」→「Box2dWeb-2.1.a.3.js」
「build」→「plugins」→「box2d.enchant.js」

ひとまず、ここまで準備ができたら、第1段階は突破です!


物理エンジンの使い方!

それでは、早速「enchant.js」で物理エンジンを実装してみたいと思います。

ここから先は、「main.js」の中身をいろいろ編集していきます!

 
まずは、さきほど用意した「main.js」の中にある「game.onload」内に、「物理エンジンを使うよ!」…という宣言みたいな構文を書きます。

var world = new PhysicsWorld(0, 9.8);

この引数に「0」と「9.8」を入れている理由ですが、これは「横方向の重力」と「縦方向の重力」を数値で入れているだけです。

現実の世界では「横方向」に重力は無いので「0」にしています。「縦方向」に「9.8」を指定しているのは、一般的な重力加速度が「1G=9.8m/s^2」という理由です。
(これは、「box2d.enchant.js」のドキュメントに記載されてました)

このあたりは、考えだすとキリがないので、デフォルトで(0, 9.8)を指定することを覚えておけば良いでしょう。

 
あとは、ここで作成した「world」を、「game.rootScene」へフレーム毎に組み込めばOKです。

game.rootScene.onenterframe = function() {
    world.step(game.fps);
}

たったこれだけで、enchant.jsでは物理エンジンが使えるようになるのは驚きです。

 
ひとまず、ここまでを以下にまとめておきます。これが、物理エンジンを使う時のデフォルトテンプレートになるでしょう!

main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
enchant()

window.onload = function() {
var game = new Core();

game.onload = function() {
var world = new PhysicsWorld(0, 9.8);

game.rootScene.onenterframe = function() {
world.step(game.fps);
}
}
game.start();
}

「物体」を落としてみよう!

物理エンジンを使う準備ができたので、とりあえず何か「物体」を作り、上から落として「重力」がどのように再現されているのか見ていきましょう!

まず、適当な「物体」を表示したいと思います。

通常なら、「Sprite」や「Entity」などを使うと思うのですが、物理エンジンを利用する場合はとりあえず「PhyBoxSprite()」を使えば良いでしょう。

構文は以下のとおり!

PhyBoxSprite(幅, 高さ, 動作モード, 密度, 摩擦力, 反発力, フラグ)

【幅・高さ】は、物体(四角形)のサイズを指定します。
【動作モード】は、物理エンジンの影響を「受ける」「受けない」を指定できます。
【密度】は、数値を大きくするほど、物体を重くしていきます。
【摩擦力】は、数値を小さくするほど、滑りやすくなります。
【反発力】は、数値が大きいほど、よく跳ね返ります。
【フラグ】は、【動作モード】と似ていますが、「true/false」を指定することで、物理エンジンの「影響の有無」を指定できます。

 
上記を踏まえた上で、32×32の物体を作るとこんな感じになります。

PhyBoxSprite(32, 32, enchant.box2d.DYNAMIC_SPRITE, 1.0, 0.5, 0.3, true);

(参考)
【enchant.box2d.DYNAMIC_SPRITE】は物理エンジンの影響を受ける。
【enchant.box2d.STATIC_SPRITE】は物理エンジンの影響を受けない。

 
あと、このままだと物体は上から落ちていき、画面外へ消えてしまいます。

そこで、床を設置してみたいと思います。

これも同じ要領で、以下のように作れることが分かります。

PhyBoxSprite(320, 16, enchant.box2d.STATIC_SPRITE, 0, 1.0, 0, false);

ゲーム画面のサイズが320なので「幅」も同じに指定し、物理エンジンの影響は受けなくても良いので「STATIC_SPRITE」を設定しています。

 
基本的には、これで「物体」と「床」は作成できたのですが、「色」と「座標」の指定をしないといけません。

指定方法は、以下のとおり!

var box = new PhyBoxSprite(......);
box.backgroundColor = "red";
box.position = {
    x: 160,
    y: 312
}

色の設定は、CSSと同じ感覚でOK。(#aaaとかも使えます)

あとは、作成した物体を通常通り「addChild()」してやれば完了です!

game.rootScene.addChild(box);

 
これで、「物体」と「床」が完成しました。

以下のサンプルを実際に確認してみてください!
(以下の画面内にマウスを置くと、右下に「RERUN」が表示されるので、クリックしてください)

See the Pen [sample1] enchant.js with box2d by webStudy (@webstudy) on CodePen.

赤色の四角形に重力が働いて、落下していくのを確認できるかと思います。


クラスを作ってみよう!

さて、いい感じに物体が落下してくれました。

しかし、この物体を10個、20個…と、たくさん表示したいと思った時に、いちいち「new PhyBoxSprite…」を何度も繰り返すのは面倒です。

関数を作っても良いのですが、「enchant.js」に標準で搭載されている「クラス作成機能」を使うと、簡単に複数の物体を表示できるようになります。

例えば、「PhyBoxSprite」のクラスは、以下のような感じで作れます!

var Box = Class.create(PhyBoxSprite, {
    initialize: function() {
        //ここに初期化処理を書く
    }
}

「initialize」の初期化処理に、物体の生成処理、座標位置、カラー、addChild…など、基本的なコードを書いておきます。

これで、「Box」という物体を持ったクラスが作られたことになります。

(参考)
クラスの変数名は、最初が大文字になるようにしておきましょう。

 
あとは、メインの処理に以下のコードを書くだけで、物体が表示されるようになります。

var box = new Box();

 
これだと、「for文」などと組み合わせて、物体を複数表示させるようなことも簡単になります。

for(var i=0; i<20; i++) {
    var box = new Box();
}

 
以下のサンプルは、上記内容を踏まえて「物体」をいくつか表示させたモノです。
(画面内にマウスを置くと、右下に「RERUN」が表示されるので、クリックしてください)

See the Pen [sample2] enchant.js with box2d by webStudy (@webstudy) on CodePen.

 
上記サンプルの「Box」クラスは、以下のようなカタチです。

main.js
1
2
3
4
5
6
7
8
9
var Box = Class.create(PhyBoxSprite, {
initialize: function(x, y) {
PhyBoxSprite.call(this, 16, 16, enchant.box2d.DYNAMIC\_SPRITE, 1.5, 1.0, 0.3, true);
this.backgroundColor = "red";
this.x = x;
this.y = y;
game.rootScene.addChild(this);
}
});

初期化処理で、「物体の生成」「赤色の設定」「出現位置」「addChild()」を行っています。

少し変化があるとすれば、「function(x, y)」というカタチで、引数に2つの数値を設定している点です。

この「x, y」を、そのまま座標位置の「x, y」に入れてやることで、物体の出現位置を操作できます。

for(var i=0; i < 320; i+=32) {
    var box = new Box(i, i);
}

このサンプルでは、「x, y」にfor文の「i」を入れて複数の物体を表示してみました。


物体に「力」を加えてみよう!

せっかく物理エンジンを使っているので、物体をクリックして横方向へ勢いよく飛ばしてみましょう!

と言っても、実現するのは簡単で、以下の構文を覚えればOKです!

applyImpulse(new b2Vec2(横方向の力, 縦方向の力))

「b2Vec2」というのは「ベクトル」の意味で、物理エンジンの世界ではこのベクトルをベースにした数値を使わないと、上手く計算できないようになっています。

(参考)
enchant.box2d.PhySprite」ドキュメント

 
あとは、生成したBoxに組み込むだけで使えるようになります。

1
2
var box = new Box();
box.applyImpulse(new b2Vec2(3, -2));

これで、右方向へ放物線を描くように飛んでいきます。

 
この新しい構文を「Box」に組み込んだサンプルが以下になります!

赤いBoxを、クリック(タッチ)すると横方向へ飛んでいくのが分かります。
(画面内にマウスを置くと、右下に「RERUN」が表示されるので、クリックしてください)

See the Pen [sample3] enchant.js with box2d by webStudy (@webstudy) on CodePen.

上記サンプルでは、Boxクラスの中へ「クリックイベント」も一緒に入れてみました。

こうすると、メインの処理がスッキリするので、扱いやすくなります。
(言い換えれば、クリックされると飛んでいく物体が作れるクラス…という感じでしょうか)


スプライトを利用してみる!

さて、そろそろ無機質な四角形の物体にも飽きてきたので、スプライト画像を適用してゲームっぽくしてみましょう。

画像は、通常のenchant.jsと同じように、「preload()」であらかじめ画像ファイルを読み込んでおく必要があります。

var game = new Core();
game.preload(
    画像ファイルパス,
    画像ファイルパス,
    画像ファイルパス
);

 
今回は、「enchant.js」で用意されている画像を使ってみたいと思います。

使うのは、以下の画像ファイルです。

2

 
読み込んだ画像ファイルを適用するには、「image」に画像パスを割り当てて、画像フレームを指定すればOKです!

var box = new PhyBoxSprite(16, 16, ......);
box.image = game.assets["画像パス"];
box.frame = 画像フレーム

これだけで、画像を使えます。

注意点として、「PhyBoxSprite」の幅と高さは、使用する画像のサイズに合わせることを覚えておきましょう。

「画像フレーム」は、自分が使いたい画像が何番目にあるかを指定すればOKです。例えば、「豚キャラ」は0から数えて22番目にあるので、「22」を指定するわけです。

 
四角形を「豚キャラ」にして、床の画像も差し替えたのが以下のサンプルです!
(画面内にマウスを置くと、右下に「RERUN」が表示されるので、クリックしてください)

See the Pen [sample4] enchant.js with box2d by webStudy (@webstudy) on CodePen.

上記サンプルでは、「床」もクラス化しています。

そして、画像の適用もクラス内で行うことで、メイン処理を見やすくしています。

(参考)
画像ファイルは、「png」で透過処理を施しておけば、自動的にその部分が透明に処理されるので便利です。

 

最後に…

これまで紹介してきたノウハウを使って、最後に障害物となる壁を表示してみたいと思います。

完成品はコチラ!
(画面内にマウスを置くと、右下に「RERUN」が表示されるので、クリックしてください)

See the Pen [Final] enchant.js with box2d by webStudy (@webstudy) on CodePen.

上記サンプルでは、「豚キャラ」をクリック(タッチ)すると障害物に向かって飛んでいき、壁を破壊していきます。

障害物も、他の物体と同様に「PhyBoxSprite」で作っているだけなので、それほど難しくはないと思います。

豚キャラは、転がっていくようにするため「PhyCircleSprite」を使って、円形の物体にしています。


まとめ

「enchant.js」を使っての物理エンジンは、いかがだったでしょうか?

基本的な部分しか紹介できてませんが、これだけでも「アングリーバード」風のゲームが作れそうな気がするかと思います。

もし、物理エンジンに興味があって、面白いゲームを作りたい方は、ぜひ参考にしてみてください!

(参考)
enchant.js」公式サイト
box2d.enchant.js」ドキュメント


最新情報をチェック!

一緒によく読まれている記事

キーワード Keyword