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, Коддинг
  • Stasik

    Однако как йода ты мысли свои излагаешь :)

    • http://suvitruf.ru Suvitruf

      Когда-то прикола ради так писал и говорил. Привык потом. Теперь уже это привычка (:

  • 2zoom

    Трение не работает, т.к. у платформы трение 0. Общий коэффициент трения вычисляется как корень из произведения коэффициентов двух тел. Поэтому твой герой не тёрся об платформу.

  • Dmitry

    Здравствуйте.Вы не сталкивались с проблемой,когда объекты проникают, а не задерживаются?Я столкнулся с этой проблемой и не понимаю почему так происходит.
    У меня есть 2 тела – static и dynamic.
    Первое(static) можно двигать,а второе падает сверху(dynamic).Если первое тело не двигать,то второе падает в первое и все нормально,но если его двигать,то оно начинает проникать сквозь второе(динамическое) тело.С чем это может быть связано?

    • http://suvitruf.ru Suvitruf

      Если мне память не изменяет, то у static тел массы нет. Может в этом дело. Попробуйте сделать его dynamic.
      Я давно уже с Box2D не работал. Без кода вряд ли что-то путное могу подсказать.

      • Dmitry

        Нет,я уже пробовал,это не помогает.
        И стало только хуже,теперь проникает и через низ,а не только через боковые грани =)

        • http://suvitruf.ru Suvitruf

          А вы эту статью смотрели? Если не боитесь, можете скинуть свой проект мне на мыло, я могу посмотреть на выходных.

          • Dmitry

            Конечно,я с нее и начинал.Я только вместо стандартных тел использовал программу
            http://www.aurelienribon.com/blog/projects/physics-body-editor/

            P.S. Вы не знаете как сильно параметр
            body.setBullet(true); может влиять на все это?

            • http://suvitruf.ru Suvitruf

              setBullet(true) указывает, что расчёты по этому телу будут более точные.
              Не думаю, что дело в нём.