Tuki & Giuli - giochi da console

Home Codice Articoli Libri

Scorrimento laterale dello sfondo in un videogame

Tuki-3 è un classico side-scrolling game, cioè un gioco di vecchia generazione in cui il protagonista deve percorrere una strada e il giocatore lo segue guardandolo da una posizione laterale. La prospettiva del giocatore è quindi diversa da quella che si ha quando si osserva il gioco da un punto di vista fisso, come accade ad esempio in Tuki-1 dove il campo di battaglia, come spesso si chiama lo sfondo su cui avviene il gioco, rimane fermo mentre si muove il personaggio protagonista del gioco.
Quando invece il giocatore segue il personaggio, si ha che ai suoi occhi lo sfondo cambia in conseguenza della posizione raggiunta dal personaggio. In questa circostanza, per simulare la sensazione che si ha nella vita reale in circostanze analoghe, per esempio quando si osserva il panorama dal finestrino di un treno, è necessario muovere gli oggetti dello sfondo con velocità diverse in base allo loro distanza dal punto di osservazione del giocatore. Qui è bene fare una precisazione, che con punto di osservazione non si intede la posizione della persona fisica che sta giocando, ma del giocatore virtuale, la cui distanza dal personaggio è decisa dal regista del gioco o, se previsto, modificabile per mezzo di controlli come joystick o pulsanti.
In questo articolo, vediamo come calcolare la velocità di scorrimento relativo degli oggetti di sfondo in base alla distanza dalla camera, cioè dal giocatore virtuale, e un esempio di implementazione in linguaggio C basato su grafica ASCII.

Prospettiva e geometria

In questo paragrafo vediamo insieme le considerazioni geometriche necessarie per sviluppare la formulazione della velocità degli oggetti di sfondo. Immaginiamo di osservare un gioco a scorrimento laterale dall'alto in modo da vedere anche la camera nascosta che riprende la scena durante il gioco. Immaginiamo che nello sfondo del gioco siano presenti uno smeraldo e un rubino.
Come si vede in figura, lo smeraldo e il rubino, vengono mappati nel campo di vista in base alla loro posizione orrizontale e alla distanza verticale dalla camera. Quando la camera avanza verso destra con una certa velocità che indichiamo con $v_c$, nel campo di vista, le due pietre risultano spostate verso sinistra e come si vede, l'entità dello spostamento dipende ancora dalla loro distanza vericale dalla camera. In figura si è indicato con $d_1$ la distanza del rubino dal piano di osservazione dove sta la camera, e con $d_2$ la distanza dello smeraldo.
Dalla figura osserviamo che un oggetto, fermo rispetto al suolo, che si trovi a distanza $d$ dalla camera, si muove apparentemente da un estremo all'altro del campo di vista in ragione di uno spostamento $\Delta x=x_2-x_1$ della camera. Supponendo che lo spostamento della camera avvenga in un intervallo di $\Delta t$ secondi, si ha che la velocità apparente dell'oggetto è data da: $$ v_o(d)=\frac{1}{\Delta t} $$ dove l'unità di misura è da intendersi in campo di vista al secondo. Lo spostamento fisico $\Delta x$ della camera, necessario a provocare lo spostamento di un intero campo di vista è dato da: $$ \Delta x= 2 \times d\ sin(\alpha/2) $$ dove $\alpha$ è l'apertura angolare della camera. Visto che tale spostamento avviene nel tempo $\Delta t$, la velocità della camera al suolo è data da: $$ v_c=\frac{2 \times d\ sin(\alpha/2)}{\Delta t} $$ da cui: $$ \Delta t=\frac{2 \times d\ sin(\alpha/2)}{v_c} $$ Sostituendo quindi questa espressione di $\Delta t$ nella formulazione di $v_o$, e considerando che la velocità dell'oggetto ha verso opposto a quella della camera, otteniamo: $$ v_o(d)=-\frac{1\times v_c}{2\times d\ sin(\alpha/2)} $$ La formulazione ottenuta può essere analizzata al variare di $d$. Come si vede per $d=0$ la velocità apparente sarebbe infinita, come è intuitivo, mentre per tutti i piani che si trovano ad una distanza diversa da 0, la velocità decresce in modo direttamente proporzionale alla distanza e, come è intuitivo, per un piano all'infinito, come le così dette stelle fisse, essa è zero.
Potrebbe essere interessante valutare anche la velocotà di oggetti animati e non fissi sullo sfondo. In questo caso, se l'oggetto ha una velocità $v_o$ rispetto al suolo abbiamo che la sua velocità apparente è data dalla somma della velocità al suolo con la velocità rispetto alla camera: $$ v_o(d)=v_o+-\frac{1\times v_c}{2\times d\ sin(\alpha/2)} $$

Il codice C

In questo paragrafo vediamo un esempio in C dove viene implementato uno scorrimento di tre piani dell'orizzonte. In questo codice, usiamo il terminal a caratteri come sistema di display. Questo dispositivo un tempo era la normale interfaccia video, oggi è disponibile come emulazione software nella console Linux, nel Terminal di Mac OS e nella Win 32 Console. Il modello di lavoro del terminale è molto semplice. Ogni terminale (software o hardware) corrisponde ad un foglio a quadretti. Ogni quadretto è identificato da una riga e da una colonna e su ogni quadretto possiamo disegnare un carattere tra quelli predefiniti per il terminale. I primi terminali come il VT52, nacquero con un set di caratteri molto limitato, poi i modelli successivi come il VT220 offrirono più set di caratteri e oggi, sugli emulatori sono disponibili praticamente tutti.
Questo sistema grafico ha due limiti principali. Il primo è che è possibile realizzare solo immagini grossolane ottenute da disposizioni regolari dei caratteri predefiniti. Di seguito vediamo un esempio di un albero e di una montagna e di un cespuglio. ### _/\__ ##### _/ \ ##### / v \_ # / vvv \ # / vvvvv \ Il secondo è che è un sistema ad un singolo strato, come la tela do un pittore.
Nel mondo reale i tre soggetti appartengono a tre piani differenti con il ciuffo in primo piano, l'albero dietro e la montagna all'orizzonte. Nel modello grafico del terminale invece, essi appartengono ad un unico piano, nel senso che ad ogni casella (incrocio di riga e colonna) è possibile assegnare un solo carattere. Se due soggetti si trovano sullo stesso asse ottico, bisogna decidere se rappresentare i caratteri dell'uno o dell'altro. Per esempio se il ciuffo d'erba si trovasse sull'asse ottico dell'albero, per ogni cella, bisognerebbe decidere se stampare il carattere del v o il carattere # ### _/\__ ##### _/ \ ##### / \v # / vvv # / vvvvv Quindi, per implementare in C un programma che mostri lo scorrimento di più piani si deve:
  1. Calcolare la velocità del piano in base alla distanza dallla camera.
  2. Creare una immagine da mostrare che sia la somma dei tre piani.
Abbiamo già visto come si calcola la velocità di un oeggetto che si trovi a distanza $d$ dalla camera, quindi rimane solo da vedere come creare una immagine che sia la somma dei tre piani. Per farlo bisogna pensare ad una regola che per ogni cella stabilisca quele dei tre piani deve essere visibile. Nell'esempio che segue ho implementato una regola molto semplice. I piani hanno un ordi di precedenza che è inversamente proporzionale alla loro distanza dalla camera, quindi più un piano è vicino, maggiore è la sua precedenza o diritto di mostrare il contenuto della cella. Il carattere spazio (cioè il codice ASCII 32) però fa eccezione, perchè qui stabiliamo che equivale all'aria e quindi è trasparente. La regole quindi è molto facile da implementare: si parte con il piano più lontano e si passa al piano successivo rimpiazzando tutti i caratteri del piano più lontano con quelli del piano più vicino, purchè questi non corrispondano al carattere spazio. In tal caso si lascia il carattere del piano più indietro. Si ripete la procedura finché si sono processati tutti i piani (tre in questo esempio).
Con queste semplici regole, vediamo come qualche riga di codice C (più di duecento a dire il vero) sia possibile creare un esempio completo senza uso di librerie esterne. Buon divertimento!

Risultato

Il codice riportato sopra, produce un array di stringhe, una per ogni riga dell'immagine, ad ogni iterazione. Le stringhe vengono stampate sullo schermo e la successione delle immagini crea l'effetto del movimento. Nel video qui sotto è mostrato il risultato finale.

Conclusioni