Проблемы обнаружения конфликтов

У меня есть небольшая проблема с моей системой обнаружения конфликтов для игры. В игре есть несколько структур, которые соединяются друг с другом. Однако они не должны соединяться, когда между ними существует другая структура.

По какой-то странной причине иногда не удается подключиться к непосредственно смежным структурам, когда есть структура в прямой линии позади них. Редко он создает другие странные связи.

Фото:

BUG

Предполагается, что подключены красные отмеченные узлы.

код:

public void drawConnections(Graphics g) {
    ArrayList<EnergyContainer> structurecopy = (ArrayList<EnergyContainer>) Mainclass.structures.clone(); //all structures in a list
    structurecopy.remove(this); //as we are member of the list
    structurecopy.removeIf(t -> (!hasStructureInRangeWithoutObstaclesInBetween(t))); 
    structurecopy.removeIf(t -> !t.receivesEnergyfromNeighbors()); //unimportant check if it is allowed to connect (its working)
    structurecopy.forEach(t -> drawConnectionTo(t, g)); //also works fine 
}

public boolean hasStructureInRangeWithoutObstaclesInBetween(Structure structureWhichShouldBeInRange) {
    // if in Range
    if (getRange() >= Math.hypot(structureWhichShouldBeInRange.getX() - getX(),
            structureWhichShouldBeInRange.getY() - getY())){ //checks if structure is in range
        ArrayList<EnergyContainer> structureclone = (ArrayList<EnergyContainer>) Mainclass.structures.clone();
        structureclone.remove(this); //again removes itself from the list
        structureclone.remove(structureWhichShouldBeInRange); //also removes target - so it doesn't block itself
        structureclone.removeIf(t -> !t.collidesWithLine(this.getX(), structureWhichShouldBeInRange.getX(),
                this.getY(), structureWhichShouldBeInRange.getY())); //removes it when it does not collide
        return structureclone.size() == 0; //returns true when no collisions are found
    }
    return false;
}

public boolean collidesWithLine(int x1, int x2, int y1, int y2) {
    // Line Segment - Circle Collision Detection
    double dx = x2 - x1;
    double dy = y2 - y1;
    double a = dx * dx + dy * dy; //this is the distance
    double b = 2 * dx * (x1 - getX()) + 2 * dy * (y1 - getY());
    double c = getX() * getX() + getY() * getY() + x1 * x1 + y1 * y1 - 2 * (getX() * x1 + getY() * y1)
            - getCollisionRadius() * getCollisionRadius();
    double discriminant = b * b - 4 * a * c;
    return discriminant >= 0; // no intersection -> discriminant <0

}

(Я добавил комментарии только для этого текста, поэтому, пожалуйста, проигнорируйте их, если они вызовут ошибки компиляции).

Может кто-нибудь сказать мне, что я делаю неправильно?

Ответ 1

Здесь могут быть проблемы с паролем:

Сначала: Как сказал Марат: b может возвращать значение 0. Это произойдет, если ваши getX() и getY() возвращаются x1 и y1, В этом случае вы по существу делаете это: (2dx * 0) + (2dy * 0). Если это произойдет, это может негативно повлиять на ваши более поздние уравнения.

Во-вторых: Скорее всего, вы ВСЕГДА возвращаете true из этой любезности своего окончательного уравнения:

double discriminant = b * b - 4 * a * c;
//This breaks down to discriminant = b^2 * 4ac

Даже если b равно 0 в этой точке, если значение a или c имеет значение больше 0, будет ;

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

Кроме того, Unity API имеет функции обнаружения столкновений. Вы должны посмотреть на это. https://docs.unity3d.com/Manual/PhysicsSection.html

Надеюсь, что это поможет.

Ответ 2

Предположение:  1 Если я правильно понимаю, это методы некоторого класса структуры.  2 hasStructureInRangeWithoutObstaclesInBetween является единственным вызывающим лицом collidesWithLine или, по крайней мере, тем, как представлен вопрос.

Из-за (2) b всегда 0. У меня такое чувство, что это не твое намерение. Пожалуйста, перейдите к методу collidesWithLine.