box2d.jsというJavaScriptライブラリを使うと物理的な動きが短く記述できる

Box2Dというライブラリがあり、最初はC++専用のライブラリだったのだが、最近はActionScript向けやJavaに移植されており、あまり更新はされていないがJavaScript向けのものもある。
Box2Dは物理エンジンと呼ばれており、物理的な計算を勝手にしてくれるので物体が床に落ちるなどの物理的な動きを完結にコード化することが出来る。
わたしは単純にサンプルが面白そうだったこととJavaScriptで使えるのでiPhoneで動くゲームが作れたら面白そうだと思い使ってみた。

動作確認のみだがiPhoneでも動作した。
左マウスクリックで、ランダムな大きさの円オブジェクトが生成され、右マウスクリックで四角い落下しないオブジェクトが生成される。


これで何かゲームが作れると面白い。
HTML部分はcanvasタグが記述されいるだけでシンプルだ。
box2d.jsとcanvasとの組み合わせで何か出来ないだろうかと考えている。
今後バージョンアップして何か作ってみようと思う。
【ソースコード】

<!DOCTYPE html>
<html>
<head>
<!--
Box2D/床に四角と丸のオブジェクトを落とす
Ver 0.8/オブジェクト作成を関数化した create_shapes2.js 傾き(angle)追加
オブジェクトを傾けてみた
イベント処理をつけた(クリックするとボックスが出現)
-->
<title>Box2D/床に四角と丸のオブジェクトを落とす Ver 0.8</title>
<meta charset="utf-8">
<meta name="viewport" content="width=320,user-scalable=no">
<link rel="stylesheet" type="text/css" href="reset.css">
<!-- Box2D 読み込み -->
<script src="prototype-1.6.0.2.js"></script>
<script src="box2d.js"></script>
<!-- /Box2D 読み込み -->
<!-- Box2D を利用する上で使いやすくする関数を読み込み -->
<script src="draw_world.js"></script>
<script src="create_shapes2.js"></script>
<!-- /Box2D を利用する上で使いやすくする関数を読み込み -->
<script>
(function(){
var title = "Box2D/床に四角と丸のオブジェクトを落とす Ver 0.8";
var config = {
width: 320,
height: 480,
top: 0,
left: 0
};
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width = config.width;
canvas.height = config.height;
canvas.top = config.top;
canvas.left = config.left;
canvas.style.backgroundColor = "#777";
var ctx = canvas.getContext("2d");
ctx.font = "16px メイリオ";
/* Create a world */
var worldAABB = new b2AABB();   // この辺はお約束
worldAABB.minVertex.Set(-1000, -1000);    // この辺はお約束
worldAABB.maxVertex.Set(1000, 1000);        // この辺はお約束
var gravity = new b2Vec2(0, 100);   // 重力
var doSleep = true;
var world = new b2World(worldAABB, gravity, doSleep);
// Create objects
var ground = createBox(world, 20, 400, 280, 10, 0, {"density":0.0, "friction":0.0, "restitution":0.0});
var bar1 = createBox(world, 0, 50, 200, 10, 10, {"density":0.0, "friction":0.0, "restitution":0.0});
var bar2 = createBox(world, 100, 150, 220, 10, -10, {"density":0.0, "friction":0.0, "restitution":0.0});
var bar3 = createBox(world, 0, 250, 200, 10, 30, {"density":0.0, "friction":0.0, "restitution":0.0});
var box1 = createBox(world, 150, 20, 50, 50, 0, {"density":1.0, "friction":0.1, "restitution":0.1});
var circle1 = createCircle(world, 110, 0, 20, 20, 0, {"density":1.0, "friction":0.0, "restitution":0.1});
var circle2 = createCircle(world, 215, 50, 10, 20, 10, {"density":1.0, "friction":0.2, "restitution":0.5});
/* Create a revolute joint */
// None
/* Step a world */
var timeStep = 1.0 / 60;
var iteration = 1;
/* Draw objects */
var tick = function(){
world.Step(timeStep, iteration);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillText(title, canvas.width/2-100, canvas.height/2, 200 );
drawWorld(world, ctx);
setTimeout(tick, 10);
};
/* Event */
Event.observe('canvas', 'click', function(e) {
createCircle(world, Event.pointerX(e) - canvas.left, Event.pointerY(e) - canvas.top, Math.random()*20+1, 10, 0, {"density":1.0});
});
/* Right mouse click */
Event.observe('canvas', 'contextmenu', function(e) {
if (e.preventDefault) e.preventDefault();
createBox(world, Event.pointerX(e) - canvas.left, Event.pointerY(e) - canvas.top, 10, 10, 0, {"density":0.0});
});
tick();
};/*  */
})();
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

box2d.jsはprototype.jsを最初に読み込む必要がある。
<script src="prototype-1.6.0.2.js"></script>
box2d.jsは実際は沢山のファイルをheadタグ内で読み込む必要があるが、面倒なためわたしは一つのファイルにしてしまった。
<script src="box2d.js"></script>
オブジェクトの生成にはパラメータが沢山あるため関数化したほうが使い易い。
draw_world.jsファイルはbox2d.jsのサンプルに使われていたファイルをそのまま使っている。
意味はまだわたし自身よく理解していない。
丸や四角といったオブジェクトの作成は関数化した。create_shapes2.jsというファイルに関数化した。
<!– Box2D を利用する上で使いやすくする関数を読み込み –>
<script src="draw_world.js"></script>
<script src="create_shapes2.js"></script>
<!– /Box2D を利用する上で使いやすくする関数を読み込み –>
オブジェクトの傾きが分からなかったので、Box2Dの中身をみてそれらしき「rotation」というパラメタを見つけた。
create_shapes2.jsの中で使っている。
【create_shapes2.js】

function createBox(world, x, y, width, height, angle, params){
var boxSd = new b2BoxDef();
boxSd.extents.Set(width/2, height/2);
for(var i in params) boxSd[i] = params[i];
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
x = x + width / 2;
y = y + height /2;
boxBd.position.Set(x, y);
boxBd.rotation = Math.PI * angle / 180;   // 傾き
var box = world.CreateBody(boxBd);
return box;
}
function createCircle(world, x, y, width, height, angle, params){
var circleSd = new b2CircleDef();
circleSd.radius = width;
for(var i in params) circleSd[i] = params[i];
var circleBd = new b2BodyDef();
circleBd.AddShape(circleSd);
circleBd.position.Set(x, y);
    circleBd.rotation = Math.PI * angle / 180;  // 傾き
    var circle = world.CreateBody(circleBd);
return circle;
}

参考URL

コメント

タイトルとURLをコピーしました