LibgdxのBox2dからContactListenerを操作する

LibgdxでのBox2dの使用に関する前回の記事の続きで、 ContactListenerクラスでの作業を検討することにしました。

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

画像


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

beginContactendContactpreSolvepostSolve 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)非アクティブにすると、エラーは発生しません。


ソースコード

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

Source: https://habr.com/ru/post/J162079/


All Articles