Estoy tan sin matemáticas que duele, pero para algunos de ustedes esto debería ser pan comido. Quiero mover un objeto alrededor de otro a lo largo de sus edades o circunferencia en un camino circular simple. Por el momento, mi algoritmo de juego sabe cómo mover y colocar un sprite justo al borde de un obstáculo y ahora espera a que se mueva el siguiente punto, dependiendo de varias condiciones.
Entonces, el problema matemático aquí es cómo obtener las posiciones (aX, aY) y (bX, bY) , cuando conozco el Centro (cX, cY), la posición del objeto (oX, oY) y la distancia requerida para mover (d)
java
mathematics
Lumis
fuente
fuente
d
una distancia lineal o es un arco?Respuestas:
( CAVEAT: estoy usando dos aproximaciones aquí: la primera toma d como una longitud de arco, y la segunda lo toma como una longitud ortogonal. Ambas aproximaciones deberían ser buenas para valores relativamente pequeños de d, pero no cumplen la pregunta precisa como se aclara en los comentarios).
La matemática sobre esto, afortunadamente, es relativamente sencilla. En primer lugar, podemos encontrar el vector relativo desde nuestra posición central hasta nuestra posición actual:
Y una vez que tengamos este vector relativo, entonces podemos saber el radio del círculo en el que estamos trabajando al encontrar su longitud:
Además, desde nuestro vector relativo podemos encontrar el ángulo preciso en el que se encuentra la línea de cX a oX:
Ahora las cosas se ponen un poco más complicadas. En primer lugar, comprenda que la circunferencia de un círculo, es decir, la 'longitud del arco' de un arco con una medida angular de 2π, es 2πr. En general, la longitud del arco de un arco con una medida angular de θ a lo largo de un círculo de radio r es solo θr. Si tuviéramos que usar la d en su diagrama como la longitud del arco, y dado que conocemos el radio, podemos encontrar el cambio en theta para llevarnos a la nueva posición simplemente dividiendo:
Para el caso donde d necesita ser una distancia lineal, las cosas son un poco más complicadas, pero afortunadamente no mucho. Allí, d es un lado de un triángulo isoceles cuyos otros dos lados son el radio del círculo (de cX / cY a oX / oY y aX / aY respectivamente), y la división de este triángulo isoceles nos da dos triángulos rectángulos, cada uno de los cuales tiene d / 2 como un lado y radio como la hipotenusa; Esto significa que el seno de la mitad de nuestro ángulo es (d / 2) / radio, por lo que el ángulo completo es solo el doble de esto:
Observe que si elimina el asin de esta fórmula y cancela los 2, esto sería lo mismo que la última fórmula; Esto es lo mismo que decir que sin (x) es aproximadamente x para valores pequeños de x, lo cual es una aproximación útil para saber.
Ahora podemos encontrar el nuevo ángulo simplemente sumando o restando:
Una vez que tengamos el nuevo ángulo, podemos usar algunos trigonometría básica para encontrar nuestro vector relativo actualizado:
y desde nuestra posición central y nuestro vector relativo podemos (finalmente) encontrar el punto objetivo:
Ahora, con todo esto, hay algunas advertencias importantes a tener en cuenta. Por un lado, notará que esta matemática es principalmente de punto flotante, y de hecho casi tiene que serlo; intentar usar este método para actualizar en un bucle y redondear de nuevo a valores enteros en cada paso puede hacer todo, desde hacer que su círculo no se cierre (ya sea en espiral hacia adentro o hacia afuera cada vez que se da la vuelta al bucle) hasta no comenzarlo en el primer ¡sitio! (Si su d es demasiado pequeña, entonces puede descubrir que las versiones redondeadas de aX / aY o bX / bY están exactamente donde estaba su posición inicial oX / oY). Por otro lado, esto es muy costoso, especialmente por lo que está tratando de hacer; en general, si sabes que tu personaje se va a mover en un arco circular, debes planear todo el arco por adelantado y nomarque de fotograma a fotograma de esta manera, ya que muchos de los cálculos más caros aquí se pueden cargar por adelantado para reducir los costos. Otra buena manera de recortar los costos, si realmente desea actualizar de forma incremental de esta manera, es no utilizar trigonométricos en primer lugar; si d es pequeño y no necesita que sea exacto pero muy cercano, entonces puede hacer un 'truco' agregando un vector de longitud d a oX / oY, ortogonal al vector hacia su centro (tenga en cuenta que un el vector ortogonal a (dX, dY) viene dado por (-dY, dX)), y luego lo reduce a la longitud correcta. No explicaré este código tan paso a paso, pero espero que tenga sentido dado lo que has visto hasta ahora. Tenga en cuenta que 'reducimos' el nuevo vector delta implícitamente en el último paso,
fuente
Forma un triángulo usando los dos lados que ya tienes (un lado es de 'c' a 'o', el otro de 'o' a 'a'), y el tercer lado va de 'a' a 'c'. Todavía no sabes dónde está 'a', imagina que hay un punto allí por ahora. Necesitará trigonometría para calcular el ángulo del ángulo opuesto al lado 'd'. Tienes la longitud de los lados c <-> o y c <-> a, porque ambos son el radio del círculo.
Ahora que tiene la longitud de los tres lados de este triángulo que aún no puede ver, puede determinar el ángulo opuesto al lado 'd' del triángulo. Aquí está la fórmula SSS (lado a lado) si lo necesita: http://www.teacherschoice.com.au/maths_library/trigonometry/solve_trig_sss.htm
Usando la fórmula SSS tiene el ángulo (que llamaremos 'j') que es opuesto al lado 'd'. Entonces, ahora podemos calcular (aX, aY).
Asegúrate de que los ángulos que estás calculando estén siempre en radianes.
Si necesita calcular el radio del círculo, puede usar la resta del vector, restar el punto 'c' del punto 'o', luego obtener la longitud del vector resultante.
Algo como esto debería hacer, creo. No conozco Java, así que adiviné la sintaxis exacta.
Aquí está la imagen dada por el usuario
Byte56
para ilustrar cómo se vería este triángulo:fuente
Para hacer que obj2 gire alrededor de obj1, quizás intente:
fuente