Если у вас есть "шарик" внутри двумерного многоугольника, состоящий, например, из четырех сегментов линии, которые действуют как ограничивающие стены, как вы вычисляете угол шара после столкновения с нерегулярно наклонной стенкой?
Я знаю, как заставить мяч отскакивать, если стена горизонтальная, вертикальная или под углом 45 градусов. У меня также есть моя настройка кода для обнаружения столкновения со стеной.
Я читал о точечных продуктах и нормалях, но я не могу понять, как их реализовать в Java/Android. Я полностью в тупике и чувствую, что теперь я искал все 10 страниц в Google в 10 раз. Я сгорел, пытаясь понять это, я надеюсь, что кто-то может помочь.
Извините заранее: я не знаю правильных типов Android. Я предполагаю, что у вас есть векторный тип со свойствами "x" и "y".
Если стена была горизонтальной, а текущая скорость была "вектором", то это было бы так же просто, как:
vector.y = -vector.y;
И вы оставите x-компонент один. Поэтому вам нужно сделать что-то аналогичное, но более общее.
Вы делаете это, подставляя идею нормальной линии (вектор, перпендикулярный прямой) для жесткого кодирования оси y (которая перпендикулярна горизонтали).
Так как нормаль ортогональна прямой, ее можно найти, повернув линию на 90 градусов. В 2d вектор (a, b) можно поворачивать на 90 градусов, преобразуя его в (-b, a). Следовательно, если у вас есть строка от (x1, y1) до (x2, y2), вы можете получить нормальный с помощью:
vectorAlongLine.x = x2 - x1;
vectorAlongLine.y = y2 - y1;
normal.x = -vectorAlongLine.y;
normal.y = vectorAlongLine.x;
Вы действительно не заботитесь о том, как долго была оригинальная строка (и это повлияет на вычисления позже, когда вы этого не захотите), поэтому вы хотите сделать нормальную длину длиной 1 независимо от ее текущей длины. Вы можете сделать это, разделив его на текущую длину. Так, например,
lengthOfNormal = Math.sqrt(normal.x*normal.x + normal.y*normal.y);
normal.x /= lengthOfNormal;
normal.y /= lengthOfNormal;
Используя теорему Пифагора, получим длину.
С горизонтальной линией, переворачивание по оси y было таким же, как (i) разработка того, какова протяженность вектора вдоль оси y; и (ii) вычитать эту сумму дважды - один раз, чтобы получить скорость в 0 в этом направлении, чтобы сделать ее отрицательной версией оригинала. То есть, это то же самое, что:
distanceAlongNormal = vector.y;
vector.y -= 2.0 * distanceAlongNormal;
Точечный продукт используется в общем случае для работы, насколько вектор распространяется вдоль нормали. Таким образом, он делает то же самое, что и vector.y делает для горизонтальной линии. Здесь вам, возможно, придется немного поверить вере. Это свойство точечного продукта, и вы можете убедить себя, проверив прямоугольный треугольник. Но пока, если бы у вас была горизонтальная линия, вы бы закончили с нормальным (0, 1). Так как точка-произведение будет:
vector.x * normal.x + vector.y * normal.y
Вы бы вычислили:
distanceAlongNormal = vector.x * 0.0 + vector.y * 1.0;
Это, очевидно, то же самое, что просто взять y-компонент.
Выработав расстояние по нормали, вы действительно захотите вычесть это количество раз в два раза. Единственный дополнительный шаг здесь - это умножение на нормаль, чтобы получить 2d-величину для вычитания. Это потому, что вы хотите вычесть в порядке нормы. Таким образом, полный код, основанный на норме, вычисленный ранее, следующий:
distanceAlongNormal = vector.x * normal.x + vector.y * normal.y;
vector.x -= 2.0 * distanceAlongNormal * normal.x;
vector.y -= 2.0 * distanceAlongNormal * normal.y;
Если вы не сделали нормальной длины 1, вам нужно разделить ее по длине, так как точечный продукт будет масштабировать значение DistanceAlongNormal на эту величину.
Это может пригодиться вам http://www.tonypa.pri.ee/vectors/tut07.html