車輪はゴロゴロとどこかに転がっていってしまいます。これらをつなぐのがジョイントの役目です。/p>
なお、ここから説明するソースコードは、後輪を作るところの直後から書き足していくものと考えてください。
b2RevolutionJointDefでつなぐ場所を決める
ジョイントを作るには、物体を作るときと同じように
- XxxJoiontDefクラスを使ってジョイントを定義する
- 定義を使ってXxxJointクラスの変数を作る
という順番で作業を進めます。車体と車輪をつなぐには、回転ジョイント(b2RevolutionJointDef)を使います。
jointDef変数を作ったら、まずInitializeメソッドで初期化します。1番目と2番目の引数は、つなぎ合わせる物体です。まずは車体と前輪をつなぐので、bodyとfrontWheelを指定します。
3番目の引数は、回転の軸となる座標です。この座標に指定しているfrontWheel.GetWorldCenter()は、前輪の中心座標、つまり画面の左から2.8m、上から2mの場所を表します。数字で直接指定することもできますが、このようにGetWorldCenterメソッドを使ったほうが分かりやすいかと思います。
ジョイントの細かい設定
次に、ジョイントに関する細かい設定をします。
motorSpeedは、回転の速さを表す値です。単位はラジアン毎秒なので、1にすると約6秒で車輪が1回転することになります。
maxMotorTorqueは、トルク(回転の強さ)を表す値です。速さとはまた別の値で、坂道を走らせるのであればある程度意味を持ってくる値です。単位はニュートンメートルですが、今回のサンプルでは少し説明しづらいので詳細は省きます。
ここまで設定してきた値は、enableMotorをtrueにすることで効果を発揮します。これは文字通り、回転ジョイントをモーターとさせるかどうかのフラグです。連載第1回のサンプルで紹介したラグドールのようなものを作るときは、これがfalseになります。
定義からジョイントを作る
ジョイントの定義が終わったので、実際にジョイントを作ります。
ここの書き方はCreateDynamicBodyなどを使って物体を作るときとほぼ同じですが、b2RevoluteJointにキャストしている部分だけが違います。CreateJointメソッドが返すオブジェクトの型がb2Jointという汎用的な型なので、それをfrontJointに代入するためにキャストしています。
後輪のジョイントを作る
後輪のジョイントを作るときには、前輪のジョイントの定義をほぼそのまま使えるので、たった2行で書くことができます。
後輪の中心を軸に車体と後輪をつなぐように設定し、ジョイントを作るだけです。他のパラメータは変える必要がありません。
ここまで書いてきたプログラムに必要なimport文を書き加えてコンパイルすると、以下のような結果になります(これもクリックで動作開始するように書き換えてます)。
ちゃんと車ができましたね。四角や円だけでもそこそこ使えるBox2Dですが、ジョイントを使うとできることが格段に増えます。
マウスジョイントを使って車を持ち運ぶ
ただ車が走っているだけではつまらないので、マウスで持ち運べるようにしましょう。マウスで操作をするときには、マウスジョイント(b2MouseJointDef)を使います。
クラスにプロパティを追加する
まず準備段階として、クラスに以下の3つのプロパティを追加します。
このうち、bodyは先ほど車体として使っていたローカル変数を移動させたものです。そのため、bodyを作っている行を以下のように書き換えます。
mouseJointDefとmouseJointは、今回新しく追加されたもので、マウスジョイントの定義と、ジョイントそのものです。
マウスジョイントを定義する
車を作り終わった直後のところに、マウスジョイントの定義を設定するプログラムを書きます。
回転ジョイントのときと同じように、つなぎたい物体をbody1とbody2に設定します。ここではb2WorldクラスのGetGroundBodyメソッドを使って、片方をワールド全体に設定します。もう片方にはマウスで動かしたい物体を設定します。
targetには、引っ張られる対象の座標を設定します。今回は車体を引っ張ることにするので、body.GetWorldCenterを使って車体の中心座標を設定します。
maxForceとtimeStepは、それぞれ説明にあるとおり、マウスで引っ張る力とシミュレーションの間隔です。maxForceが小さすぎると、重力に打ち勝つことができずに車が落ちていってしまいます。このあたりは実際に値を書き換えてみて試してみてください。シミュレーション間隔は、Flashの画面更新間隔と同じ1/24秒にします。
マウスイベントのハンドラを追加する
ここまで書いて気づいたかもしれませんが、マウスジョイントの定義は作りましたが、マウスジョイントそのものは作っていません。なぜかというと、マウスジョイントを作ってしまうと、車体が引っ張られ続けてしまうからです。マウスボタンが押されている間だけジョイントでつなぐという処理が必要になります。
マウス操作が絡んでくるので、イベントハンドラを登録しなければなりません。コンストラクタの最後に、以下の3行を追加してください。
マウスジョイントを作る
マウスボタンが押されたときに、マウスジョイントを作ります。作り方は回転ジョイントと同じくCreateJointメソッドを使います。
マウスジョイントを切り離す
重要なのはマウスボタンが離されたときで、ここでジョイントを切らないと車が宙に浮いたままになってしまいます。ジョイントを切るには、以下のようにDestroyJointメソッドを使います。ジョイントを切ったら、mouseJointをnullにしておきます。
マウスジョイントの位置を更新する
最後に、マウスカーソルが動かされたときの処理です。mouseJointがnullでないとき、つまりジョイントが存在しているときだけ処理を実行します。実行する処理とは、現在のマウスカーソル位置をマウスジョイントに設定することです。これには、SetTargetメソッドを使います。
これで完成です。コンパイルすると以下のようなFlashができると思います。画面上部でマウスを適当にドラッグすると、車を持ち運ぶことができます。
ここまで編集してきたソースを、クラス名を変えて置いておきますので、参考にしてください。
まとめ
6種類あるジョイントの中から回転ジョイントとマウスジョイントを使い、マウスで持ち運ぶことのできる車を作りました。ジョイントを使うことで、より動きがあり、Box2DらしいFlashが作れると思います。今回説明し切れなかったジョイントについては、Box2Dのサンプルなどを参考にしてぜひ試してみてください。
次回は脱DebugDrawをテーマに、自前の描画を行う方法について説明したいと思います。