Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Interpolazione

L'interpolazione è un'operazione comune nella programmazione grafica, utilizzata per fondere o passare tra due valori. L'interpolazione si può utilizzare anche per rendere più fluido un movimento, una rotazione, ecc. È utile familiarizzarsi con questa operazione per ampliare i propri orizzonti come sviluppatore di giochi.

L'idea di base è che si desidera passare da A a B. Il valore t rappresenta gli stati intermedi.

Ad esempio, se t è 0, allora lo stato è A. Se t è 1, allora lo stato è B. Qualsiasi valore intermedio è un'interpolazione.

Tra due numeri reali (in virgola mobile), un'interpolazione può essere descritta come:

interpolation = A * (1 - t) + B * t

E spesso semplificata in:

interpolation = A + (B - A) * t

Il nome di questo tipo di interpolazione, che trasforma un valore in un altro a una velocità costante, è "lineare". Quindi, quando si sente parlare di interpolazione lineare, ci si riferisce a questa formula.

Esistono altri tipi di interpolazioni, che non saranno trattati qui. Si consiglia di leggere successivamente la pagina Bezier.

Interpolazione vettoriale

Anche i tipi di vettori (Vector2 e Vector3) possono essere interpolati; e sono dotati di funzioni utili per farlo Vector2.lerp() e Vector3.lerp().

Per l'interpolazione cubica, ci sono anche Vector2.cubic_interpolate() e Vector3.cubic_interpolate(), che eseguono un'interpolazione di stile Bezier.

Ecco un esempio di pseudo-codice per passare dal punto A al punto B tramite l'interpolazione:

var t = 0.0

func _physics_process(delta):
    t += delta * 0.4

    $Sprite2D.position = $A.position.lerp($B.position, t)

Ciò produrrà il seguente movimento:

../../_images/interpolation_vector.gif

Interpolazione di trasformazioni

È anche possibile interpolare intere trasformazioni (assicurandosi che abbiano una scala uniforme o, almeno, la stessa scala non uniforme). Per fare ciò, si può utilizzare la funzione Transform3D.interpolate_with().

Ecco un esempio di trasformazione di una scimmia da Position1 a Position2:

../../_images/interpolation_positions.png

Utilizzando il seguente pseudo-codice:

var t = 0.0

func _physics_process(delta):
    t += delta

    $Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)

E di nuovo, produrrà il seguente movimento:

../../_images/interpolation_monkey.gif

Smoothing motion

L'interpolazione si può utilizzare per seguire fluidamente un valore di destinazione in movimento, come una posizione o una rotazione. A ogni frame, lerp() sposta il valore attuale verso il valore di destinazione di una percentuale fissa della differenza rimanente tra i due valori. Il valore attuale si sposterà fluidamente verso la destinazione, rallentando man mano che si avvicina. Ecco un esempio di un cerchio che segue il mouse attraverso un'interpolazione fluida:

const FOLLOW_SPEED = 4.0

func _physics_process(delta):
    var mouse_pos = get_local_mouse_position()

    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, delta * FOLLOW_SPEED)

Ecco come appare:

../../_images/interpolation_follow.gif

Questo è utile per smussare i movimenti della telecamera, per far sì che gli alleati seguano il giocatore (assicurandosi che restino entro una certa distanza) e per molti altri pattern comuni di gioco.

Nota

Nonostante l'utilizzo di delta, la formula utilizzata sopra dipende dal frame rate, perché il parametro weight di lerp() rappresenta una percentuale della differenza rimanente nei valori, non una quantità assoluta da cambiare. In _physics_process(), questo di solito va bene perché ci si aspetta che la fisica mantenga un frame rate costante, e dunque delta dovrebbe rimanere costante.

Per una versione di interpolazione fluida indipendente dal frame rate che si può utilizzare anche in process(), utilizzare invece la seguente formula:

const FOLLOW_SPEED = 4.0

func _process(delta):
    var mouse_pos = get_local_mouse_position()
    var weight = 1 - exp(-FOLLOW_SPEED * delta)
    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, weight)

Derivare questa formula va oltre lo scopo di questa pagina. Per una spiegazione, consultare Improved Lerp Smoothing o guardare Lerp Smoothing is broken.