( 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:
deltaX = oX-cX;
deltaY = oY-cY;
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:
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
Además, desde nuestro vector relativo podemos encontrar el ángulo preciso en el que se encuentra la línea de cX a oX:
curTheta = atan2(deltaX, deltaY);
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:
deltaTheta = d/radius; // treats d as a distance along the arc
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:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
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:
newTheta = curTheta+deltaTheta; // This will take you to aX, aY. For bX/bY, use curTheta-deltaTheta
Una vez que tengamos el nuevo ángulo, podemos usar algunos trigonometría básica para encontrar nuestro vector relativo actualizado:
newDeltaX = radius*cos(newTheta);
newDeltaY = radius*sin(newTheta);
y desde nuestra posición central y nuestro vector relativo podemos (finalmente) encontrar el punto objetivo:
aX = cX+newDeltaX;
aY = cY+newDeltaY;
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,
deltaX = oX-cX; deltaY = oY-cY;
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
orthoX = -deltaY*d/radius;
orthoY = deltaX*d/radius;
newDeltaX = deltaX+orthoX; newDeltaY = deltaY+orthoY;
newLength = sqrt(newDeltaX*newDeltaX+newDeltaY*newDeltaY);
aX = cX+newDeltaX*radius/newLength; aY = cY+newDeltaY*radius/newLength;
d
una distancia lineal o es un arco?