LibgdxのBox2dからContactListenerを操作する

LibgdxでのBox2dの使用に関する前回の記事の続きで、 ContactListener



クラスでの作業を検討することにしました。



クラスの名前から、衝突の処理に使用する必要があることは明らかです。 いくつかの実用的な例を考えてみましょう。



画像





ContactListener



は、ゲームの世界でさらに使用するために、そのクラスに実装できるインターフェイスです。



beginContact



endContact



preSolve



postSolve



4つのメソッドを実装する必要があります。



クラスは次のようになります。

 public class MyContactListener implements ContactListener{ @Override public void endContact(Contact contact) { } @Override public void beginContact(Contact contact) { } @Override public void preSolve (Contact contact, Manifold oldManifold){ } @Override public void postSolve (Contact contact, ContactImpulse impulse){ } }
      
      







使用するには、ゲームワールドに割り当てる必要があります。

 world.setContactListener(new MyContactListener());
      
      







beginContact





2つのオブジェクトが重なり始めたときに発生します。 ステップの一部としてのみ機能します。



endContact





2つのオブジェクトの接触が停止したときに発生します。 ボディが破壊されるとトリガーされるため、このイベントはタイムステップ外で発生する可能性があります。



preSolve





衝突が検出された後、処理される前に機能します。 これにより、処理する前に何らかの方法で連絡先を変更できます。 たとえば、連絡先を非アクティブにすることができます。 前の記事の例をご覧ください。 移動プラットフォームを使用しました。 キャラクターを通過させたいとします。 preSolve



は次のようになります。

  @Override public void preSolve (Contact contact, Manifold oldManifold){ WorldManifold manifold = contact.getWorldManifold(); for(int j = 0; j < manifold.getNumberOfContactPoints(); j++){ if(contact.getFixtureA().getUserData() != null && contact.getFixtureA().getUserData().equals("p")) contact.setEnabled(false); if(contact.getFixtureB().getUserData() != null && contact.getFixtureB().getUserData().equals("p")) contact.setEnabled(false); } }
      
      







contact.getFixtureA().getUserData().equals("p")



、オブジェクトを識別するために使用されます。 プラットフォームを作成するとき、 platform.getFixtureList().get(0).setUserData("p")



メソッドが使用されることを思い出させてください。





postSolve





このメソッドを使用すると、ゲームのロジックを実装できます。これにより、接触後の物理が変わります。 たとえば、接触後にオブジェクトを変形または破壊します。 ただし、Box2Dでは現在処理中のオブジェクトを破棄してエラーを引き起こす可能性があるため、Box2Dではメソッドの物理を変更できません。



ここには微妙な点が1つあります。オブジェクトを現時点ではどこかで処理できるため、単にオブジェクトを削除することはできず、最終的にエラーが発生します。

java.lang.NullPointerException

at com.badlogic.gdx.physics.box2d.World.contactFilter








したがって、メソッドでは、遭遇したブロックを削除します。



 @Override public void postSolve (Contact contact, ContactImpulse impulse){ Body body = null; if(contact.getFixtureA() != null &amp;&amp; contact.getFixtureA().getUserData() != null &amp;&amp; contact.getFixtureA().getUserData().equals("b")) body = contact.getFixtureA().getBody(); if(contact.getFixtureB() != null &amp;&amp; contact.getFixtureB().getUserData() != null &amp;&amp; contact.getFixtureB().getUserData().equals("b")) body = contact.getFixtureB().getBody(); if(body != null){ body.setActive(false); world.destroyBody(body); } }
      
      







現在、衝突では、 getFixtureList().get(0).setUserData("b")



が設定されているブロックは破棄されます。 上記から、通常の削除中にエラーが発生することを書きました。 ただし、削除する前にオブジェクトをbody.setActive(false)



非アクティブにすると、エラーは発生しません。





ソースコード


ソースはブログからダウンロードできます。 本当に湿っています。 しかし、仕事の原則を理解することは助けになります。




All Articles