(2)複数のVector2[]配列からBody.を作りSpriteと関連付ける(複雑な形態のBody)

まず、どうやって複数のVector2[]をBodyに渡すのかが、意外に情報がない。初めはBodyをjointでつなごうと思ったが、どうもちがうらしい。同じ悩みをもつサイトにいきついた。

http://morishin127.tumblr.com/post/46425988233/ioscocos2d-box2d%E8%A4%87%E6%95%B0%E3%81%AE%E5%9B%B3%E5%BD%A2%E3%82%92%E7%B5%84%E3%81%BF%E5%90%88%E3%82%8F%E3%81%9B%E3%82%8B

iOSとCocos2d-xだがBox2dであるため、概念的には一緒であろう。このサイトのコードによるとBody.CreateFixtureでshapeを複数追加していくことができるらしい。 ここで、shapeとは?など色々疑問があったが、PhysicsFactory.createPolygonBodyのソース(下コード)を見てみるとなんとなく理解できた。

[java]
public static Body createPolygonBody(final PhysicsWorld pPhysicsWorld, final IShape pShape, final Vector2[] pVertices, final BodyType pBodyType, final FixtureDef pFixtureDef, final float pPixelToMeterRatio) {
final BodyDef boxBodyDef = new BodyDef();
boxBodyDef.type = pBodyType;

final float[] sceneCenterCoordinates = pShape.getSceneCenterCoordinates();
boxBodyDef.position.x = sceneCenterCoordinates[Constants.VERTEX_INDEX_X] / pPixelToMeterRatio;
boxBodyDef.position.y = sceneCenterCoordinates[Constants.VERTEX_INDEX_Y] / pPixelToMeterRatio;

final Body boxBody = pPhysicsWorld.createBody(boxBodyDef);

final PolygonShape boxPoly = new PolygonShape();

boxPoly.set(pVertices);
pFixtureDef.shape = boxPoly;

boxBody.createFixture(pFixtureDef);

boxPoly.dispose();

return boxBody;
}
[/java]

2-3行目はBody自体の設定(BodyDef定義)、引数より行う。staticBody(重力の影響を受けない)、DynamicBody(重力の影響を受ける)など後ほどコードを載せる。

5-7行目は座標系の変換。Bodyと実座標は違うとのこと。おまじないと思っておいてよいとのこと。

9行目でBodyDefからBodyを生成する

11行目でShpaeクラスのサブクラスのPolygonShapeを生成。

13行目でPolygonShapeのshapeにpVerticesのVector2[]配列を渡す

14行目で引数で渡されたFIXTURE_DEF(その1参照)のshapeにPolygonShapeを渡す

16行目でBodyにpFixtureDef(FIXTURE_DEF)を登録する

18行目でPolygonShapeの解放 という手続きが行われている。

先のサイトの情報より11行~18行をVector2[]配列数だけループさせればよいことが分かった。 準備として、その1で、作成した10個のVector2[]配列を定義部を記載しておく。ちょっとスマートな方法が思いかなかったが、ArrayListに10個のVector2[]を突っ込んだ。 ループで回そうと思ったがAndEngine Vertex Helperで直接定義文が出来るので、そんなめんどくさくはないが、やたらと長くなる。

[java]
ArrayList<Vector2[]> vertices_list = new ArrayList<Vector2[]>();

final Vector2[] vertices1 = {
new Vector2(-0.46000f*width, -0.11579f*height),
new Vector2(-0.19000f*width, -0.23684f*height),
new Vector2(+0.00000f*width, -0.00000f*height),

};
vertices_list.add(vertices1);

final Vector2[] vertices2 = {
new Vector2(-0.19000f*width, -0.23684f*height),
new Vector2(-0.00500f*width, -0.46316f*height),
new Vector2(+0.00000f*width, -0.00000f*height),

};
vertices_list.add(vertices2);

final Vector2[] vertices3 = {
new Vector2(-0.00500f*width, -0.46316f*height),
new Vector2(+0.19000f*width, -0.26842f*height),
new Vector2(+0.00000f*width, -0.00000f*height),

};
vertices_list.add(vertices3);

final Vector2[] vertices4 = {
new Vector2(+0.19000f*width, -0.26842f*height),
new Vector2(+0.45500f*width, -0.11579f*height),
new Vector2(+0.00000f*width, -0.00000f*height),

};
vertices_list.add(vertices4);

final Vector2[] vertices5 = {
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(+0.45500f*width, -0.11579f*height),
new Vector2(+0.32000f*width, +0.14737f*height),

};
vertices_list.add(vertices5);

final Vector2[] vertices6 = {
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(+0.32000f*width, +0.14737f*height),
new Vector2(+0.30000f*width, +0.47368f*height),

};
vertices_list.add(vertices6);

final Vector2[] vertices7 = {
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(+0.30000f*width, +0.47368f*height),
new Vector2(-0.00500f*width, +0.41053f*height),

};
vertices_list.add(vertices7);

final Vector2[] vertices8 = {
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(-0.00500f*width, +0.41053f*height),
new Vector2(-0.28500f*width, +0.45789f*height),

};
vertices_list.add(vertices8);

final Vector2[] vertices9 = {
new Vector2(-0.31500f*width, +0.14211f*height),
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(-0.28500f*width, +0.45789f*height),

};
vertices_list.add(vertices9);

final Vector2[] vertices10 = {
new Vector2(-0.46000f*width, -0.11579f*height),
new Vector2(+0.00000f*width, -0.00000f*height),
new Vector2(-0.31500f*width, +0.14211f*height),

};
vertices_list.add(vertices10);
[/java]

ここから、複数のVector2[]配列をshapeにしてBodyに登録していく部である。

[java]
BodyDef bDef = new BodyDef();
bDef.type = BodyType.DynamicBody;
bDef.fixedRotation = false; //回転許可
bDef.position.x = sp.getX() / PIXEL_TO_METER_RATIO_DEFAULT;
bDef.position.y = sp.getY() / PIXEL_TO_METER_RATIO_DEFAULT;

Body body = this.mPhysicsWorld.createBody(bDef);

for(Vector2[] v : vertices_list){
PolygonShape shape = new PolygonShape();
shape.set(v);
FIXTURE_DEF.shape = shape;
body.createFixture(FIXTURE_DEF);
shape.dispose();
}

attachChild(sp);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sp, body, true, true));
[/java]

BodyDefでBody(Sprite)の回転許可や、静止物体なのか、動的物体なのかを定義する。 名称未設定-1

以上で、複数のVector2[]配列をBodyに登録し物理シミュレーションができる状態となるはずです。 補足

[java]
//複数のVertices[]配列のリストからBodyを生成
public static Body createVerticesListBody(final PhysicsWorld pPhysicsWorld, final IShape pShape, final ArrayList<Vector2[]> vertices_list , final BodyType pBodyType, final FixtureDef pFixtureDef) {
final BodyDef boxBodyDef = new BodyDef();
boxBodyDef.type = pBodyType;

final float[] sceneCenterCoordinates = pShape.getSceneCenterCoordinates();
boxBodyDef.position.x = sceneCenterCoordinates[Constants.VERTEX_INDEX_X] / PIXEL_TO_METER_RATIO_DEFAULT;
boxBodyDef.position.y = sceneCenterCoordinates[Constants.VERTEX_INDEX_Y] / PIXEL_TO_METER_RATIO_DEFAULT;

final Body boxBody = pPhysicsWorld.createBody(boxBodyDef);

for(Vector2[] v : vertices_list){
final PolygonShape boxPoly = new PolygonShape();
boxPoly.set(v);
pFixtureDef.shape = boxPoly;
boxBody.createFixture(pFixtureDef);
boxPoly.dispose();
}

return boxBody;
}
[/java]

このクラスメソッドをPhysicsFactoryに追加し、定義クラスでも作って、スプライトごとのArrayListを吐き出して、このメソッドに投げてやれば、使いやすくなるんではないかと思います

投稿者 まる

Twitter : @dinagon Instagram : @d_dinagon フォロバします!!最近、ESP/Arduinoいじりすぎでアプリ開発が進んでない。歯医者なのに歯のことはあまり触れませんw