Movimento curvo tra due punti


15

Qual è una buona tecnica per consentire a un oggetto di spostarsi tra i punti con un bel movimento curvo?

La posizione finale potrebbe anche essere in movimento, come la traiettoria di un missile homing.

Risposte:


11

Supponendo che tu voglia che questa sia una cosa fotogramma per fotogramma (in cui il bersaglio potrebbe persino muoversi), e non una traiettoria pre-calcolata, in realtà è incredibilmente semplice:

Ogni frame confronta il vettore-velocità del missile con il vettore (posizione target - posizione missile ) ; cioè, il vettore che punta dal missile al bersaglio. Ogni fotogramma, se i due vettori non hanno la stessa direzione, ruota il vettore di veloity leggermente verso l'altro vettore, quindi ogni fotogramma del missile si avvicina un po 'di più al suo bersaglio.

È possibile determinare se ruotare in senso orario o antiorario osservando il segno del prodotto incrociato tra i due vettori.


[Modifica] Codice XNA-ish (non ho XNA per testarlo):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Si noti che, poiché rotationAngleha solo tre possibili valori, tutti i possibili valori di Matrix.CreateRotationZ(rotationAngle)possono essere memorizzati nella cache in modo da non doverlo chiamare ogni frame.


Potresti forse fornire qualche pseudo codice dato che sono nuovo in tutto questo. Attualmente sto lavorando solo nella seconda dimensione in modo da eliminare alcune complicazioni.
anonymouse

@anonymouse: certo, prova questo
BlueRaja - Danny Pflughoeft

15

Esistono due tecniche possibili:

La prima tecnica consiste nell'eseguire una simulazione basata su frame . Questo è buono se stai facendo qualcosa come un missile homing nel gameplay, che non deve colpire esattamente il tuo obiettivo.

In questo caso, si desidera tenere traccia della posizione e della velocità dell'oggetto. Ogni fotogramma osserva la direzione verso il bersaglio e la direzione di movimento corrente e regola la velocità in modo appropriato.

Se si attiva istantaneamente la velocità, il missile colpirà sempre il bersaglio. Ma se si regola la velocità di una piccola quantità per ogni fotogramma, il missile si curverà verso il bersaglio - e se si curva abbastanza lentamente, il bersaglio potrebbe schivarlo.

La seconda tecnica consiste nell'utilizzare un metodo parametrico . Questo è utile per animare cose in cui vuoi colpire il tuo obiettivo in modo preciso e prevedibile. In questo caso di solito prendi "tempo" come parametro e lo metti in una funzione di qualche tipo.

Un insieme particolarmente utile di funzioni sono le equazioni del movimento che hai appreso nella fisica delle scuole superiori. Applicandoli su entrambi gli assi è possibile ottenere traiettorie balistiche. Con un po 'di matematica, puoi determinare i parametri iniziali per colpire un bersaglio - anche uno in movimento, se si muove in modo prevedibile.

XNA offre anche numerose funzioni di interpolazione e di movimento curvo. Dai un'occhiata alla documentazione diVector2 e perMathHelper . Questi forniscono alcune funzioni di interpolazione che puoi usare e persino combinare per fare cose interessanti. Ad esempio, sparare un missile: Lerp(interpolare lineare) la posizione del missile dal suo punto iniziale a una posizione bersaglio, e anche eseguire quella posizione bersaglio da un bersaglio iniziale alla posizione reale (cambiante) dell'oggetto bersaglio. Questo ti darà un piacevole effetto "aggancio".

(Esistono anche alcune funzioni per la produzione di curve, ad esempio: CatmulRom , Hermite. Tuttavia, sono probabilmente più difficili da utilizzare con successo con un bersaglio in movimento.)

Se cerchi "allentamento" (nel contesto dell'animazione), puoi ottenere alcune funzioni di interpolazione più interessanti che possono darti effetti interessanti come l'accelerazione.

Ora, puoi dire che questa tecnica dà alcuni risultati strani mentre il tuo bersaglio si muove. Tuttavia, in pratica, fintanto che il proiettile si muove più velocemente del bersaglio, di solito sembra a posto. Se si tratta di un problema, probabilmente dovresti comunque utilizzare una tecnica basata su frame.


3

Potresti cercare onde sinusoidali o eventualmente curve di Bezier . Non so se l'approccio dell'onda sinusoidale sia normale, ma non riesco a capire perché sarebbe così povero.


L'uso delle curve di Bezier con B-Splines consente una rappresentazione abbastanza accurata di qualsiasi curva. Se hai bisogno di precisione, le spline Cubic Hermit sono leggermente più accurate. Ricorda, a volte l'imprecisione fornisce un gradito tocco di organicità.
doppelgreener

+1 per le curve di Bezier. Per l'uso descritto, è probabilmente il più semplice e il più controllabile.
ggambett,

1

Puoi dare un'occhiata a Steering Behaviors, come definito da Craig Reynolds: http://red3d.com/cwr/steer/

Questo è spesso usato nell'intelligenza artificiale per far muovere gli NPC verso il loro obiettivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.