サイトのトップへ戻る

AndEngineドキュメント 日本語訳

センサーを作成する:

まず最初に、 "sensor"はどこで使用できるのかと、それが何なのかを説明します。公式の box2d マニュアルからの引用です: センサーとは衝突を検知する部品ですが、応答を行うことはありません。任意の部品にセンサーとしてのフラグを付けることができます。センサーは静的にも動的にもできます。 Bodyごとに複数のfixtureを持ち、任意のセンサーとsolid fixture の組み合わせを持つことができるということを覚えておいてください。



1. 使用例:
ゲーム内に、何らかのゾーン/エリアを作成したいとしましょう。 プレイヤーがこのエリアに入った時に何らかのアクションを実行するというものです。 (例。メッセージを表示するなど。)
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がどのように動作するかを必ず理解するようにしてください。理解できていない場合は、再度確認してください。

  • エリアセンサーのbodyにはユーザーデータを設定する(serUserData)必要があります。
  • beginContact() 内で確認の処理を記述する必要があります;
  • boolean isInsideZoone = falseと設定したフィールドを新規に作成します;
  • 接触が発生した場合 -  beginContact()、isInsideZoone にtrueを設定します。
  • endContact()内でisInsideZoone にfalseを設定します。
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"を使用しているので注意してください。 この簡単なやり方で、プレイヤーがゾーン/エリア内にいるタイミングもしくはいないタイミングを検知し、アクションを実行することができます。 状況により、異なる目的の広域エリアなどを実装する場合に方法に便利です。