まず最初に、 "sensor"はどこで使用できるのかと、それが何なのかを説明します。公式の box2d マニュアルからの引用です: センサーとは衝突を検知する部品ですが、応答を行うことはありません。任意の部品にセンサーとしてのフラグを付けることができます。センサーは静的にも動的にもできます。 Bodyごとに複数のfixtureを持ち、任意のセンサーとsolid fixture の組み合わせを持つことができるということを覚えておいてください。
final Sprite area = new Sprite(x, y, 100, 300, textureRegion, vbo); FixtureDef areaFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0); areaFixtureDef.isSensor = true; Body b = PhysicsFactory.createBoxBody(physicsWorld, area, BodyType.StaticBody, areaFixtureDef); scene.attachChild(area);
見て分かるように、ゾーン/エリアを視覚的に表すSpriteを新規に作成しています。そして、物理的な表現のためのbodyを新規に作成し、このbody をセンサーのように振舞わせます(別のbodyと重ねる)。FixtureDef オブジェクトのflagにはtrueを設定します。
ここでの主な疑問は、プレイヤーのbodyがゾーン/エリア上に入ったタイミングをどのように検知するか?です。 body同士の接触を常に制御するには、Contact Listenerを使用します (記事はここをクリック)。 Contact Listenerがどのように動作するかを必ず理解するようにしてください。理解できていない場合は、再度確認してください。
private boolean isInsideZoone = false; private ContactListener createContactListener() { ContactListener contactListener = new ContactListener() { @Override public void beginContact(Contact contact) { final Fixture x1 = contact.getFixtureA(); final Fixture x2 = contact.getFixtureB(); if(x2.getBody().getUserData().equals("player")&&x1.getBody().getUserData().equals("area")) { isInsideZoone = true; //action on enter } } @Override public void endContact(Contact contact) { final Fixture x1 = contact.getFixtureA(); final Fixture x2 = contact.getFixtureB(); if(x2.getBody().getUserData().equals("player")&&x1.getBody().getUserData().equals("area")) { isInsideZoone = false; //action on exit } } @Override public void preSolve(Contact contact, Manifold oldManifold) { } @Override public void postSolve(Contact contact, ContactImpulse impulse) { } }; return contactListener; }
この例では、使用するゾーン/エリアbodyのユーザーデータには "area"を、プレイヤーbodyのユーザーデータには"player"を使用しているので注意してください。 この簡単なやり方で、プレイヤーがゾーン/エリア内にいるタイミングもしくはいないタイミングを検知し、アクションを実行することができます。 状況により、異なる目的の広域エリアなどを実装する場合に方法に便利です。