libGDX: Box2D и проблемы с трением

Не так давно начал обкатывать физические движок Box2D, который в libGDX входит. Довольно не мало проблем с ним возникло. Последние дни мучился с различными силами.

Сразу стоит сказать, что движок охрененный. Точно довольно физику тел моделирует. Но огромная проблема возникает в подборе коэффициентов различных. В последние дни пытался разобраться с силой трения и с гравитацией. Вектор действия силы притяжения можно задать при создании мира (com.badlogic.gdx.physics.box2d.World), а именно world = new World(new Vector2(0, -20), true). Мы указали что силы притяжения действует сверху вниз, как и в реальном мире.

Допустим, если мы хотим поменять силу притяжения, действующую на объект, то можно коэффициент воздействия этой силы поменять. Как пример setGravityScale(-1). Теперь если сила действует вниз, то объект будет притягиваться вверх =D

Тут больше проблема чисто в подборе коэффициентов. А вот с трением посложнее. По умолчанию сила трения нулевая. Я использовал в мире движущиеся платформы. При нулевом трении, персонаж не будет двигаться вместе с платформой, а будет оставаться на месте, как бы скользить. Логично предположить, что надо выставить трение побольше. Я смотрел мануалы забугорные…На какой-то из сборок либы, всё работал норм, у меня почему-то нет. Вроде всего-то надо установить трение побольше для персонажа.

playerSensorFixture.setFriction(200f); 

Трение то устанавливается, но не работает на платформе. Честно говоря долго провозился. Решил пойти другим путём. В Box2D можно получить список всех контактов объектов.

List<Contact> contactList = world.getWorld().getContactList();

Я сделал метод, который проверяет, находится ли персонаж на земле. И добавил в этот метод проверку на движение. Если перс стоит, то меняю трение контакта.

private boolean isPlayerGrounded() {				
		world.groundedPlatform = null;
		List<Contact> contactList = world.getWorld().getContactList();
		for(int i = 0; i < contactList.size(); i++) {
			Contact contact = contactList.get(i);
			if(contact.isTouching() && (contact.getFixtureA() == world.getPlayer().playerSensorFixture ||
			   contact.getFixtureB() == world.getPlayer().playerSensorFixture)) {				
 
				Vector2 pos = world.getPlayer().getPosition();
				WorldManifold manifold = contact.getWorldManifold();
				boolean below = true;
				for(int j = 0; j < manifold.getNumberOfContactPoints(); j++) {
					below &;= (manifold.getPoints()[j].y < pos.y - 0.5F);
				}
 
				if(below) {
					if(contact.getFixtureA().getUserData() != null && contact.getFixtureA(). getUserData().equals("p")) {
						world.groundedPlatform = (MovingPlatform)contact.getFixtureA(). getBody().getUserData();	
						if (!keys.get(Keys.LEFT) && !keys.get(Keys.RIGHT)) 
							contact.setFriction(20F);
						else
							contact.setFriction(0F);
					}
 
					if(contact.getFixtureB().getUserData() != null &amp;&amp; contact.getFixtureB(). getUserData().equals("p")) {
						world.groundedPlatform = (MovingPlatform)contact. getFixtureB().getBody().getUserData();
						if (!keys.get(Keys.LEFT) && !keys.get(Keys.RIGHT)) 	
							contact.setFriction(20F);
						else
							contact.setFriction(0F);
					}		
					
					//
					return true;			
				}
 
				return false;
			}
		}
		return false;
	}

Ключевое здесь: contact.setFriction(20F). Теперь работает. Но всё равно это уже какой-то костыль получается)

  Категории: java, libgdx, Коддинг