( CAVEAT: sto usando due approssimazioni qui: la prima prende d come lunghezza d'arco, e la seconda la prende come lunghezza ortogonale. Entrambe queste approssimazioni dovrebbero essere buone per valori relativamente piccoli di d, ma non soddisfano la domanda precisa come chiarito nei commenti.)
La matematica su questo, per fortuna, è relativamente semplice. Prima di tutto, possiamo trovare il vettore relativo dalla nostra posizione centrale alla nostra posizione corrente:
deltaX = oX-cX;
deltaY = oY-cY;
E una volta che abbiamo questo vettore relativo, allora possiamo conoscere il raggio del cerchio su cui stiamo lavorando trovandone la lunghezza:
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
Inoltre, dal nostro vettore relativo possiamo trovare l'angolo preciso in cui si trova la linea da cX a oX:
curTheta = atan2(deltaX, deltaY);
Ora le cose diventano un po 'più complicate. Prima di tutto, capire che la circonferenza di un cerchio - cioè la "lunghezza dell'arco" di un arco con una misura angolare di 2π - è 2πr. In generale, la lunghezza dell'arco di un arco con una misura angolare di θ lungo un cerchio di raggio r è solo θr. Se dovessimo usare la d nel diagramma come lunghezza dell'arco e poiché conosciamo il raggio, possiamo trovare il cambiamento in theta per portarci nella nuova posizione semplicemente dividendo:
deltaTheta = d/radius; // treats d as a distance along the arc
Nel caso in cui d debba essere una distanza lineare, le cose sono un po 'più complicate, ma fortunatamente non molto. Lì, d è un lato di un triangolo isocele i cui altri due lati sono il raggio del cerchio (rispettivamente da cX / cY a oX / oY e aX / aY), e bisecare questo triangolo isocele ci dà due triangoli retti, ognuno dei quali ha d / 2 come un lato e raggio come ipotenusa; questo significa che il seno di metà del nostro angolo è (d / 2) / raggio, e quindi l'angolo completo è solo il doppio di questo:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
Nota come se prendessi il asin da questa formula e cancellassi i 2, questo sarebbe lo stesso dell'ultima formula; questo equivale a dire che sin (x) è approssimativamente x per piccoli valori di x, che è un'approssimazione utile da sapere.
Ora possiamo trovare il nuovo angolo semplicemente aggiungendo o sottraendo:
newTheta = curTheta+deltaTheta; // This will take you to aX, aY. For bX/bY, use curTheta-deltaTheta
Una volta che abbiamo il nuovo angolo, possiamo usare alcuni trig di base per trovare il nostro vettore relativo aggiornato:
newDeltaX = radius*cos(newTheta);
newDeltaY = radius*sin(newTheta);
e dalla nostra posizione centrale e dal nostro vettore relativo possiamo (finalmente) trovare il punto target:
aX = cX+newDeltaX;
aY = cY+newDeltaY;
Ora, con tutto ciò, ci sono alcuni grandi avvertimenti di cui essere consapevoli. Per uno, noterai che questa matematica è per lo più a virgola mobile, e in effetti deve quasi esserlo; provare ad usare questo metodo per aggiornare in un ciclo e arrotondare indietro a valori interi in ogni passaggio può fare di tutto, dal non chiudere il cerchio (o spirale verso l'interno o verso l'esterno ogni volta che fai il giro del ciclo) al non avviarlo nel primo posto! (Se la tua d è troppo piccola, potresti scoprire che le versioni arrotondate di aX / aY o bX / bY sono esattamente dove si trovava la posizione iniziale oX / oY.) Per un altro, questo è molto costoso, specialmente per quello che sta cercando di fare; in generale, se sai che il tuo personaggio si muoverà in un arco circolare, dovresti pianificare in anticipo l'intero arco e nonspuntalo da un fotogramma all'altro in questo modo, poiché molti dei calcoli più costosi qui possono essere caricati frontalmente per ridurre i costi. Un altro buon modo per ridurre i costi, se si desidera davvero aggiornare in modo incrementale in questo modo, è di non utilizzare il trig in primo luogo; se d è piccolo e non è necessario che sia esatto ma molto vicino, puoi fare un "trucco" aggiungendo un vettore di lunghezza d a oX / oY, ortogonale al vettore verso il tuo centro (nota che un il vettore ortogonale a (dX, dY) è dato da (-dY, dX)), quindi lo riduce alla giusta lunghezza. Non spiegherò questo codice così passo dopo passo, ma spero che abbia senso visto quello che hai visto finora. Tieni presente che "riduciamo" implicitamente il nuovo vettore delta nell'ultimo passaggio,
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 distanza lineare o è un arco?