Заранее извиняюсь: я не знаю правильных типов 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.
Вычислив расстояние по нормали, вы на самом деле хотите затем вычесть это количество в два раза больше нормального. Единственным дополнительным шагом здесь является умножение на нормаль, чтобы вычесть 2-мерную величину. Это потому, что вы хотите вычесть в порядке нормального. Таким образом, полный код, основанный на нормальном вычисленном ранее, выглядит так:
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 на эту величину.