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.

Parallasse 2D

Introduzione

L'effetto parallasse serve per simulare la profondità facendo muovere le texture a velocità diverse rispetto alla telecamera. Godot fornisce il nodo Parallax2D per ottenere questo effetto. Tuttavia, può comunque essere facile confondersi, quindi questa pagina fornisce descrizioni dettagliate di alcune proprietà e come correggere alcuni errori comuni.

Nota

Questa pagina spiega come utilizzare Parallax2D, che è consigliato utilizzare al posto dei nodi ParallaxLayer e ParallaxBackground.

Per cominciare

Il nodo parallasse supporta l'aggiunta di nodi che renderizzano cose come figli, quindi è possibile utilizzare uno o più nodi per comporre ogni livello. Per cominciare, aggiungi ciascun nodo o i nodi che vuoi far scorrere indipendentemente come figli del proprio nodo parallasse. Assicurati che l'angolo in alto a sinistra delle texture utilizzate si trovi all'incrocio (0, 0), come nell'immagine qui sotto. Consulta la sezione positioning per capire perché questo è importante.

../../_images/2d_parallax_size_viewport.webp

La scena qui sopra utilizza una texture preparata per le nuvole più alte in uno Sprite2D, ma si potrebbero altrettanto facilmente utilizzare più nodi distanziati tra loro per comporre il livello.

Scala di scorrimento

Il pilastro dell'effetto parallasse è la proprietà scroll_scale. Funziona come un moltiplicatore della velocità di scorrimento, consentendo ai livelli di muoversi a una velocità diversa rispetto alla telecamera per ogni asse impostato. Un valore di 1 fa scorrere il nodo parallasse alla stessa velocità della telecamera. Se vuoi che l'immagine appaia più lontana durante lo scorrimento, utilizza un valore inferiore a 1, con 0 che lo arresta completamente. Se vuoi che un elemento appaia più vicino alla telecamera, utilizza un valore superiore a 1, rendendo lo scorrimento più veloce.

La scena qui sopra è composta da cinque livelli. Alcuni buoni valori per scroll_scale potrebbero essere:

  • (0.7, 1) - Forest

  • (0.5, 1) - Hills

  • (0.3, 1) - Lower Clouds

  • (0.2, 1) - Higher Clouds

  • (0.1, 1) - Sky

Il video qui sotto mostra come questi valori influiscono sullo scorrimento durante il gioco:

Ripetizione infinita

Parallax2D fornisce un effetto in più che dà alle texture l'illusione di ripetersi all'infinito. repeat_size indica al nodo di agganciare la sua posizione in avanti o indietro quando la telecamera scorre del valore impostato. Questo effetto si ottiene aggiungendo una singola ripetizione a tutti gli elementi canvas figli, scostati da tale valore. Mentre la telecamera scorre tra l'immagine e la sua ripetizione, questa torna invisibilmente indietro, dando l'impressione di un'immagine in ciclo.

../../_images/2d_parallax_scroll.gif

Essendo un effetto delicato, è facile per gli utenti meno esperti commettere errori durante la configurazione. Analizziamo quindi il "come" e il "perché" di alcuni problemi comuni riscontrati dagli utenti.

Poor sizing

L'effetto di ripetizione infinita è più facile da gestire quando hai un'immagine progettata per ripetersi senza cuciture e ha le stesse dimensioni o è più grande della viewport prima di impostare repeat_size. Se non riesci a ottenere risorse progettate per questo compito, ci sono altre cose che potresti fare per preparare al meglio l'immagine in termini di dimensioni.

Ecco un esempio di una texture troppo piccola per la sua viewport:

../../_images/2d_parallax_size_bad.webp

Possiamo notare che le dimensioni della viewport sono 500x300, ma quelle della texture sono 288x208. Se impostiamo repeat_size sulle dimensioni della nostra immagine, l'effetto di ripetizione infinita non scorre correttamente perché la texture originale non copre la viewport. Se impostiamo repeat_size sulle dimensioni della viewport, abbiamo un grande spazio vuoto. Cosa possiamo fare?

Rendere la viewport più piccola

La soluzione più semplice è impostare la viewport in modo che abbia le stesse dimensioni o sia più piccola delle texture. In Project Settings > Display > Window, modifica le impostazioni Viewport Width e Viewport Height così da corrispondere allo sfondo.

../../_images/2d_parallax_size_viewport.webp

Scale the Parallax2D

If you're not aiming for a pixel-perfect style, or don't mind a little blurriness, you may opt to scale the textures larger to fit your screen. Set the scale of the Parallax2D, and all child textures scale with it.

Scale the child nodes

Similar to scaling the Parallax2D, you can scale your Sprite2D nodes to be large enough to cover the screen. Keep in mind that some settings like Parallax2D.repeat_size and Sprite2D.region_rect do not take scaling into account, so it's necessary to adjust these values based on the scale.

../../_images/2d_parallax_size_scale.webp

Ripetere le texture

Puoi anche cominciare con il piede giusto preparando i nodi figli in un passo precedente del processo. Se hai uno Sprite2D che vorresti ripetere, ma è troppo piccolo, puoi fare quanto segue per farlo ripetere:

Qui sotto, puoi vedere che ripetendo l'immagine due volte, questa diventa grande abbastanza da coprire l'intero schermo.

../../_images/2d_parallax_size_repeat.webp

Posizionamento inadeguato

È comune che gli utenti impostino per errore tutte le loro texture in modo che siano centrate su (0,0):

../../_images/2d_parallax_single_centered.webp

Questo crea problemi con l'effetto di ripetizione infinita e si dovrebbe evitare. Il "canvas di ripetizione infinita" inizia in (0,0) e si espande verso il basso e verso destra fino alle dimensioni del valore di repeat_size.

../../_images/2d_parallax_single_expand.webp

Se le texture sono centrate sull'incrocio (0,0), il canvas a ripetizione infinita è coperto solo parzialmente, quindi si ripete solo parzialmente.

Would increasing repeat_times fix this?

Aumentare repeat_times tecnicamente funzionerebbe in alcuni scenari, ma è una soluzione bruta e non il problema per cui è stata progettata (ne parleremo tra poco). Una soluzione migliore, per prima cosa, è capire come funziona l'effetto ripetizione e impostare le texture di parallasse in modo appropriato.

Per prima cosa, verifica che le texture non si estendano sulle parti negative del canvas. Assicurati che le texture utilizzate nei nodi parallasse si adattino al "canvas a ripetizione infinita" a partire da (0,0). In questo modo, se Parallax2D.repeat_size è impostato correttamente, dovrebbe apparire più o meno così, con un singolo ciclo dell'immagine delle stesse dimensioni o più grande della viewport:

../../_images/2d_parallax_repeat_good_norect.webp

If you think of how the image scrolls across the screen, it starts by displaying what's inside the red rectangle (determined by repeat_size), and when it reaches what's inside the yellow rectangle it zips the image forward to give the illusion of scrolling forever.

../../_images/2d_parallax_repeat_good.webp

If you have the image positioned away from the "infinite repeat canvas", when the camera reaches the yellow rectangle, half of the image is cut off before it jumps forward like in the image below:

../../_images/2d_parallax_repeat_bad.webp

Scroll offset

If your parallax textures are already working correctly, but you prefer it to start at a different point, Parallax2D comes with a scroll_offset property used to offset where the infinite repeat canvas starts. As an example, if your image is 288x208, setting the scroll_offset to (-144,0) or (144,0) allows it to begin halfway across the image.

Numero di ripetizioni

Ideally, following this guide, your parallax textures are large enough to cover the screen even when zoomed out. Until now, we have had a perfectly fitting 288x208 texture inside of a 288x208 viewport. However, problems occur when we zoom out by setting the Camera2D.zoom to (0.5, 0.5):

../../_images/2d_parallax_zoom_single.webp

Even though everything is correctly set for the viewport at the default zoom level, zooming out makes it smaller than the viewport, breaking the infinite repeat effect. This is where repeat_times can help out. Setting a value of 3 (one extra repeat behind and in front), it is now large enough to accommodate the infinite repeat effect.

../../_images/2d_parallax_zoom_repeat_times.webp

If these textures were meant to be repeated vertically, we would have specified a y value for the repeat_size. The repeat_times would automatically add a repeat above and below as well. This is only a horizontal parallax, so it leaves an empty block above and below the image. How do we solve this? We need to get creative! In this example, we stretch the sky higher, and grass sprite lower. The textures now support the normal zoom level and zooming out to half size.

../../_images/2d_parallax_zoom_repeat_adjusted.webp

Schermo diviso

La maggior parte dei tutorial per creare un gioco a schermo diviso in Godot comincia scrivendo un piccolo script per assegnare il Viewport.world_2d della prima SubViewport alla seconda, così da condividere la loro visualizzazione. Spesso sorgono domande su come condividere un effetto parallasse tra i due schermi.

The parallax effect fakes a perspective by moving the positions of different textures in relation to the camera. This is understandably problematic if you have multiple cameras, because your textures can't be in two places at once!

Questo è comunque possibile clonando i nodi parallasse nella seconda (o terza o quarta) SubViewport. Ecco come appare una configurazione per un gioco a due giocatori:

../../_images/2d_parallax_splitscreen.webp

Of course, now both backgrounds show in both SubViewports. What we want is for each parallax to only show in their corresponding viewport. We can achieve this by doing the following:

  • Leave all parallax nodes at their default visibility_layer of 1.

  • Imposta la proprietà canvas_cull_mask della prima SubViewport in modo da includere solo gli strati 1 e 2.

  • Fa lo stesso per la seconda SubViewport ma usa gli strati 1 e 3.

  • Assegna ai nodi parallasse della prima SubViewport un genitore comune e imposta il suo visibility_layer su 2.

  • Fai lo stesso per i nodi parallasse della seconda SubViewport, ma usa un livello di 3.

Come funziona? Se un elemento canvas ha un visibility_layer che non corrisponde al canvas_cull_mask della SubViewport, nasconderà tutti i figli, anche se corrispondono. Sfruttiamolo a nostro vantaggio, permettendo alle SubViewport di bloccare il rendering dei nodi parallasse il cui genitore non ha un visibility_layer supportato.

Vedere l'anteprima nell'editor

Prima della 4.3, la raccomandazione era di posizionare ogni livello nel proprio ParallaxBackground, abilitare la proprietà follow_viewport_enabled e scalare il singolo livello. Questo metodo è sempre stato difficile da implementare correttamente, ma è ancora realizzabile utilizzando un CanvasLayer invece di un ParallaxBackground.

Nota

Un'altra raccomandazione è il componente aggiuntivo "Parallax2D Preview" di KoBeWi. Offre diverse modalità di anteprima ed è molto utile!