2013年7月24日水曜日

AndEngineのExtensionと物理演算メモ

AndEngineの拡張ライブラリを使ってみたい

AndEngine本も終わって、新たなことがやりたくなったのです
公式(?)サンプルの導入メモと
物理演算系サンプルの内容のメモです

AndEngineExamplesの導入メモ

ずっとほったらかしていた物理演算の拡張ライブラリを使いたくなったので、いろいろ試してみた
まずは公式のExampleを動かしてみることにする

以下のサイトから大量の拡張ライブラリをダウンロードする
https://github.com/nicolasgramlich?tab=repositories

ダウンロードするのは
AndEngineの本体。これはもう入っている人はいらない
・AndEngine

AndEngineの拡張ライブラリ(多すぎ!)
・AndEngineAugmentedRealityExtension
・AndEngineLiveWallpaperExtension
・AndEngineMODPlayerExtension
・AndEngineMultiplayerExtension
・AndEnginePhysicsBox2DExtension
・AndEngineScriptingExtension
・AndEngineSVGTextureRegionExtension
・AndEngineTexturePackerExtension
・AndEngineTMXTiledMapExtension

サンプルプロジェクト
・AndEngineExamples
パッケージを見つけたらクリックして・・・

左下のところからダウンロード




これらをすべてEclipseにインポートする

インポート後

ここで、AndEngineExamplesにエラーが出ていると思います。
これは普通にバグなのか、ライブラリのアップデートによっておかしくなったのか、よくわかりません
とにかくこれを修正しましょう。


AndEngineExamplesの中のエラーしている箇所はおそらく4つ
src/org.andengine.examplesの中の
・BoundCameraExample
・HullAlgorithmExample
・SplitScreenExample
・TextBreakExample.java
だと思います

それぞれ修正しましょう

・BoundCameraExample
・SplitScreenExample
修正前
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);
修正後
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager());
face.animate(100);

・HullAlgorithmExample
修正前
import org.andengine.entity.primitive.vbo.DrawMode;
修正後
import org.andengine.entity.primitive.DrawMode;


・TextBreakExample.java
修正前
this.mText = new Text(50, 40, this.mFont, "", 1000, new TextOptions(AutoWrap.LETTERS, AUTOWRAP_WIDTH, Text.LEADING_DEFAULT, HorizontalAlign.CENTER), vertexBufferObjectManager);
修正後
this.mText = new Text(50, 40, this.mFont, "", 1000, new TextOptions(AutoWrap.LETTERS, AUTOWRAP_WIDTH,  HorizontalAlign.CENTER, Text.LEADING_DEFAULT), vertexBufferObjectManager);


こちらのサイトを参考にしました。ありがとうございます。
上記の記事が書かれたのが半年前だから、このバグは半年以上放置されているということなんだろうか・・・


これでエラーが消えればExampleが動かせます
AndEngineExamplesを実行してみましょう。動けばOKですね



物理演算機能を調べてみる

やりたいのは物理演算なので、それ関係のプログラムを見てみる

実際に実行してみるときはこの場所


CollisionDetection(CollisionDetectionExample.java)


いつもどおりに作ったスプライトを、PhysicsHandlerというクラスのインスタンスに登録している
こうすることでPhysicsHandlerのインスタンスに対して速度を設定したり、加速度を所得したりといったことが可能になる。
このサンプルでは接触判定(これはAndEngine本に載ってる)や、アナログスティックを使った物体への速度設定を行っている


  final Sprite face = new Sprite(centerX, centerY + 42, this.mFaceTextureRegion, this.getVertexBufferObjectManager());
  final PhysicsHandler physicsHandler = new PhysicsHandler(face);
  face.registerUpdateHandler(physicsHandler);

  scene.attachChild(face);


・物体加速
・加速度設定・取得
・速度設定・取得
なんかが出来るようになるみたい


Using Physics(PhysicsExample.java)


CollisionDetection(CollisionDetectionExample.java)のサンプルと違い、接触や跳ね返りに物理演算ライブラリを使っている。

アクティビティに物理空間(PhysicsWorld)を設定し、
Rectangleで地面、屋根、右壁、左壁を作り、
FixtureDefで素材の定義をし、(物体密度、弾性力、摩擦を設定する)
createBoxBodyで剛体を登録している(引数は、登録する物理空間、物体の形状、剛体の種類、素材。だと思う)

タップすると顔が出てくるところは
onSceneTouchEventの中にあるthis.addFace(~)のところ
addFaceメソッドを見ると
丸顔⇒三角形顔⇒六角形顔⇒四角顔と順番に出現するようになっている
AniatedSpriteクラスのfaceを作る、Bodyクラスを作り、それに登録するという流れのよう

丸型のBody形状と四角型のBody形状はPhysicsFactoryというクラスの中に用意されているが、三角形と六角形のBody形状はないようで、PhysicsExampleのなかにメソッドが作られている。つまり好きな形のボディが割と簡単に作れるようだ。
最後に物理空間クラスの中のメソッドのregisterPhysicsConnectorを使い、生成した顔faceと剛体bodyを結び付けている


つまり物理物体を追加する方法は
方法1、PhysicsFactory.createBoxBody(~)で追加する
方法2、スプライトとボディを別々に作り、最後に結びつける

の二種類ということだろうか?



Using FixedStep Physics(PhysicsFixedStepExample.java)

シミュレーションステップが固定されるらしい。
物理空間の作成のときの引数に
int pVelocityIterations
int pPositionIterationsの二つが追加されている
よくわからないが、たぶん速度計算と現在位置計算をここで指定した値毎にするってことなんじゃ内だろうか?
・・・うんよくわからん。

Filtering Collisions(PhysicsCollisionFilteringExample.java)




物体の接触は登録したBodyすべてが行っているので、「特定の物体にはぶつからない」という処理方法が書かれている。

Bodyを生成するときに指定する引数にFixtureDefがあるが、これに「自分のカテゴリービット」と「接触判定をするカテゴリービット」を設定する

// 密度0、弾性力0.5、摩擦0.5、センサーなし、カテゴリビット1、カテゴリマスクビット1、グループ番号0
FixtureDef fixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f, false, 1, 1, (short)0);

まだわかっていないパラメータ(センサーとかグループ番号とか)もあるが、大体わかった気がする。
説明が難しいけど、ビット演算で接触・非接触を判定しているらしい

たとえば
物体A、B、Cがあるとする
Aのビット=1(2の0乗)
Bのビット=2(2の1乗)
Cのビット=4(2の2乗)
とする(必ず2の~乗で設定する)

ここで、「AとCにだけ接触する」ようにしたいときは
AとCに接触するマスクビット=AのビットCのビット
と設定するので
AとCに接触するマスクビット=
つまり
AとCに接触するマスクビット=5
となる

そうすると「5」という数字を作るための組み合わせは「2の0乗2の2乗」のパターンしかないので
このマスクビット「5」を設定すると2の0乗のビットをもつA2の2乗のビットをもつCにだけ接触するという処理をライブラリ側が勝手にやってくれる。

この手法って結構メジャーなんだろうか?
ライブラリなんだから、もっとわかりやすい方法使えばいいのにと思うけども



Combing Physics and Touch(PhysicsJumpExample.java)


生成した顔をタッチすると、重力方向と逆向きにジャンプ(?)するというもの。
上下左右の壁の生成や顔の生成は上のサンプル達と同様。
ただし、顔スプライトの生成、顔のBodyの生成の後、顔スプライトのUserDataにBodyを登録している。なるほどー。

注目すべきはこれまで無かった
onAreaTouchedメソッドだろう。
おそらく、画面上のスプライトを触ったときに呼ばれる関数で、pTouchAreaに触ったスプライト(厳密にはITouchArea)が格納されている。
なので、「顔画像を触ったら何か処理を行う」というのが可能になっている。
というかこれ、物理演算使わない場合でも使える関数なんだろうか?今度試してみよう。

顔をジャンプさせる関数部分は見たまんま。



Using a RevoluteJoint(PhysicsRevoluteJointExample.java)



ついに来ました!回転ジョイントの登場ですね!

BasePhysicsJointExample.javaを継承しています。
まずはこのBasePhysicsJointExampleの内容から見ていきま・・・とおもったけど、こっちの中身はこれまでのサンプルとほぼ同じでした。上下左右の壁と、タッチすると顔が増えるってだけです。

PhysicsRevoluteJointExample.javaのほうを見てみます。
流れは
1、固定された四角顔をつくる
 ・顔のスプライトを作る
 ・ボディを作って登録
2、移動可能な丸顔をつくる
 ・顔のスプライトを作る
 ・ボディを作って登録
3、丸顔と四角顔をつなぐ線を作る
 (この線が実際にジョイントになっているわけではない)
4、四角顔と丸顔のスプライトとボディを関連付ける
 ・四角顔の関連付けと同時にupdateメソッドをオーバーライドして、ラインの再描画をやっている
 ・丸顔は普通に関連付け
5、ジョイントをつくる
 ・RevoluteJointDefというクラスのインスタンスを作成
 ・固定顔(四角顔)と移動顔(丸顔)を登録し、固定顔の中心をアンカー位置にする
 ・モーターをtrueに
 ・モータースピードを10に
 ・最大トルクを200に
 ・最後に物理空間に作ったジョイントを登録

ということらしい。
なんか出来そうな気がしてきた。



Using a MouseJoint(PhysicsMouseJointExample.java)

顔スプライトをタッチして、ドラッグすると付いてくる(ゴム紐で結んであるヨーヨーみたいな感じ)サンプル

顔画像をタッチするとMouseJointが生成される。
mouseJointというのがいったい何なのかいまいちわかっていないですが、「マウスポインタで引っ張ったりするジョイント」というのが名前の由来なのかな?

まだわからないことが多い。
また、指を離すとマウスジョイントは消えるようになっているので
ジョイントの消去方法もわかった。



Removing a Physics Object(PhysicsRemoveExample.java)

最後は、顔スプライトをタッチして消すというサンプル
別段新しいことはないが消す方法が詳細にわかる

1、物理空間からコネクタを消す
this.mPhysicsWorld.unregisterPhysicsConnector(facePhysicsConnector);
2、物理空間からボディを消す
this.mPhysicsWorld.destroyBody(facePhysicsConnector.getBody());
3、シーンからタッチエリアの登録を外す
this.mScene.unregisterTouchArea(face);
4、シーンからスプライトを外す
this.mScene.detachChild(face);
5、ガベージコレクションを行う(だぶんこれでいろいろ不要なものを勝手に消してくれるんだろう)
System.gc();




0 件のコメント:

コメントを投稿