今回から3回ほどにわたって、
Box2dWebを使う
「Box2D」
まずは、

ダウンロードしたZip圧縮ファイル

そして、
<script src="http://code.createjs.com/easeljs-0.7.1.min.js"></script>
<script src="http://code.createjs.com/preloadjs-0.4.1.min.js"></script>
<script src="lib/Box2dWeb-2.1.a.3.min.js"></script>
また、
<body onLoad="initialize()">
<canvas id="myCanvas" width="400" height="300"></canvas>
</body>
ボールの画像をBitmapオブジェクトに読み込む
物理演算エンジンを初めて使うとき、
先に、

Box2Dでボールをひとつ落とすスクリプトは、
画像ファイルのURLを引数に受取った関数
画像のオブジェクトをステージに置く関数
処理の行数はさほどないのに関数が多いのは、

var stage;
var ballImage;
var imageRadius;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
createjs.Ticker.timingMode = createjs.Ticker.RAF;
preloadImage("images/Pen.png");
}
function tick(eventObject) {
stage.update();
}
function addBall() {
var ball = createVisualBall(imageRadius);
stage.addChild(ball);
}
function createVisualBall(radius) {
var ball = new createjs.Bitmap(ballImage);
ball.regX = ballImage.width / 2;
ball.regY = ballImage.height / 2;
ball.scaleX = ball.scaleY = radius / imageRadius;
return ball;
}
function preloadImage(file) {
var loader = new createjs.LoadQueue(false);
loader.addEventListener("fileload", loadFinished);
loader.loadFile(file);
}
function loadFinished(eventObject) {
ballImage = eventObject.result;
imageRadius = ballImage.width / 2;
createjs.Ticker.addEventListener("tick", tick);
addBall();
}
物理空間と剛体を定める
ここから、
- 【物理演算シミュレーションの準備】
- 物理空間をつくる
- 剛体を定義する
- 剛体定義に表示オブジェクトを関連づける
第1の物理空間は、
var world = new Box2D.Dynamics.b2World(重力, スリープ);
Box2dWebには、
物理空間をつくる関数
var world;
var gravityVertical = 15;
function initialize() {
var gravity = new Box2D.Common.Math.b2Vec2(0, gravityVertical);
initializeBox2D(gravity);
}
function initializeBox2D(gravity) {
world = new Box2D.Dynamics.b2World(gravity, true);
}
第2に、
b2Body定数 | 剛体の種類 | 値 |
---|---|---|
b2_ | 動的 | 2 |
b2_ | キネマティック | 1 |
b2_ | 静的 | 0 |
剛体定義の関数
なお、
var SCALE = 1 / 30;
function addBall() {
// var ball = createVisualBall(imageRadius);
var ball = createDynamicBall(stageWidth / 2, -imageRadius, imageRadius);
}
function createDynamicBall(nX, nY, radius) {
var dynamicBody = Box2D.Dynamics.b2Body.b2_dynamicBody;
var bodyDef = defineBody(nX, nY, dynamicBody);
var ball = createVisualBall(radius, bodyDef);
return ball;
}
function defineBody(nX , nY, bodyType) {
var bodyDef = new Box2D.Dynamics.b2BodyDef();
bodyDef.position.Set(nX * SCALE, nY * SCALE);
bodyDef.type = bodyType;
return bodyDef;
}
第3は、
// function createVisualBall(radius) {
function createVisualBall(radius, bodyDef) {
var ball = new createjs.Bitmap(ballImage);
bodyDef.userData = ball;
return ball;
}
剛体をつくって落とす ー 物理演算シミュレーションの実行
ようやく、
- 【物理演算シミュレーションの準備】
- 剛体の定義から剛体をつくる
- 時間を進めてシミュレーションする
第4の仕事となる剛体づくりは、
b2Worldオブジェクト.CreateBody(b2BodyDefオブジェクト)
b2World.
function createDynamicBall(nX, nY, radius) {
createBody(world, bodyDef);
}
function createBody(world, bodyDef) {
var body = world.CreateBody(bodyDef);
}
いよいよ、
b2Worldオブジェクト.Step(経過秒数, 速度再計算, 位置再計算)
人形であるボールのBitmapオブジェクトは、
物理演算の時間を進めたら、
そして、
var velocityIterations = 8;
var positionIterations = 3;
function tick(eventObject) {
var delta = eventObject.delta;
update(delta);
}
function update(delta) {
world.Step(delta / 1000, velocityIterations, positionIterations);
var body = world.GetBodyList();
var myObject = body.GetUserData();
if (myObject) {
var position = body.GetPosition();
myObject.x = position.x / SCALE;
myObject.y = position.y / SCALE;
myObject.rotation = body.GetAngle() / createjs.Matrix2D.DEG_TO_RAD;
}
}
以上の5つの手順がBox2Dを使う最小限の仕込みだ。これで、

var SCALE = 1 / 30;
var stage;
var world;
var gravityVertical = 15;
var velocityIterations = 8;
var positionIterations = 3;
var stageWidth;
var stageHeight;
var ballImage;
var imageRadius;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
var gravity = new Box2D.Common.Math.b2Vec2(0, gravityVertical);
stage = new createjs.Stage(canvasElement);
stageWidth = canvasElement.width;
stageHeight = canvasElement.height;
initializeBox2D(gravity);
createjs.Ticker.timingMode = createjs.Ticker.RAF;
preloadImage("images/Pen.png");
}
function initializeBox2D(gravity) {
world = new Box2D.Dynamics.b2World(gravity, true);
}
function tick(eventObject) {
var delta = eventObject.delta;
update(delta);
stage.update();
}
function addBall() {
var ball = createDynamicBall(stageWidth / 2, -imageRadius, imageRadius);
stage.addChild(ball);
}
function createDynamicBall(nX, nY, radius) {
var dynamicBody = Box2D.Dynamics.b2Body.b2_dynamicBody;
var bodyDef = defineBody(nX, nY, dynamicBody);
var ball = createVisualBall(radius, bodyDef);
createBody(world, bodyDef);
return ball;
}
function defineBody(nX , nY, bodyType) {
var bodyDef = new Box2D.Dynamics.b2BodyDef();
bodyDef.position.Set(nX * SCALE, nY * SCALE);
bodyDef.type = bodyType;
return bodyDef;
}
function createBody(world, bodyDef) {
var body = world.CreateBody(bodyDef);
}
function update(delta) {
world.Step(delta / 1000, velocityIterations, positionIterations);
var body = world.GetBodyList();
var myObject = body.GetUserData();
if (myObject) {
var position = body.GetPosition();
myObject.x = position.x / SCALE;
myObject.y = position.y / SCALE;
myObject.rotation = body.GetAngle() / createjs.Matrix2D.DEG_TO_RAD;
}
}
function createVisualBall(radius, bodyDef) {
var ball = new createjs.Bitmap(ballImage);
ball.regX = ballImage.width / 2;
ball.regY = ballImage.height / 2;
ball.scaleX = ball.scaleY = radius / imageRadius;
bodyDef.userData = ball;
return ball;
}
function preloadImage(file) {
var loader = new createjs.LoadQueue(false);
loader.addEventListener("fileload", loadFinished);
loader.loadFile(file);
}
function loadFinished(eventObject) {
ballImage = eventObject.result;
imageRadius = ballImage.width / 2;
createjs.Ticker.addEventListener("tick", tick);
addBall();
}
結果がつまらないのは、