Работа с ContactListener из Box2d в Libgdx

в 19:56, , рубрики: android, box2d, game development, Gamedev, java, libgdx, Разработка под android, метки: , , ,

В продолжение прошлой статьи про использование Box2d в Libgdx решил рассмотреть работу с классом ContactListener.

Из наименования класса очевидно, что использовать его следует для обработки коллизий. Рассмотрим пару практических примеров.

image

ContactListener — интерфейс, который можно реализовать в своём классе для дальнейшего использования в игровом мире.

Необходимо реализовать 4 метода: beginContact, endContact, preSolve, postSolve.

Наш класс будет иметь примерно такой вид:

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

Срабатывает, когда два объекта начинают накладываться. Прокает только в рамках шага.

endContact

Срабатывает, когда два объекта прекращают соприкасаться. Может быть вызван, когда тело разрушено, таким образом, это событие может иметь место вне временного шага.

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 в настоящее время обрабатывает, приводя к ошибке.

Есть тут одна тонкость — нельзя просто удалить объект, так как он может обрабатываться где-то в данный момент, и в итоге вы получите ошибку:
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), то ошибки не будет.

Исходники

Можете скачать исходники с блога. Они довольно сыроваты, правда. Но понять принципы работы помогут.

Автор: Suvitruf

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js