Не так давно начал обкатывать физические движок 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 && 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). Теперь работает. Но всё равно это уже какой-то костыль получается)