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 && contact.getFixtureA().getUserData() != null && contact.getFixtureA().getUserData().equals("b")) body = contact.getFixtureA().getBody(); if(contact.getFixtureB() != null && contact.getFixtureB().getUserData() != null && 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)
非アクティブにすると、エラーは発生しません。
ソースコード
ソースは
ブログからダウンロードできます。 本当に湿っています。 しかし、仕事の原則を理解することは助けになります。