Potresti strutturare la cosa in questo modo:
- Definisci delle funzioni che determinano la posizione P(k, x0, y0, x1, y1) partendo da (x0, y0) fino a (x1, y1) in funzione di un parametro generico k compreso nell'intervallo chiuso [0.0, 1.0]
- Definisci una funzione di interpolazione temporale F(t, t0, t1) che prende in input un parametro t in [t0, t1], e da in output un parametro k in [0.0, 1.0]
le animazioni 2D più semplici si possono pensare come la composizione (x, y) = P( F(t, t0, t1), x0, y0, x1, y1), dove:
(x,y) sono le coordinate correnti dell'oggetto
t è il tempo corrente in secondi
t0 è il tempo in cui inizierà l'animazione (costante)
t1 è il tempo in cui finirà l'animazione (costante)
(x0,y0) è la posizione di partenza (costante)
(x1,y1) è la posizione di arrivo (costante)
Quelle che ho indicato come costanti potrebbero in realtà variare ad ogni passo, ma complicheresti solamente l'utilizzo della libreria senza un reale vantaggio (potrebbe essere utile nei giochi, ma non in una semplice GUI).
Ecco un esempio concreto:
Voglio far muovere un oggetto in linea retta da A = (3, 5) a B = (12, -4), a velocità costante, in un tempo di 3 secondi con un'attesa iniziale di 5 secondi.
La funzione di interpolazione temporale dovrà avere un primo tratto orizzontale, lungo 5 secondi, poi un segmento di retta lungo 3 secondi in cui sale da 0.0 fino a 1.0 e poi un altro tratto orizzontale infinitamente lungo.
Quindi:
k = F(t, t0, t1) =
if (t < t0) return 0.0;
else if (t>t1) return 1.0;
else return (t - t0) / (t1 - t0);
La funzione geometrica P invece sarà invece una semplice retta parametrica in [0.0, 1.0], del tipo:
(x,y) = P( k, x0, x1, y0, y1) =
return (x = (x0 * k) + x1 * (1.0 - k) ; y = (y0 * k) + y1 * (1.0 - k)
Se vuoi ottenere un moto che parte lento e poi accelera, devi semplicemente sostituire nella F() la formula dell'ultimo ramo, inserendo una parabola parametrica invece di una retta, cioè basta banalmente elevare al quadrato quella piccola formuletta.
Se vuoi farla decelerare basta scambiare di posto t0 con t1, creando quindi una parabola a testa in giù.
Se vuoi farla rimbalzare potresti usare il valore assoluto di una funzione seno che moltiplica a sua volta un'esponenziale negativa, e così via.
Analogamente puoi sostituire la funzione P con l'equazione parametrica di un arco di cerchio, un'ellisse, una parabola, una spirale, o quello che vuoi (per spirali e archi ti consiglio di convertire le coordinate in forma polare).
Se crei delle classi che derivano da un paio di classi astratte chiamate Traiettoria e Interpolatore, puoi implementare questi algoritmi ed esporre solo i parametri necessari nei costruttori (se vuoi farli costanti) oppure predisporre dei metodi per cambiarli al volo durante l'animazione.
Ovviamente, essendo basate sul tempo reale, se chiami la funzione 100 volte in un secondo avrai 100 piccoli incrementi, mentre se la chiami 1 volta in 3 secondi (l'esempio durava 3 secondi) ti farà un unico grande balzo, mantenendo comunque la velocità dell'animazione del tutto indipendente dalla quantità di chiamate di update, e quindi indipendente dalla velocità della macchina. Chiaramente dovrai fornire a queste funzioni un parametro temporale letto dal clock di sistema per funzionare correttamente.
Se hai difficoltà a scrivere le funzioni matematiche necessarie, puoi sperimentare con questo sito
http://www.wolframalpha.com/ oppure procurarti un buon testo di geometria analitica :-)
Buon divertimento :ugeek: