Я так не в математике, что это больно, но для некоторых из вас это должно быть просто пирогом. Я хочу переместить объект вокруг другого по его возрасту или окружности по простому круговому пути. На данный момент мой игровой алгоритм знает, как перемещать и размещать спрайт только на краю препятствия, и теперь он ожидает, когда следующая точка будет двигаться, в зависимости от различных условий.
Таким образом, математическая проблема здесь заключается в том, как получить (aX, aY) и (bX, bY) позиции, когда я знаю центр (cX, cY), положение объекта (oX, oY) и расстояние, необходимое для перемещения (d)
java
mathematics
Lumis
источник
источник
d
линейное расстояние или дуга?Ответы:
( ПРЕДУПРЕЖДЕНИЕ: я использую здесь два приближения: первое принимает d в качестве длины дуги, а второе принимает ее в качестве ортогональной длины. Оба этих приближения должны быть хороши для относительно небольших значений d, но они не удовлетворяют точный вопрос, уточненный в комментариях.)
Математика в этом, к счастью, относительно проста. Прежде всего, мы можем найти относительный вектор от нашей центральной позиции к нашей текущей позиции:
И когда у нас есть этот относительный вектор, мы можем узнать радиус круга, над которым мы работаем, найдя его длину:
Более того, из нашего относительного вектора мы можем найти точный угол, под которым находится линия от cX до oX:
Теперь все становится немного сложнее. Прежде всего, следует понимать, что окружность круга, то есть «длина дуги» дуги с угловой мерой 2π, составляет 2πr. В общем, длина дуги дуги с угловой мерой θ вдоль окружности радиуса r равна просто θr. Если бы мы использовали d на вашей диаграмме в качестве длины дуги, и, поскольку мы знаем радиус, мы можем найти изменение в тэте, чтобы получить нас в новой позиции, просто разделив:
Для случая, когда d должно быть линейным расстоянием, все немного сложнее, но, к счастью, немного. Здесь d - это одна сторона равнобедренного треугольника, две другие стороны которого являются радиусом окружности (от cX / cY до oX / oY и aX / aY соответственно), и деление этого равнобедренного треугольника дает нам два прямоугольных треугольника, каждый из которых имеет d / 2 в качестве одной стороны и радиус в качестве гипотенузы; это означает, что синус половины нашего угла равен (d / 2) / радиусу, и поэтому полный угол всего в два раза больше этого:
Обратите внимание, что если вы удалите asin из этой формулы и отмените 2, это будет то же самое, что и последняя формула; это то же самое, что сказать, что sin (x) приблизительно равен x для малых значений x, что полезно знать.
Теперь мы можем найти новый угол, просто сложив или вычтя:
Как только у нас будет новый угол, мы можем использовать базовый триггер, чтобы найти наш обновленный относительный вектор:
и из нашей центральной позиции и нашего относительного вектора мы можем (наконец) найти целевую точку:
Теперь, со всем этим, есть некоторые большие предостережения, о которых нужно знать. Во-первых, вы заметите, что эта математика в основном с плавающей запятой, и на самом деле она почти обязана; Попытка использовать этот метод для обновления в цикле и округления до целочисленных значений на каждом шаге может сделать все, начиная от того, что ваш круг не замыкается (либо вращается внутрь, либо наружу каждый раз, когда вы проходите цикл), до того, как он не запустился в первом цикле. место! (Если ваш d слишком маленький, то вы можете обнаружить, что округленные версии aX / aY или bX / bY находятся именно там, где была ваша начальная позиция oX / oY.) С другой стороны, это очень дорого, особенно из-за того, что он пытается делать; в общем, если вы знаете, что ваш персонаж будет двигаться по дуге окружности, вы должны планировать всю дугу заранее, а неОтметьте это от кадра к кадру, как это, так как многие из самых дорогих вычислений здесь могут быть загружены заранее, чтобы сократить расходы. Еще один хороший способ сократить расходы, если вы действительно хотите производить поэтапное обновление, как это, - это вообще не использовать триг; если d мало, и вам не нужно, чтобы он был точным, а просто очень близким, то вы можете сделать «трюк», добавив вектор длины d к oX / oY, ортогональный к вектору к вашему центру (обратите внимание, что вектор, ортогональный (dX, dY), определяется как (-dY, dX)), а затем сжимается до нужной длины. Я не буду объяснять этот код шаг за шагом, но, надеюсь, он будет иметь смысл, учитывая то, что вы видели до сих пор. Обратите внимание, что на последнем шаге мы неявно сокращаем новый дельта-вектор,
источник
Сформируйте треугольник, используя две стороны, которые у вас уже есть (одна сторона от 'c' до 'o', другая от 'o' до 'a'), а третья сторона переходит от 'a' к 'c'. Вы еще не знаете, где находится «а», просто представьте, что сейчас есть смысл. Вам понадобится тригонометрия для расчета угла, противоположного стороне 'd'. У вас есть длина сторон c <-> o и c <-> a, потому что они оба - радиус круга.
Теперь, когда у вас есть длина трех сторон этого треугольника, которую вы еще не видите, вы можете определить угол, противоположный стороне 'd' треугольника. Вот формула SSS (боковая сторона), если вам нужно: http://www.teacherschoice.com.au/maths_library/trigonometry/solve_trig_sss.htm
Используя формулу SSS, вы получите угол (который мы назовем «j»), противоположный стороне «d». Итак, теперь мы можем вычислить (aX, aY).
Убедитесь, что рассчитываемые углы всегда в радианах.
Если вам нужно вычислить радиус круга, вы можете использовать векторное вычитание, вычесть точку 'c' из точки 'o', а затем получить длину полученного вектора.
Я полагаю, что-то подобное должно сделать. Я не знаю Java, поэтому я угадал точный синтаксис.
Вот изображение, данное пользователем,
Byte56
чтобы проиллюстрировать, как может выглядеть этот треугольник:источник
Чтобы заставить obj2 вращаться вокруг obj1, попробуйте:
источник