Tratto da: Game Maker Tutorial – Adding Depth to Games – Written by Mark Overmars – Copyright © 2007 YoYo Games Ltd – www.yoyogames.com/…/threed.zip
I giochi veri sono 3D, non è vero? In realtà non è vero.
Tutti i giochi producono, sullo schermo del computer, immagini 2D… possono sembrare 3D ma non significa che lo siano.
Ma allora cosa si intende quando si dice che un gioco è 3D? Si tratta di una domanda difficile.
La risposta è: la combinazione di diversi fattori
- come il gioco è stato creato
- l’immagine che il giocatore vede
- il modo con cui il giocatore controlla il gioco.
In questo tutorial ti sarà spiegato come dare ai tuoi giochi un aspetto 3D e come aggiungere profondità ai tuoi giochi.
Ma non vogliamo utilizzare funzioni grafiche 3D per questo.
Descriveremo delle tecniche più semplici come parallasse, scalatura, trasparenza, viste isometriche.
Quasi tutto può essere ottenuto tramite drag-and-drop di azioni di GameMaker sebbene in qualche punto sarà necessario unpezzetto di codice GML.
Per seguire il tutorial dovresti avere qualche esperienza con GameMaker ma non è necessario che tu conosca GML a fondo.
Introduzione
I moderni giochi 3D modellano il mondo del gioco con oggetti 3D.
Per disegnare le scene utilizzano schede grafiche 3D.
Dato un punto di vista, cioè la posizione dalla quale il giocatore osserva il mondo del gioco, la scheda crea l’immagine corretta tenendo conto di aspetti come illuminazione, rimozione di superfici nascoste (oggetti che non si vedono non dovrebbero essere disegnati), effetti atmosferici…
Con l’hardware attuale questo produce esperienze di gioco spettacolari ma c’è un prezzo per tutto questo.
Modellare un mondo 3D con oggetti 3D e realizzare le animazioni per i personaggi richiede molte competenze e tanto tempo tempo.
Inoltre la logica del gioco, i comportamenti delle entità, il controllo delle collisioni, le animazioni, … sono molto più difficili che nei giochi 2D.
Il risultato è che la produzione di giochi 3D moderni richiede risorse enormi, personale numeroso e specializzato e arriva a costare milioni di dollari.
E comunque la maggior parte di questi giochi presentano errori, in particolare nei movimenti della camera e dei personaggi e nel controllo delle collisioni.
Questo significa che i giochi 3D sono fuori dalla tua portata? Bene, sì e no.
GameMaker non supporta direttamente mondi 3D, anche se ci sono funzioni per la grafica 3D (e su questo c’è un tutorial specifico).
Ma tutti i giochi apparentemente 3D fino al 1995 e molti altri anche dopo non utilizzano mondi 3D.
Per esempio giochi come Age of Empires e Command and Conquer (eccetto le versioni più recenti) non utilizzano mondi 3D.
Sono giochi così detti isometrici.
Essi utilizzano sprite per rappresentare le scene e i personaggi e utilizzano alcuni trucchi relativamente semplici per dare la senzazione all’utente di essere in un mondo 3D.
Questo tutorial spiegherà le basi di giochi come questi.
…
Spero che questo tutorial ti convinca che con GameMaker è possibile realizzare molti tipi diversi di giochi che hanno un evidente look and feel 3D.
Come sempre l’unico limite è l’immaginazione.
Se vuoi realizzare giochi veramente 3D dovresti scaricare il tutorial ufficiale First Person Shooter.
Ingannare la mente
Come far sembrare 3D qualcosa?
Il concetto di base è ingannare la nostra mente e farle credere che le immagini che vede sono 3D.
Allora, il problema diventa perché pensiamo che un immagine che vediamo è 3D.
Giocano un ruolo in questo un certo numero di fattori.
Gli oggetti che si trovano dietro altri oggetti sono invisibili (anche parzialmente)
Questo è un aspetto importante.
Normalmente noi non vediamo attraverso gli oggetti solidi.
Quando per esempio un oggetto è parzialmente nascosto da una roccia, l’osservatore capisce subito che l’oggetto si trova dietro la roccia.
In questo modo l’osservatore ottiene una visuale migliore delle relazioni 3D esistenti tra gli oggetti.
Per realizzare un mondo 3D dobbiamo quindi visualizzare gli (le parti degli) oggetti che sono attualmente visibili.
Questo processo si chiama rimozione delle superfici nascoste.
Le schede grafiche 3D rimuovono automaticamente le superfici nascoste ma, siccome GameMaker opera con mondi 2D, dobbiamo occuparcene noi.
Il modo per ottenerlo è disegnare le sprite degli oggetti nell’ordine corretto.
Un oggetto che si trova più lontano viene disegnato per primo.
Il prossimo oggetto viene disegnato sopra di esso, e così via.
Siccome gli oggetti più vicini sono disegnati sopra gli oggetti che stanno dietro, essi copriranno (anche parzialmente) gli altri oggetti.
Possiamo indicare questo ordine in GameMaker impostando la variabile depth per i diversi oggetti.
Le istanze di oggetti con profondità maggiore saranno disegnate prima degli oggetti con profondità minore e quindi appariranno dietro.
Gli oggetti trasparenti lasciano vedere cosa c’è dietro
Quando gli oggetti sono parzialmente trasparenti, attraverso di essi vedi cosa c’è dietro.
Utilizzare la trasparenza in combinazione con il corretto ordine di profondità aumenta ulteriormente la sensazione di profondità.
Gli oggetti che si trovano più lontano sembrano più piccoli
Chiaramente, più gli oggetti sono lontani più appaiono piccoli.
Questo dà una forte sensazione di distanza e quindi una migliore sensazione 3D.
Questo si può ottenere cambiando la dimensione delle sprite a seconda della loro profondità.
Puoi realizzare sprite di dimensioni diverse oppure disegnare le sprite con un fattore di scala.
Quando un oggetto si muove verso l’osservatore deve diventare più grande.
In un mondo 3D, questo dà una forte sensazione di movimento.
La scalatura deve essere fatta con attenzione altrimenti potrebbe dare l’effetto opposto.
Gli oggetti che si trovano più lontano sembrano sfocati
Quando gli oggetti sono più lontani non riesci a vederli più così bene.
Questo vale anche al contrario: se un’immagine appare sfocata, la interpretiamo come se fosse più lontana.
Quindi, aggiungere alle immagini che si trovano più lontano un misto tra velatura e sfocatura aggiunge un maggiore senso della distanza.
Anche questo si può ottenere utilizzando sprite diverse per la stessa istanza, in funzione della sua profondità.
Gli oggetti che si trovano più lontano sembra che si muovano più piano
Un oggetto lontano impiega più tempo per attraversare la nostra vista da sinistra verso destra rispetto a un oggetto vicino che sembra passarci davanti più veloce.
Puoi utilizzare questo fenomeno per dare un’indicazione sulla profondità degli oggetti.
Un aspetto particolare di questo fenomeno sarà trattato più avanti come scorrimento con parallasse.
Inoltre, gli oggetti che si avvicinano o si allontanano da te cambiano posizione sullo schermo più lentamente.
Normalmente la velocità verticale, rispetto allo schermo, dovrebbe essere più piccola della velocità orizzontale.
Gli oggetti presentano un’ombra
Gli oggetti proiettano le ombre.
Le ombre proiettate da oggetti su altri oggetti sono difficili da calcolare ma è relativamente semplice realizzare ombre sul pavimento.
Anche se non si ottiene un’ombra precisa è comunque positivo avere una piccola macchia scura sotto un oggetto.
Questo dà l’impressione che l’oggetto stia sul pavimento.
Devi fare le cose con cura, per esempio tutti gli oggetti, o nessuno, hanno l’ombra e tutte le ombre hanno la stessa dimensione e la stessa direzione.
Nella figura si intuisce che il personaggio al centro si trova sul terreno mentre quello a destra ci sta saltando sopra.
Le linee parallele sembra che si incontrino in un punto
Come probabilmente sai, in un mondo 3D le linee parallele, alla distanza, si incontrano in un punto.
Per esempio, i due lati di una strada alla distanza si toccano.
Per essere più precisi, la nostra vista genera una proiezione prospettica.
In qualche modo deforma gli oggetti a seconda della loro profondità ma è proprio questa deformazione che crea la sensazione 3D.
L’immagine a sinistra mostra una proiezione senza prospettiva.
Le linee verticali sono parallele.
Nell’immagine a destre utilizziamo una trasformazione prospettica e come risultato le linee si toccheranno da qualche parte alla distanza.
Questo da una sensazione migliore di 3D.
Le proiezioni prospettiche sono importanti nei giochi 3D ma sfortunatamente non sono facili da ottenere con le sprite.
Per questo i giochi basati sull’uso delle sprite normalmente non utilizzano trasformazioni prospettiche.
Per limitarne gli effetti spesso usano una proiezione con un angolo di 45 gradi.
Cioè, in questi giochi non si guarda dritto ma un po’ di lato.
Come risultato l’effetto delle linee parallele è meno evidente e anche l’osservatore ne è meno influenzato.
Questo fenomeno è alla base dei giochi isometrici.
Se guardi attentamente la figura vedi che le linee sono ancora parallele (che è sbagliato…) ma comunque appare di nuovo più 3D della prima.
La creazione di giochi isometrici è possibile in GameMaker e più avanti mostreremo come ottenerla.
Scorrimento con parallasse
Tratto da: www.yoyogames.com/…/threed.zip > parallax.gmk.
Come detto prima, gli oggetti lontani si muovono più lentamente degli oggetti che sono vicini all’osservatore.
In questo tutorial utilizzeremo questa osservazione.
Comunque, la utilizzeremo soltanto per creare sfondi scorrevoli lateralmente.
Come dovresti sapere puoi aggiungere sfondi ai tuoi livelli in GameMaker.
Molto spesso un livello contiene proprio uno sfondo ma è possibile avere sfondi multipli.
Naturalmente, perché siano visibili è necessario che siano parzialmente trasparenti oppure che coprano solo una parte del livello.
Dando agli sfondi più bassi velocità orizzontali più basse dai al giocatore l’impressione che questi sfondi si trovino più lontano.
Non puntiamo alla qualità grafica ma soltanto a dimostrare l’effetto.
Prima di tutto utilizziamo due sfondi.
Il primo visualizza alcune montagne alla distanza.
Questo sfondo sarà sistemato in cima al livello e scorre verso sinistra con una velocità molto bassa di -1.
Imposta questa velocità nella finestra delle proprietà del livello.
Tassella orizzontalmente ma non verticalmente.
Il secondo sfondo rappresenta la strada.
È molto piccolo, è posizionato alla base del livello e si muove più velocemente (-4).
Di nuovo tasselliamo orizzontalmente.
Posizioniamo un’auto sulla strada ma non ha bisogno di muoversi.
Siccome la strada si muove sotto di essa abbiamo già l’illusione del movimento.
Siccome la strada si muove più velocemente delle montagne hai l’impressione che le montagne siano molto lontane.
Per aggiungere ancora più profondità alla scena aggiungiamo degli alberi.
Utilizziamo 3 sprite di 3 dimensioni diverse
Per ognuno di questi alberi creiamo un oggetto.
Per assicurarci che l’albero piccolo stia dietro l’albero medio che a sua volta stia dietro l’albero grande dobbiamo assegnare loro profondità diverse.
- L’albero grande lo sistemeremo vicino alla strada e nell’evento Create gli daremo l’azione di muoversi verso sinistra con speed=4, come la strada.
- L’albero medio sarà sistemato un po’ più indietro con speed=3.
- All’albero piccolo gli daremo speed=2.
Ne sistemeremo alcuni alle posizioni appropriate nel livello.
Per assicurarci che essi riappaiano a destra quando scompaiono a sinistra aggiungiamo un evento Outside Room nel quale includiamo un’azione Wrap Screen con selezionato Wrap horizontally.
Ecco il risultato
Si tratta solamente di una dimostrazione e non di un gioco.
Per trasformarlo in gioco dovresti dare al giocatore la possibilità di sterzare e per esempio aggiungere del traffico da evitare.
Lo scorrimento con parallasse è molto utile per esempio nei giochi di piattaforma.
In questo caso dovresti adattare le velocità degli sfondi scorrevoli alla velocità (orizzontale) del protagonista controllato dal giocatore.
Proiezioni parallele
Tratto da: www.yoyogames.com/…/threed.zip > parallel.gmk.
Sebbene i veri giochi 3D dovrebbero usare le proiezioni prospettiche descriviamo prima come le proiezioni parallele possano essere comunque utilizzate per ricreare una sensazione di profondità.
In una proiezione parallela la dimensione degli oggetti rimane la stessa indipendentemente dalla distanza.
Anche le linee parallele rimangono parallele.
Questo rende tutto più facile perché le sprite hanno una dimensione fissa (anche se possono essere scalate).
Chiaramente, una proiezione parallela produce una distorsione della vista.
Per limitare questa distorsione ci assicureremo che il giocatore non veda gli oggetti che sono molto lontani.
In questo modo non noterà gli errori.
Otteniamo questo guardando il mondo sotto un angolo (normalmente si usa un angolo di circa 45°).
In questo modo un mondo di quadrati ci apparirà come un mondo di rettangoli
Per un’immagine di sfondo l’effetto è questo
Creare un’immagine di questo tipo è semplice.
Semplicemente scaliamo l’immagine soltanto nella direzione verticale.
Dimostreremo questo approccio con un piccolo demo nel quale il giocatore controlla un personaggio che può muoversi in un mondo contenente degli alberi.
Ci sono tre cose da gestire in un’applicazione di questo tipo:
- La rimozione delle superfici nascoste deve essere fatta correttamente.
Quindi quando il personaggio si trova dietro un albero dovrebbe essere disegnato prima dell’albero in modo da renderlo parzialmente invisibile. - La velocità del personaggio deve essere trattata correttamente.
Il movimento avanti-indietro deve essere più lento del movimento destra-sinistra. - E la cosa più difficile, trattare correttamente le collisioni.
Rimozione delle superfici nascoste
Come dovresti sapere ogni sprite ha un’origine.
Di default è l’angolo in alto a sinistra della sprite.
Quando sistemiamo un’istanza di un oggetto in una posizione particolare stiamo in realtà posando la sprite corrispondente con la sua origine in quella posizione.
Quando si lavora con un mondo tridimensionale è più facile prendere come origine dell’oggetto la posizione dove si appoggia sul terreno.
Per tutte le sprite imposteremo l’origine a questa posizione.
Quindi per esempio per il personaggio che cammina nella foresta impostiamo l’origine della sprite alla posizione (16,30).
Inoltre abbiamo disabilitato Precise collision checking e modifichiamo la maschera tramiteBounding box – Manual a una piccola area alla base del personaggio.
Così le collisioni non avverranno con l’intera sprite ma soltanto con il piccolo rettangolo.
Useremo questo più avanti.
Il nostro personaggio sarà rappresentato tramite 4 sprite diverse; una per ognuna delle 4 direzioni in cui può camminare.
Chiaramente imposteremo gli stessi valori per ciascuna.
Adesso quale dovrebbe essere la profondità?
In molti casi l’ordine con cui gli oggetti devono essere disegnati è lo stesso con cui si trovano sul terreno.
Quindi impostando l’origine come specificato prima la coordinata y dell’istanza determina l’ordine.
Le istanze con una coordinata y bassa sono vicine alla cima della finestra e devono essere disegnate prima di quelle con una coordinata y maggiore.
Quindi una coordinata y più frande deve corrispondere a una profondità più piccola.
Si può ottenere questo impostando depth a –y utilizzando l’azione Set Variable.
Per gli oggetti statici, come gli alberi del nostro esempio, è necessario farlo una sola volta nell’evento Create.
Per gli oggetti dinamici, come il personaggio del nostro esempio, dobbiamo farlo a ogni passo.
Sarebbe meglio utilizzare l’evento End Step per essere sicuri che tutti gli altri eventi siano stati elaborati prima di aggiornare depth.
Movimento del personaggio
Possiamo muovere il personaggio utilizzando comunemente le frecce direzionali.
In ciascun evento del tasto freccia impostiamo il movimento nella direzione corretta e impostiamo la sprite corretta per l’istanza.
Inoltre, per avere un’animazione della sprite durante il movimento e nessuna animazione quando il personaggio non è in movimento utilizziamo la variabile image_speed.
Questa variabile specifica con quale velocità devono essere visualizzate le sottoimmagini dell’animazione.
Impostandola a 1 si ha l’animazione a velocità normale.
Impostandola a 0 si fermerà l’animazione.
Allora ogni volta che l’utente preme un tasto freccia scegliamo la sprite corretta e impostiamo image_speed a 1 utilizzando l’azione Change Sprite
Utilizziamo -1 per subimage per evitare un cambiamento di sottoimmagine quando ci stiamo già muovendo nella stessa direzione.
Quando il giocatore rilascia il tasto impostiamo image_speed a 0 utilizzando l’azioneSet Variable.
Facciamo lo stesso se avviene una collisione.
Tutto questo non ha niente a che fare con i giochi 3D.
In questo modo si gestisce normalmente il movimento del personaggio in molti giochi.
L’unica cosa che dobbiamo trattare accuratamente in un gioco tridimensionale è la variazione della velocità.
Utilizziamo una velocità 3 per il movimento orizzontale e una velocità 2, più bassa, per il movimento verticale.
Devi fare delle prove con questi numeri per ottenere l’effetto migliore per il tuo gioco.
Collisioni
Le collisioni avvengono normalmente quando le sprite si sovrappongono parzialmente.
Questo funziona nei giochi 2D ma non funziona nei giochi 3D.
Quando il personaggio si trova davanti a un albero le sprite si sovrappongono ma non c’è collisione.
Quindi abbiamo bisogno di un’altra area che definisca la collisione.
Quest’area corrisponde normalmente all’area dell’istanza sul terreno.
Soltanto quando i piedi del personaggio si sovrappongono alla base del tronco dell’albero c’è una vera collisione.
Il modo più semplice per ottenere questo è di definire un bounding box molto piccolo in basso per tutte le sprite e non utilizzare precise collision checking.
Una collisione viene segnalata soltanto quando si sovrappongono parzialmente i due bounding box, che è proprio quello che vogliamo.
Per le figure più complesse un piccolo rettangolo in basso potrebbe non rappresentare correttamente l’area di collisione.
In questi casi utilizziamo un’altra funzionalità di GameMaker.
Un oggetto può avere una maschera diversa rispetto alla sprite utilizzata per rappresentare l’istanza.
Allora possiamo realizzare una seconda sprite che ha la forma dell’area di collisione richiesta e utilizzarla come maschera di collisione.
Utilizzeremo questo approccio più avanti per realizzare un gioco isometrico.
Adesso abbiamo tutti gli ingredienti per il gioco 3D che vogliamo realizzare.
Per fare in modo che tutto sembri più bello utilizziamo un insieme di tessere per tassellare lo sfondo.
Le scaliamo come spiegato prima per ottenere la dimensione 48x24.
Riempiamo lo sfondo.
Aggiungiamo allo sfondo anche delle tessere di muri.
Per provocare le collisioni utilizziamo una tecnica standard nella quale definiamo un oggetto muro solido invisibile e sistemiamo istanze di questo oggetto sopra i muri dello sfondo.
In questo modo il personaggio si fermerà perché si scontra con queste istanze invisibili mentre il giocatore vedrà soltanto il piacevole sfondo davanti a esse.
Il livello
Utilizzeremo una vista nel livello in modo che il giocatore veda solo una parte del mondo.
Per aumentare la sensazione di profondità impostiamo la vista a 400x200, così facendo scaliamo di nuovo con un fattore 1/2 nella direzione verticale.
In molti giochi questa proporzione viene ottenuta aggiungendo un pannello delle informazioni sotto il mondo scorrevole.
Questo è il motivo per cui in questo tipo di giochi è meglio posizionare il pannello delle informazioni alla base dello schermo piuttosto che di lato.
Il demo finale appare così:
Sprite scalate
Tratto da: www.yoyogames.com/…/threed.zip > scaling.gmk.
Nel tutorial precedente abbiamo utilizzato la proiezione parallela.
Se fissi la vista in alto rispetto al terreno in una direzione fissa e se mostri una piccola parte della scena funziona abbastanza bene.
Ma se vogliamo avere una vista in prima persona oppure una vista più vicina al terreno allora è necessaria una proiezione prospettica.
La dimensione degli oggetti deve diminuire quando sono più lontani.
Ma come possiamo ottenerlo?
Nel tutorial sullo scorrimento con parallasse abbiamo utilizzato alberi di 3 dimensioni diverse.
Questo funziona quando gli alberi rimangono a distanze prefissate ma in un vero gioco 3D il giocatore deve potersi avvicinar e a essi, e quindi la dimensione dovrebbe cambiare continuamente.
Dovremmo creare un numero enorme di sprite diverse, una per ogni dimensione, ma questo comporterebbe un uso eccessivo di memoria.
Potresti comunque pensare di farlo per gli oggetti veramente importanti del gioco perché si ottiene la migliore qualità grafica.
Per le altre istanze possiamo utilizzare il ridimensionamento delle sprite.
In questo tutorial mostreremo come farlo utilizzando un semplice esempio nel quale il giocatore deve evitare degli alberimentre si muove in una foresta.
La pima sprite che ci serve è quella per l’albero.
Ne utilizziamo una.
Impostiamo manualmente una piccolaBounding box per la sprite alla base dell’albero.
Questa è la sola parte dove vogliamo che avvengano le collisioni con il personaggio.
Utilizziamo ancora le montagne come sfondo, ma questa volta senza scorrimento, horizontal speed=0.
Piuttosto utilizziamo un ampio livello con width=2000.
Sistemiamo il personaggio, per il quale ci serve una sprite, nel mezzo del livello in basso.
Utilizzeremo una vista di dimensioni 480x320 e posizioneremo il personaggio inizialmente al centro impostando correttamente i parametri e impostando che la vista deve seguirlo, con Object following …
Il personaggio si muoverà a sinistra e a destra quando il giocatore premerà le frecce direzionali sinistra e destra.
Chiaramente dobbiamo evitare di muoverci troppo a sinistra o a destra.
Come punteggio utilizziamo il tempo che il giocatore resiste…
Quindi nell’evento Step del personaggio aggiungiamo 1 a score.
Quando il personaggio provoca una collisione con un albero visualizziamo la classifica e facciamo ripartire il gioco.
Ci rimane ancora l’albero.
Ci sono 3 aspetti che dobbiamo trattare: la dimensione, la posizione sullo schermo, la profondità.
- Gli alberi appaiono alla coordinata y=180.
Nell’evento End step scaliamo la sprite utilizzando la sua y per aggiornare le variabili image_xscale eimage_yscale.
Utilizziamo un fattore prossimo a 0 quando y è 180 e aumenta quando l’albero si muove verso il basso.
Per essere precisi utilizziamo un valore di scala (y-178)/100.
Se vuoi, puoi fare degli esperimenti, ma assicurati che sia sempre positivo.
Potresti anche usare l’azione Transform Sprite della Standard Edition. - Gestiamo la profondità tramite depth=-y nell’evento Step.
Questo significa che gli alberi più vicini alla parte bassa dello schermo e che sono più vicini all’osservatore hanno ygrande e saranno disegnati sopra gli altri, come vogliamo.
Anche il personaggio deve avere una profondità adeguata per stare nella posizione corretta tra gli alberi(-300). - Controllare il movimento è più difficile del previsto.
Potremmo muoverli con velocità costante ma si noterà come un rallentamento quando si avvicinano, perché dovrebbero in realtà accelerare.
Quindi dobbiamo aumentare la velocità verticale.
Inoltre si devono spostare di lato quando si avvicinano, perché le linee parallele dovrebbero convergere all’infinito.
Quindi la velocità orizzontale deve essere adattata alla posizione dell’albero rispetto al centro della vista.
Per questo utilizziamo del codice nell’evento Step.
Osserva l’uso delle variabili locali xoff and yoff.
I numeri sono sperimentali, prova a cambiarli.
Per finire il gioco mancano ancora poche cose: distruggere gli alberi quando scompaiono sotto, aggiungere un oggetto controllore per l’apparizione degli alberi (di più quando il punteggio cresce).
Utilizza questo gioco come base di partenza per i tuoi giochi.
Adesso puoi utilizzare lo stesso meccanismo per realizzare un gioco completo di tipo first person shooter.
In questi giochi l’oggetto principale ha una posizione e un orientamento nel mondo del gioco.
Per tutte le altre istanze nella scena devi calcolare la posizione relativa e la direzione rispetto allo sguardo del giocatore e la loro distanza.
La distanza determina l’ordine nel disegno e la dimensione, come sopra.
Per evitare di disegnare troppe istanze normalmente si disegnano solo quelle abbastanza vicine.
Tuttavia per questo tipo di giochi è conveniente l’uso di funzioni 3D come quelle contenute nella Standard Edition di GameMaker .
Questo argomento è trattato in un altro tutorial.
Giochi isometrici
Tratto da: www.yoyogames.com/…/threed.zip > isometric.gmk
Per ultimo ci occupiamo di un tipo di gioco molto popolare: il gioco isometrico.
Molti dei giochi più popolari del recente passato sono isometrici.
Esempi sono Age of Empires, Diablo,Command and Conquer, SimCity, e molti altri giochi di strategia e di simulazione.
Questi giochi sono in linea di principio realizzabili con GameMaker (ma considera che la realizzazione di questi giochi commerciali richiede anni di lavoro di personale specializzato).
Il principio di un gioco isometrico è che il mondo 3D viene osservato con un angolo fisso di 45°.
Di nuovo si utilizza la proiezione parallela, cioè non c’è alcuna prospettiva e quindi gli oggetti più lontani non diventano più piccoli.
Immagina il mondo come costituito da celle quadrate.
In una vista isometrica tutti i quadrati diventano dei rombi.
Per rendere semplice l’allineamento delle celle tipicamente utilizziamo rombi 2x1, cioè di 32x16 pixel.
Facendo la stessa cosa con un’immagine di sfondo otteniamo
Questi sfondi si possono realizzare in GameMaker in un modo abbastanza semplice.
- crea un nuovo sfondo tassellato
- componilo passo-passo
- allarga l’immagine
- ruotala di 45°
- ingrandiscila (rimpiccioliscila) verticalmente del 50%.
In alternativa puoi utilizzare un insieme di tessere già pronto della giusta dimensione e orientazione.
Nella finestra del livello indica di utilizzare una griglia isometrica.
Adesso è relativamente semplice posizionare correttamente le tessere nel livello.
Il vantaggio della proiezione isometrica rispetto alla proiezione normale come abbiamo fatto prima è che la nostra mente interpreta immediatamente i rombi come quadrati visti sotto un certo angolo.
Questo produce un’impressione tridimensionale.
Chiaramente otterremo ancora distorsioni di prospettiva la dimensione degli oggetti non cambia con la distanza.
Questa distorsione di prospettiva può essere ancora limitata visualizzando soltanto una piccola parte del mondo.
Ecco perché la maggior parte dei giochi isometrici utilizzano una vista sul mondo limitante.
Una volta che hai uno sfondo piacevole passiamo alla posa degli oggetti in esso.
Gli oggetti dovrebbero avere ovviamente un aspetto 3D dell’angolo corretto di 45°.
La realizzazione di questi oggetti isometrici non è facile e normalmente è l’operazione che richiede più tempo nei giochi isometrici.
Ogni oggetto ha un’ombra sul terreno.
L’ombra è fondamentale.
Verrà utilizzata per il controllo delle collisioni, o detto in modo diverso, sarà utilizzata come maschera di collisione.
Allora avrai bisogno di due sprite per ogni oggetto: l’immagine dell’oggetto e la maschera ombra.
La cosa migliore è che l’origine della sprite e della maschera sia il centro dell’ombra.
Per esempio, a destra, vedi un’immagine di un muro che stiamo per utilizzare nel nostro gioco isometrico e la sua maschera ombra corrispondente (la x rappresenta l’origine).
In questo caso la maschera ha precisamente la dimensione di una tessera dell’immagine.
Svolgendo il controllo di collisione sulle ombre allora le immagini si possono sovrapporre, finché le loro ombre non si sovrappongono.
Questo è precisamente quello che noi vogliamo.
Per esempio, quando una palla gira tra i blocchi le sprite si possono sovrapporre.
Ma si ha una collisione con un muro quando l’ombra della palla tocca l’ombra del muro.
Come nel caso parallelo impostiamo depth in ogni istanza a –y.
In questo modo le istanze vengono disegnate nell’ordine corretto.
Tuttavia c’è ancora un problema.
Quando si creano i livelli le sprite non sono disegnate in questo ordine.
Questo potrebbe rendere difficile la realizzazione di scene corrette.
Un avvertimento è di iniziare sempre dall’alto e operare verso il basso.
Inoltre, c’è un pulsante nella barra degli strumenti che ordina le istanze secondo la coordinata y, che è proprio quello che vogliamo.
Un’ultima parola sul movimento.
Siccome c’è la proiezione il movimento orizzontale dovrebbe essere veloce il doppio del movimento verticale.
Inoltre, quando utilizzi le frecce direzionali (per esempio) per guidare il movimento, è comune farle corrispondere a movimenti in diagonale (lungo i lati delle tessere) piuttosto che a movimenti orizzontali e verticali.
Un labirinto come esempio
Stiamo per realizzare un esempio di gioco isometrico: un semplice labirinto.
Non è molto sofisticato ma ti illustrerà le idee di base.
Come primo passo è meglio che tu realizzi il labirinto su carta.
Sarà molto difficile farlo mentre crei il livello.
Poi creiamo un terreno di sfondo per il labirinto che riempia l’intera area coperta dal labirinto.
Come secondo passo creiamo le sprite.
Come detto primo sono necessarie due sprite per ogni oggetto: l’immagine effettiva e la maschera utilizzata per il controllo di collisione.
Per molti oggetti utilizziamo la stessa maschera.
Assicurati che ogni sprite si inserisca bene sulla superficie e che l’origine sia al centro della maschera ombra.
Per rendere le cose più interessanti aggiungiamo un passaggio.
Il passaggio consiste di tre parti.
I pilastri destro e sinistro sono semplicemente dei muri più alti e di colore diverso.
Utilizzano la stessa maschera come i muri normali e sono esattamente identici (allora definiamo come loro Parent l’oggetto muro per farli comportare allo stesso modo).
Il pezzo in mezzo del passaggio è diverso.
Consiste di un blocco in alto nell’aria.
Non ha bisogno di una maschera perché la palla può passarci sotto.
Ma dobbiamo essere sicuri che la sua origine sia ancora al centro della sua ombra (altrimenti non sarebbe disegnato alla profondità giusta).
Per ciascun elemento impostiamo la sua profondità nell’evento Create.
Per la palla la impostiamo nell’evento End Step.
Per il resto il gioco è praticamente lo stesso di un semplice gioco di labirinto.
Quando premi un tasto freccia muoviamo la palla di un po’ nella direzione diagonale corretta, nell’ipotesi che la nuova posizione sia senza collisione.
Come detto prima la distanza orizzontale è il doppio della distanza verticale.
Quando la palla (la sua ombra…) colpisce la bandierina (la sua ombra…) il labirinto è stato risolto.
Realizzare il livello richiede maggiore impegno.
Bisogna posizionare correttamente tutti gli elementi muro.
Inoltre, come detto prima, è meglio se inizi dall’alto verso il basso.
Utilizza il pulsante nella barra degli strumenti Sort all instances by y-coordinate se hai commesso un errore.
Utilizza una griglia 16x8 per allineare correttamente le istanze.
Per rendere più facile il posizionamento delle istanze seleziona Turn the grid into an isometric grid.
Deseleziona la casella Delete underlying per rendere per lo stesso motivo.
C’è ancora un trucco aggiunto nel demo.
Quando mantieni premuto il tasto <Space> puoi vedere la palla attraverso i muri.
Questo è utile quando l’oggetto in movimento può scomparire completamente dietro gli altri oggetti.
Ecco come funziona.
C’è un nuovo oggetto chiamato transparent_ball.
Ha una profondità –100000, cioè davanti a qualsiasi altra cosa.
Quando l’utente preme <Space> viene creata un’istanza di questo oggetto e quando lo rilascia l’oggetto viene distrutto.
Per assicurarti che l’oggetto occupi la stessa posizione della palla dagli la stessa sprite ma impostagli alpha a 0.2.
Come risultato vediamo un’immagine trasparente della palla davanti al muro.
Questo rende produce l’impressione opposta che il muro sia parzialmente trasparente.
Dovresti giocare ancora per un po’ con il demo.
Aggiungi qualche altro muro e dei passaggi, aggiungi dei livelli, ecc.
Giochi isometrici più avanzati
I giochi isometrici si adattano particolarmente a molti tipi di giochi.
La maggiore complicazione comunque è che sono necessarie sprite e tessere fatte molo bene.
Utilizza Google con le parole isometric tiles e troverai molte pagine interessanti.
Ci sono solo due cose che ti devi ricordare bene: le maschere di collisione e l’impostazione corretta della profondità.
Ecco altre due cose da tenere a mente:
- Quando non puoi andare dietro certi oggetti (come le montagne o foreste) è meglio se li disegni sullo sfondo.
Successivamente puoi utilizzare degli oggetti invisibili per evitare che gli oggetti in movimento possano coprirli. - Quando un oggetto si distribuisce su più tessere (come un passaggio) spezzalo in diverse tessere per evitare problemi con la profondità.
- Ricordati sempre di impostare l’origine al centro della proiezione verticale dell’oggetto.
Quindi, per esempio, un uccello in volo avrà il suo centro a una notevole distanza sotto di esso.
Osserva che non è necessario allungare la sprite.
Il centro può cadere fuori dalla sprite.