Ошибка столкновения кругов, круги вращаются вокруг неподвижных кругов

У меня есть рабочий код ниже для столкновения двух кругов, но теперь у меня есть специальные круги, которые никогда не должны двигаться. При попытке применить их с существующим кодом движущиеся круги начинают вращаться вокруг статических, «скрепленных болтами», неподвижных кругов (когда я говорю «орбита», я имею в виду, что круг вращается вокруг круга, касаясь его некоторое время, пока не дойдет до точки). другую сторону, а затем продолжает движение в своем первоначальном направлении). Я попытался заставить часть кода работать со статическими кругами (см. огромный раздел с комментариями), но это сработало только наполовину. Мои круги нормального размера работают нормально, большую часть времени, но иногда они все еще вращаются. Кроме того, у меня есть еще один особый круг, на который не влияет трение, он меньше и почти всегда вращается по орбите. Кто-нибудь знает, в чем моя проблема? Я наполовину понимаю, что здесь происходит с математикой, я взял ее из какой-то статьи о Гамасутре.

//move them apart so they don't intersect anymore
float distance = (float) Math.sqrt(((circleA.getCenterX() - circleB.getCenterX()) * (circleA.getCenterX() - circleB.getCenterX())) + ((circleA.getCenterY() - circleB.getCenterY()) * (circleA.getCenterY() - circleB.getCenterY())));
float separation = (circleA.getRadius() + circleB.getRadius()) - distance;

float xSepA = separation * (circleA.getCenterX() - circleB.getCenterX()) / distance / 2; //distance to move circleA in x dir
float ySepA = separation * (circleA.getCenterY() - circleB.getCenterY()) / distance / 2; //distance to move A in y dir
float xSepB = separation * (circleB.getCenterX() - circleA.getCenterX()) / distance / 2; //same for B
float ySepB = separation * (circleB.getCenterY() - circleA.getCenterY()) / distance / 2;

if (circleA.isStatic()) {
    xSepA = 0;
    ySepA = 0;
    xSepB = separation * (circleB.getCenterX() - circleA.getCenterX()) / distance; //same for B
    ySepB = separation * (circleB.getCenterY() - circleA.getCenterY()) / distance;
}
if (circleB.isStatic()) {
    xSepA = separation * (circleA.getCenterX() - circleB.getCenterX()) / distance;
    ySepA = separation * (circleA.getCenterY() - circleB.getCenterY()) / distance;
    xSepB = 0;
    ySepB = 0;
}

//moving them

circleA.setX(circleA.getX() + xSepA);
circleA.setY(circleA.getY() + ySepA);
circleB.setX(circleB.getX() + xSepB);
circleB.setY(circleB.getY() + ySepB);
//change velocity to bounce
Vector2f va = circleA.getVelocityVector();
Vector2f vb = circleB.getVelocityVector();
Vector2f vn = MathUtil.sub(circleA.getPositionVector(), circleB.getPositionVector());
vn.normalise();



float aa = va.dot(vn);
float ab = vb.dot(vn);

float optimizedPA = (2f * (aa - ab)) / (circleA.getMass() + circleB.getMass());
float optimizedPB = (2f * (ab - aa)) / (circleA.getMass() + circleB.getMass());

Vector2f newVA = MathUtil.sub(va, MathUtil.scale(vn, optimizedPA * circleB.getMass()));
Vector2f newVB = MathUtil.sub(vb, MathUtil.scale(vn, optimizedPB * circleA.getMass()));

//    if (circleA.isStatic()) {
//        optimizedPB = (2f * (ab - aa)) / (circleB.getMass());
//        newVA = va;
//        newVB = MathUtil.sub(vb, MathUtil.scale(vn, optimizedPB));
//        System.out.println(vb + " " + newVB);
//    } else if (circleB.isStatic()) {
//        optimizedPA = (2f * (aa - ab)) / (circleA.getMass() + circleB.getMass());
//        newVA = MathUtil.sub(va, MathUtil.scale(vn, optimizedPA));
//        newVB = vb;
//        System.out.println(va + " " + newVA);
//    }

circleA.setVX(newVA.getX());
circleA.setVY(newVA.getY());
circleB.setVX(newVB.getX());
circleB.setVY(newVB.getY());

person Rahat Ahmed    schedule 05.04.2011    source источник
comment
Переформатированный код; пожалуйста, верните, если неправильно.   -  person trashgod    schedule 05.04.2011
comment
@trashgod: Вы изменили код или просто сделали его более приятным для просмотра?   -  person Rahat Ahmed    schedule 05.04.2011
comment
Просто отступ, я думаю.   -  person trashgod    schedule 05.04.2011


Ответы (1)


Чтобы понять, как работает векторный подход, вы можете получить некоторую информацию из этой статьи и пример. Одним из источников таких аномалий «орбиты» является неправильная реализация изменяемых векторов; необходимы тщательные модульные тесты. Нет простого способа отладить такой фрагмент кода; вам, вероятно, потребуется подготовить sscce.

person trashgod    schedule 05.04.2011
comment
Я прочитал эту статью и даже попытался реализовать ее, используя те же шаги, но это было хуже, чем закомментированный код, который у меня есть. Я должен делать что-то не так - person Rahat Ahmed; 05.04.2011
comment
Я предполагаю, что ваши круги перекрываются более чем на один радиус, когда вы проверяете столкновение; попробуйте проверять чаще или перемещать меньше пикселей за итерацию. - person trashgod; 05.04.2011
comment
Это не имеет смысла? Как они могут перекрываться больше радиуса? - person Rahat Ahmed; 05.04.2011
comment
Перекрываются в том смысле, что центры больше не сближаются, а удаляются друг от друга. - person trashgod; 05.04.2011
comment
Нет, похоже, это не так, потому что код разделил бы их позиции. Я думаю, что это связано с моим измененным уравнением для нахождения новых скоростей, потому что столкновение почти не меняет скорость. - person Rahat Ahmed; 05.04.2011