定価:本体価格2,980円+税ISBN978-4-8399-4517-6仕様:B5変型、344ページ(予定)刊行:2013年6月下旬予定*画像はイメージです。おまけ先に、インストールについて簡単に紹介する。Box2dWebのサイトに「Downloads」のリンクがある(図001)。図001■Box2dWebのサイトダウンロードしたZip圧縮ファイル(Box2dWeb-2.1a.3.zip)を展開すると、ふたつのJavaScript(JS)ファィルが入っている(図002)。どちらかひとつのJSファイルをライブラリ用の適切なフォルダに納めればよい。サーバーに上げるにはmin(コンパクト)版が少ない容量で済む。実装を調べるときは通常版を用いる。物理空間と剛体を定めるBox2Dのスクリプティングにかかる前に、物理演算シミュレーションで落とすオブジェクトをひとつCanvasに置く。矩形のShapeインスタンスを使うことにする。位置は定めないので、ステージの基準点である左上角に描かれる(図03-03-004)。後に全体を掲げるコード001から抜出したscript要素は以下のとおり。nHeight);}</script>物理演算は計算なので、結果は数値。数値はステージに描いたオブジェクトのプロパティに当てはめて、初めてオブジェクトの動きとして目に見える。ステージのオブジェクトとBox2Dとの間は、人形と黒子のような関係になる。Box2dWebライブラリのJavaScript(JS)ファイルBox2dWeb-2.1.a.3.min.jsを、script要素で読込んでおく(ファイルを納めたフォルダはlibとした)。src="lib/Box2dWeb-2.1.a.3.min.js"></script>物理演算を行うにために、まずは3つの仕込みを行う。物理空間をつくる物理空間は、Box2Dのb2Worldクラスのオブジェクトとしてつくる。コンストラクタの第1引数に渡す重力は、2次元のベクトルを表すb2Vec2オブジェクトで定める。第2引数のスリープはブール(論理)値で、trueを渡すと動かなくなった剛体はシミュレーションから外して(スリープして)効率を高める。スリープ);Box2dWebは、数多くのクラスをJavaScriptファイルでは分けず、代わりに名前空間により分類・識別する。ひとつの関数の中で同じクラスを何度も用いる場合には、いちいち名前空間から書上げるのは煩わしく、コードも見にくい。いうときは、クラスを予め変数に入れて参照すると便利だ。スリープ);重力は通常垂直(y軸)方向の力なので、b2Vec2()コンストラクタの第1引数に渡すx座標値は0にした(第30行目)。垂直方向のy座標値は、変数(gravityVertical)に定めている(第18行目)。生成したb2Worldインスタンスは、変数(world)に納めた(第17および第30行目)。剛体を定義する後で落下させる予定の剛体は、1辺20ピクセルの正方形とし、その長さを変数(boxEdge)に置く(第19行目)。剛体を定義する関数(defineBody())は別に定めた(第35〜41行目)。関数の第1および第2引数(nXとnY)は、剛体のxy座標だ。第3引数(nType)は剛体の種類で、b2Bodyクラスの定数(静的プロパティ)として備わる整数で定める(表001)。0剛体を定義する関数(defineBody())は、b2BodyDef()コンストラクタでインスタンスをつくったら、剛体の位置と種類を決める(第36〜39行目)。位置はb2BodyDef.positionプロパティでb2Vec2オブジェクトを参照し、b2Vec2.Set()メソッドにより座標を決める。剛体の種類はb2BodyDef.typeプロパティに、b2Body.b2_dynamicBodyを定めた。関数は、定義の済んだb2BodyDefインスタンスを返す(第40行目)。bodyDef;}なお、Box2Dは物理学と同じメートル(m)・キログラム(kg)・秒の単位にもとづいてシミュレーションする。そこで、ピクセルからメートルへの換算比率(メートル/ピクセル)を定数(SCALE)にした(上記コード第16行目)。したがって、ピクセルで与えられた数値をBox2Dの座標として渡すときには、この定数値を乗じる(第38行目)。剛体定義に表示オブジェクトを関連づけるここまでの物理空間と剛体の定義は、Box2Dの仕込だった。ステージ上で動かそうとしているオブジェクトは、まだ蚊帳の外だ。そこで、Shapeオブジェクトをつくる関数(createShape())に、剛体定義とのつながりを加える。関数の第1引数には剛体定義のb2BodyDefオブジェクトが渡される(第32および第42行目)。そのb2BodyDef.userDataプロパティにShapeオブジェクト(myShape)を与えた(第47行目)。myShape;}3つの準備を整えたscript要素全体は、つぎのコード03-03-001のとおりだ。物理演算のシミュレーションは行っていないので、青い正方形のShapeインスタンスがCanvasの左上角に表れるだけだ(前掲図003)。物理演算シミュレーションの実行Box2Dで剛体の物理演算をするには、まず剛体定義のb2BodyDefオブジェクトをb2World.CreateBody()メソッドの引数に渡して、物理空間に剛体(Bodyオブジェクト)をつくらなければならない。メソッドからは、剛体定義にもとづいたBodyオブジェクトが返される。b2Worldオブジェクト.CreateBody(b2BodyDefオブジェクト)これから手を加えるJavaScriptのステートメントは、後にコード002として全体を掲げる。b2World.CreateBody()メソッドは、新たに定める関数(createBody())から呼出す(第61行目)。この関数の呼出しは、Box2Dを初期設定する関数(initializeBox2D())に加える(38行目)。引数にはb2Worldとb2BodyDefのオブジェクト(worldとbodyDef)を渡す。つぎに、物理シミュレートするため、物理空間のb2Worldオブジェクトに対して時間を進めるメソッドが、b2World.Step()だ。第1引数には、シミュレーションのために進める時間を秒数で渡す。第2および第3引数は、物理的な制約に合わせて調整の再計算をさせる回数だ。前者は速度、後者が位置についての演算を定める。位置再計算)人形のオブジェクトはTickerクラスで動かす(第14および第29行目)。リスナー関数(update())から、b2World.Step()メソッドを呼出す(第63〜64行目)。02-01-005)でTicker.tickイベントの間隔も合わせた(第28行目)。物理演算の時間を進めるたら、剛体の幾何情報を人形のオブジェクトに伝える。物理空間に加えられた剛体のうち初めのb2Bodyオブジェクトを取出すのが、b2World.GetBodyList()メソッドだ。剛体の位置は、b2Body.GetPosition()メソッドでb2Vec2オブジェクトとして得られる。その回転角は、b2Body.GetAngle()メソッドによりラジアン角が返される。剛体定義のb2BodyDef.userDataプロパティに与えた人形のオブジェクトの参照は、定義からつくられた剛体のオブジェクトにb2Body.GetUserData()メソッドを呼出すと得られる。DisplayObject.rotationプロパティの単位は度数なので、ラジアン角はMatrix2D.DEG_TO_RAD定数で除す。Matrix2D.DEG_TO_RAD;stage.update();}}</script>これでBox2Dの物理演算シミュレーションにもとづいて、インスタンスが重力により自由落下する(図004)。ここまでの書替えをすべて加えたscript要素の全体は、つぎのコード002のとおりだ。衝突のシミュレーションステージの下端に床を静的な剛体として加える。b2BodyDef.typeプロパティに与える定数はb2Body.b2_staticBodyだ(前掲表001「剛体の種類を定めるb2Body定数」参照)。床の静的な剛体と落下させる動的な剛体は、それぞれ別の関数(createStaticFloor()とcreateDynamicBox())に分けてつくる。ともに剛体の定義(defineBody())と作成(createBody())、およびShapeオブジェクト作成(createShape)の3つの関数を呼出す。今のところ、つくられる剛体の種類が静的か動的かというほかに違いはない。myShape;}物理空間の中の初めのb2Bodyオブジェクトは、b2World.GetBodyList()メソッドから参照を得た。その後、物理空間から順につぎの剛体を取出すには、b2Bodyオブジェクトに対してb2Body.GetNext()メソッド(前掲03-03-001-2)を呼出す。そこで、Ticker.tickイベントのリスナー関数(update())で複数の剛体が扱えるように、while文を加えて繰返し処理するように書替えた(第67〜76行目)。ループの終わりにb2Body.GetNext()メソッドでつぎの剛体を取出し、オブジェクトがあればシミュレーションを続ける。body.GetNext();}stage.update();}なお、矩形と床の剛体はTicker.tickイベントごとにまとめて描画すればよい。そのため、Stage.update()メソッドの呼出しは、whileループの外に出した(第77行目)。ここまでの手を加えたJavvaScriptコードが、以下のコード003だ。試してみると、落下したオブジェクトが床を抜けるイリュージョンになってしまう(図005)。物理シミュレーションにフィクスチャを加える私たちが「矩形」とか「床」とわかるのは、Shapeインスタンスのかたちを見ているからだ。黒子のBox2Dには、剛体定義の関数(defineBody())で座標と動くか動かないかしか伝えていない。剛体のかたちや大きさは、フィクスチャというオブジェクトで定めなければならない。剛体にフィクスチャを加えたコード03-03-004は後にまとめて掲げる。フィクスチャの定義をb2FixtureDefオブジェクトでつくり、b2FixtureDef.shapeプロパティにかたちを与える。かたちを定めるのはBox2Dのシェイブ(b2Shape)オブジェクトだ。矩形はb2PolygonShapeオブジェクトにb2PolygonShape.SetAsBox()メソッドで幅と高さを引数に渡してつくる。剛体をつくる関数(createBody())の引数には、b2FixtureDefオブジェクトを加えた(第77行目)。剛体にフィクスチャを与えるのはb2Body.CreateFixture()メソッドで、b2FixtureDefオブジェクトを引数に渡す(第79行目)。world.CreateBody(bodyDef);body.CreateFixture(fixtureDef);}これでBox2Dにふたつの剛体のかたちは伝わり、互いの衝突がわかるということです。JavaScriptコード全体は、以下のコード004のとおりだ。矩形は床に落ちても弾みもせず、まるで完璧な体操の着地のごとく、床に吸いつくように止まる(図006)。body.GetNext();}stage.update();}前掲コード004では、落とした剛体が弾むような材質であることを、まだBox2Dに教えていない。フィクスチャの定義には、つぎの表002のように密度と摩擦および弾性の3つの性質がプロパティで定められる。0から1の間の数値フィスクチャに質感を加えよう。JavaScriptコード全体は後にコード03-03-005として掲げる。つぎのように、密度と摩擦および弾性の3つを新たな関数(setFixtureDef())で定め(第81〜85行目)、落下する剛体をつくる関数(createDynamicBox())から呼出した(第46行目)。restitution;}これで、動的な剛体に弾力などの質感が加わった。落ちたオブジェクトは床で軽く何度か弾んだ後、やがて止まる(図007)。できあがったJavaScriptコード全体は、以下のコード005のとおりだ。おまけ3つほどリンクを加えておく。前に書いたノートで、できあがりのコードはほぼ同変わらない。勉強会では書籍に向けて書き改めた原稿にもとづいて解説した。説明の順序や途中のコードは異なっている。「Box2dWebを使うときの名前空間の扱い方」Box2dWebの長い名前空間のクラスを扱ういくつかのやり方を紹介した。前掲コード005に手を加えて、落とす剛体を50個に増やした。Box2Dについての新たな知識は要らない。ついでに、CreateJSのクラスに名前空間「createjs」を添えるとともに、Box2Dのクラスにも短い名前空間「box2d」を定めてみた。ラジアン角を度数値に換算する処理が漏れていたので追加。jsdo.itのコードを掲載。