だいたい47度

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PageTop

Box2DのJointまとめ(cocos2d)

Box2DのJOINTについて、理解が足りないことに気づきました。ちょっと複雑な動きのものを作ろうとしたのですが、なかなか難しい。「Distance JointとRevolute Jointがあればそれらを組み合わせてできるはず」という考えは甘っちょろかったか……。

マニュアルの8章の重要そうなとこのメモと思ったことを以下に書きます。jointとはなんぞやから、それぞれのjoint説明まで。英語が苦手な方も、図がよいのでそこだけは見ておくと良いかも。

Jointの基本
Jointは、body同士もしくはbodyとworldをつないで、bodyの動作に制御を加えるものです。それらの衝突可否はcollideConnectedで設定されます。

Jointにはモータとして働かせることができるものもあります。モータとインパルスが、Box2Dでbodyを動かすために推奨される2つの方法でしたので、これは重要です。

Jointの破壊については気を使いましょう。まず、DestroyJointしたあとはJointのポインタをnullにすることが推奨されています。破壊したjointによってゲームがクラッシュすることを防ぐためです。これはdeallocでworldをdeleteするときもやったりしますね。また、繋げているbodyが破壊されるとjointも自動的に破壊されますが、基本的にはjointを破壊してから、bodyを破壊する順番で処理しましょう。

Jointのメソッドを幾つか。まず、GetBodyAやBでbodyを取得したり、それらの接続点をGetAnchorAやBで呼び出せます。body2にかかる力やトルクもGetReactionForceやGetReactionTorqueで取得できるそうな。他にもモータとして使えるjointでは、SetMotorSpeed(float32 speed);などはかなり大事です。

Jointの種類として、b2JointDefのサブクラスが幾つかあります。Distance Joint、Revolute Joint、Prismatic Joint、Pulley Joint、Gear Jointなど。詳しくは以下で見ます。

Distance Joint
b2DistanceJointDefで定義されるDistance Joint。ふたつの物体の接続点を一定距離にするようにつなぐjointです。

といっても単に棒のようにつなぐというより、バネのようにつなぎます。バネの性質は周波数(jointDef.frequencyHz)と減衰(jointDef.dampingRatio)で制御できます。周波数はFPSの半分以下にするのが普通とのこと(60なら30)。ナイキスト周波数がその理由だとのことですが、まぁ考えて見ればFPSに近い数字(およびそれ以上)じゃ意味無いですね。減衰は0から1を指定してやり、1以上だと全く振動しないです。棒のようにしたければjointDef.dampingRatio = 1としてやればいいと。

Revolute Joint
b2RevoluteJointDefで定義されるRevolute Joint。ふたつの物体を一点でつないで、そこを中心に回転できるようにします。回転角はInitializeされたときを0として、反時計回り方向を正に、ラジアンで扱われます。回転角の最大値と最小値を制限できます。

Revolute Jointはモータとしても働けます。モータとして使う場合は最大トルクは定義しておきましょう(無限の力は恐ろしいもの)。また、速度は0にしながらも最大トルクを小さめの値で渡しておけば、回転への摩擦を持つようなRevolute Jointを描画することもできます。

モータの回転速度は毎Stepごとに決められるので、三角関数を用いた以下の様な記述もありだそうな。なるほど。
myJoint->SetMotorSpeed(cosf(0.5f * time));

Prismatic Joint
b2PrismaticJointDefで定義されるPrismatic Joint。2つの物体を一つの直線軸上で動かせるようにします。直動ジョイントともいうらしいです。Initializeされたときの位置関係が0となり、Initialize時の引数のベクトルにそって動作します。動作の上限下限もlowerTranslation、upperTransitionで決められます。

Prismatic Jointもモータとして使えます。ちょっと感覚的に変ですが、これは便利です。Distance JointとRevolute Jointを組み合わせて直線運動を作成するのは至難の業です。

Pulley Joint
b2PulleyJointDefで定義されるPulley Joint。片方の物体が上昇すると片方が下降するといったような、滑車の動きを実現するjointです。片方がnだけ上昇したとき、もう片方が2n下降するといったような、倍率をかけた制御もできるとのこと(その分、掛かる力は反比例します)。小学生くらいに勉強したなー、滑車。

Initializeのときには、それぞれのbodyと滑車の紐の接続点を渡します。ratioはbody2の方の滑車の長さにかかります。GetLengthAやBなどのメソッドもあります。

jointDef.Initialize(myBody1, myBody2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio);
//length1 + ratio * length2 == constant

片方の滑車が引き出されすぎて、もう片方の滑車の長さが0にならないように注意とのこと。それぞれの下に何か台でもつけてやるのが普通ですけど、上端に何か設置してやるのもかっちょいいかもしれません。

Gear Joint
b2GearJointDefで定義されるGear Joint。2つのjointを連動させる歯車のような仕組みが簡単に作れます。たとえば、Revolute Jointがxだけ回るとPrismatic Jointがyだけ進む、といったような仕組みです。組み合わせられるjointは、Revolute JointおよびPrismatic Jointのみです(Revolute JointとRevolute Jointの組み合わせなども可能)。

比率はPulley Joint同様ratioで設定。マニュアルではjointDef.ratio = 2.0f * b2_pi / myLength;としていますが、単純に数値をいれてしまう(jointDef.ratio = 2.0f;)ことも多いようです。

Gear Jointは、連動させているJointを破壊する前に破壊しなければなりません。順番を間違えるとクラッシュするそうです。Jointの基本で述べたように、きちんと順番通り破壊しましょう。

Flashですが、Flashで遊ぼう!さんの記事が動くサンプルもあってわかりやすいです。

その他
マニュアルで説明が適当なのでここでも簡単に。

Mouse Joint。マウス(タッチポイント)と物体をつなぐJoint。結構面白い動きになったり、デバッグに楽だったりするので、書籍やWebにある説明には詳しく書いてあったりします。aabbで走査したりする必要があるため、実装はちょっと面倒。最初は、マウスで物体を動かす時にまさかJOINT使うとは思わないよね。

Wheel Joint。b2WheelJoint.hとCar.hを見てね、とのこと。どうも、回転体と直動体を組み合わせてサスペンションみたいに働くようです。円運動と直動運動を変換できるわけですが、Gear Jointなどもあるし、使いどころがピンとこない。

Weld Joint。Cantilever.hを見てね、とのこと。weldは溶接という意味で、ゲームのどこかでバラバラになるものをくっつけておくのに使うようです。一つのbodyに複数fixtureをくっつけておいてバラバラにすると、bodyの再initializeが必要になるので、何かをバラバラにしたい場合はこれを使うようです。

Rope Joint。b2RopeJoint.hとRopeJoint.hを見てね、とのこと。2つの物体が一定以上の距離に離れないようにするそうです。鎖でつながれた犬のような感じですね。

Friction Joint。b2FrictionJoint.hとApplyForce.hを見てね、とのこと。例としてはこんな感じのようです。ちょっと面白い。
関連記事
スポンサーサイト

PageTop

コメント


管理者にだけ表示を許可する
 

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。