(2)複数のVector2[]配列からBody.を作りSpriteと関連付ける(複雑な形態のBody)
まず、どうやって複数のVector2[]をBodyに渡すのかが、意外に情報がない。初めはBodyをjointでつなごうと思ったが、どうもちがうらしい。同じ悩みをもつサイトにいきついた。
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)の回転許可や、静止物体なのか、動的物体なのかを定義する。
以上で、複数の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を吐き出して、このメソッドに投げてやれば、使いやすくなるんではないかと思います