Как рассчитать угол отскока? - PullRequest
61 голосов
/ 21 февраля 2009

Я немного поигрался с этим, но просто не могу понять.

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

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

Является ли решение, которое я ищу, достаточно продвинутым?

Есть ли относительно простой способ сделать это?

Ответы [ 9 ]

185 голосов
/ 21 февраля 2009

Вы можете подумать, что поскольку ваши стены выровнены по осям координат, имеет смысл написать код специального случая (для вертикальной стены отрицание координаты скорости X; для горизонтальной стены отрицание координаты y скорости). Тем не менее, как только у вас получится хорошо работать с вертикальными и горизонтальными стенами, возможно, вы подумаете следующее: «А как насчет стен под произвольными углами?» Поэтому стоит подумать об общем случае с самого начала.

В общем случае предположим, что ваша ракета имеет скорость v и поражает стену с нормальной поверхностью n .

Missile with vector v about to obliquely hit a wall with surface normal n.

Разделить v на компоненты u перпендикулярно стене и w параллельно ей.

Right-angled triangle with hypotenuse for v, short side u parallel to wall and long side w parallel to wall.

Где:

u = ( v · n / n · n ) n
w = v - u

Здесь v · n является точечным произведением векторов v и n . Смотрите ссылку для объяснения того, как его вычислить. Точечное произведение n · n соответствует квадрату длины вектора нормали; если вы всегда сохраняете свои нормали в виде векторов единиц , тогда n · n = 1 и вы можете опустить деление.

После отскока на компонент движения параллельно стене воздействует трение f , а на компонент, перпендикулярный стене, влияет упругость, которая может быть задана в виде коэффициент реституции r .

Таким образом, скорость после столкновения равна v ' = f w - r u . В elastic идеально упругом, без трения столкновении, v ′ = w - u ; то есть движение отражается относительно нормали в точке столкновения, как на диаграмме, приведенной в ответе Билла.

Этот подход также работает в трех измерениях.

(Очевидно, это очень упрощенное понятие подпрыгивания; оно не учитывает момент импульса или деформацию. Но для многих видов видеоигр такое упрощение вполне подходит.)

66 голосов
/ 21 февраля 2009

Я думаю, что более простой способ сделать это - использовать скорость ракеты вместо вычисления углов. Допустим, у вас есть ракета, у которой xVelocity и yVelocity представляют ее движение по горизонтали и вертикали. Эти скорости могут быть положительными или отрицательными для представления влево, вправо, вверх или вниз.

  • Если ракета попадает на верхнюю или нижнюю границу, поменяйте знак yVelocity.
  • Если ракета попадает в левую или правую границу, поменяйте знак xVelocity.

Это сохранит движение в противоположной оси.

Заимствование изображения из Ответ ChrisF , допустим, ракета стартует в положении I.

Angle of Reflection

При положительных значениях xVelocity и yVelocity (в 2D-графике, как правило, справа и вниз, как правило, положительные) ракета будет двигаться в указанном направлении. Давайте просто присвоим значения

xVelocity = 3
yVelocity = 4

Когда ракета попадает в стену в позиции C , ее xVelocity не должна измениться, но ее yVelocity следует обратить на -4, чтобы она двигалась назад в направлении вверх, но продолжает идти направо.

Преимущество этого метода заключается в том, что вам нужно только отслеживать ракеты xPosition, yPosition, xVelocity и yVelocity. Используя только эти четыре компонента и частоту обновления вашей игры, ракета всегда будет перерисовываться в правильном положении. Как только вы столкнетесь с более сложными препятствиями, которые не находятся под прямыми углами или движутся, работать со скоростями X и Y будет намного проще, чем с углами.

9 голосов
/ 21 февраля 2009

Для идеальных частиц (и света) угол отражения равен углу падения, как показано на этой диаграмме (из commons.wikimedia.org).

Angle of Reflection

Выполните поиск по «углу отражения» (без кавычек) в Google.

Это немного сложнее, если принять во внимание эластичность и материал объекта и препятствий;)

6 голосов
/ 18 июня 2015

У меня была эта проблема, единственный путь, который я нашел, это разделение осей столкновения!

Попробуйте:

x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);

if (x < 0 || x > canvas.width) {
     angle = 180 - angle;   
}
else if (y < 0 ||y > canvas.height) {
     angle = 360 - angle; 
}

Надеюсь, это вам поможет!

5 голосов
/ 21 февраля 2009

В дополнение к конкретному физическому вопросу, который вы задаете, я бы порекомендовал книгу «Начало математики и физики для программистов игр» Венди Шталер. Я нашел это весьма полезным для моих проектов программирования игр / физики.

Код, сопровождающий книгу, - C ++, но если вы знаете C #, преобразование будет довольно легко выполнить.

Хорошего вам!

3 голосов
/ 21 февраля 2009

180-а не будет работать во всех случаях, если только вы не выполняете отскок на верхней поверхности при увеличении X.

Одно из направлений - форумы XNA или пример кода XNA. Это C #, и это для создания игр. Я не утверждаю, что вы хотите создавать свои игры в XNA, но это отличный инструмент, и он бесплатный.

3 голосов
/ 21 февраля 2009

Совсем не сложно - псевдокод:

angleObjectHitWall = a;
bounceAngle = 180-a;

Конечно, это очень простой расчет, и он совершенно не имеет значения, если вы начнете учитывать такие факторы, как материал, гравитация, стены, которые не являются прямыми и т. Д. *

0 голосов
/ 09 июля 2015
if(!Collide(Missle, Mainchar)){
(Velocity.x)*-1;
(Velocity.y)*-1;
}

Работает и просто, удачи.

0 голосов
/ 21 февраля 2009

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

Я предлагаю прочитать эту статью в Википедии, чтобы получить основную идею о глубине вашего вопроса.

Если вы только хотите, чтобы это выглядело "правдоподобно", я бы не стал слишком беспокоиться об этом и использовал бы ответ Билла Ящерицы , однако, если вы хотите все исправить, у вас будет довольно приключение. Пусть это тебя не пугает! Удачи!

...