Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming
Gamedevelopment

Parsing e rendering del formato TMX di Tiled nel vostro motore di gioco

by
Difficulty:IntermediateLength:LongLanguages:

Italian (Italiano) translation by Chip (you can also view the original English article)

Nel mio precedente articolo, abbiamo osservato Tiled Map Editor come strumento per realizzare i livelli per i vostri giochi. In questo tutorial, vi porterò attraverso il passo successivo: l'analisi ed il rendering delle mappe nel vostro motore.

Nota: Anche se questo tutorial è stato scritto utilizzando Flash e AS3, dovrebbe essere possibile utilizzare le stesse tecniche e concetti in quasi tutti gli ambienti di sviluppo per videogiochi.


Requisiti


Salvataggio in formato XML

Utilizzando la specifica TMX possiamo memorizzare i dati in una varietà di modi. Per questo tutorial salveremo la nostra mappa in formato XML. Se si pensa di utilizzare il file TMX incluso nella sezione requisiti si può passare alla sezione successiva.

Se avete fatto la vostra mappa è necessario dire a Tiled di salvarla in formato XML. Per farlo, apriamo la mappa con Tiled e selezioniamo Edit > Preferences...

Dalla casella a discesa "Store tile layer data as:", selezionare XML, come mostrato nell'immagine qui sotto:

Ora, quando si salva la mappa verrà memorizzata in formato XML. Sentitevi liberi di aprire il file TMX con un editor di testo per dare un'occhiata al suo interno. Ecco un frammento di ciò che ci si può aspettare di trovare:

Come potete vedere, semplicemente memorizza tutte le informazioni di mappa in questo pratico formato XML. Le proprietà dovrebbero essere per lo più semplici, con l'eccezione di gid - che andrò a spiegare più in dettaglio più avanti nel tutorial.

Prima di continuare, vorrei attirare la vostra attenzione sull'elemento objectgroup "Collision". Come ricorderete dal tutorial di creazione della mappa, avevamo specificato l'area di collisione intorno all'albero; è così che viene memorizzato.

È possibile specificare power-up o il punto di spawn del giocatore nello stesso modo, quindi potete immaginare quante possibilità offre Tiled come editor di mappe!


Fase centrale

Ora ecco un breve riassunto di come porteremo la nostra mappa nel gioco:

  1. Leggere il file TMX.
  2. Analizzare (n.d.a. il parser analizza una struttura per smontarla nella sue componenti) il file TMX come un file XML.
  3. Caricare tutte le immagini tileset.
  4. Disponiamo le tileset nei riquadri del nostro layout di mappa, strato dopo strato.
  5. Leggiamo gli oggetti della mappa.

Lettura del file TMX

Per quanto riguarda interessa il programma, questo è solo un file XML, quindi la prima cosa che vogliamo fare è leggerlo. La maggior parte dei linguaggi ha una libreria XML per questo; nel caso di AS3 userò la classe XML per memorizzare le informazioni XML e un URLLoader per leggere nel file TMX.

Si tratta di un semplice lettore di file per "../assets/example.tmx". Si presuppone che il file TMX si trovi nella directory del progetto sotto la cartella "assets". Abbiamo solo bisogno di una funzione per gestire quando la lettura del file è completata:

Questo è dove avviene il parsing iniziale. (Ci sono alcune variabili di cui terremo traccia fuori da questa funzione perché le useremo in seguito.)

Una volta che abbiamo i dati della mappa salvati, dobbiamo passare all'analisi di ciascun tileset. Ho creato una classe per memorizzare le informazioni di ogni tileset. Infiliamo ciascuna di queste classi istanza in un array dato che le useremo in seguito:

Anche in questo caso, si può vedere che gid appare di nuovo, nelle variabili firstgid e lastgid. Diamo ora un'occhiata a cosa servono.


Capire i "gid"

Per ogni tile, abbiamo bisogno di associarla in qualche modo ad un tileset e ad una posizione particolare in quel tileset. Questo è lo scopo del gid.

Guardate il tileset grass-tessere-2-small.png. Contiene 72 tile distinte:

Diamo a ciascuna di queste tile un unico gid da 1-72, in modo che si possa fare riferimento a ciascuno con un solo numero. Tuttavia, il formato TMX specifica solo il primo gid della tileset, poiché tutti gli altri gids possono essere derivati conoscendo le dimensioni del tileset e la dimensione di ogni singola tile.

Ecco una immagine utile per aiutare a visualizzare e spiegare il processo.

Quindi, se abbiamo messo la tile in basso a destra di questo tileset da qualche parte su una mappa, dovremmo conservare il gid 72 in quella posizione sulla mappa.

Ora, nel file TMX di esempio sopra, si noterà che tree2-final.png ha una firstgid di 73. Questo perché continuiamo a contare le gids senza reimpostarle a 1 per ogni tileset.

In sintesi, un gid è un ID univoco assegnato ad ogni tile di ogni tileset all'interno di un file TMX, in base alla posizione della tile all'interno tileset e al numero di tilesets nel file TMX.


Caricare i Tilesets

Ora vogliamo caricare tutte le immagini delle tileset nella memoria in modo da poterle mettere nella nostra mappa insieme. Se non state usando AS3, l'unica cosa che dovete sapere qua è che stiamo caricando le immagini di ogni tilesed:

Qua ci sono alcune cose specifiche di AS3, come ad esempio l'utilizzo della classe Loader per importare lle immagini del tileset. (Più precisamente, si tratta di un Loader esteso, così possiamo semplicemente memorizzare le istanze dei Tileset all'interno di ogni Loader. Così al termine del caricamento si può facilmente mettere in relazione il Loader con il tileset.)

Questo può sembrare complicato, ma il codice è davvero molto semplice:

Ora, prima di iniziare a prendere queste tileset e crearci la mappa abbiamo bisogno di creare un'immagine di base su cui metterle:

Copieremo i dati delle tile su queste immagini bitmap in modo da utilizzarle come sfondo. La ragione per cui ho creato due immagini è che così possiamo avere uno strato superiore e uno strato inferiore, per poter muovere il giocatore in-tra di loro al fine di fornire una prospettiva. Si precisa inoltre che il livello superiore deve avere un canale alfa.

Come gestore di eventi per i loaders possiamo usare questo codice:

Questa è una funzione simpatica in quanto è possibile monitorare fino a che punto l'immagine è stata caricata, e può quindi fornire un feedback all'utente di come le cose stanno andando veloci, come ad esempio una barra di avanzamento.

Qui andiamo a memorizzare i dati bitmap con il tileset ad esso associati. Abbiamo anche contato quanti tilesets sono completamente caricati e quanti sono fatti completamente, possiamo chiamare una funzione (l'ho chiamata addTileBitmapData in questo caso) per cominciare a mettere insieme i pezzi delle tile.


Combinare le Tiles

Per combinare le tile in una singola immagine, le disegnamo strato per strato in modo che sia visualizzato allo stesso modo in cui viene visualizzata la finestra di anteprima di Tiled.

Ecco come appare la funzione finale; i commenti inclusi nel codice sorgente dovrebbero spiegare adeguatamentecosa sta succedendo senza entrare troppo brutalmente nei dettagli. Vorrei sottolineare che può essere implementato in molti modi diversi, e la vostra implementazione potrebbe apparire completamente diversa dalla mia.

Quello che sta succedendo qui è che stiamo analizzando solo le tile con i gids che sono maggiori di 0, dal momento che 0 indica una tessera vuota e li memorizziamo in un array. Dal momento che ci sono così tante "tile 0" nel nostro layer superiore, sarebbe inefficiente memorizzarle tutte in memoria. E' importante notare che stiamo memorizzare la posizione del gid con un contatore, perché useremo più tardi il suo indice nella matrice.

In questa sezione stiamo tirando fuori il nome del livello e controlliamo se è uguale a "Top". Se lo è, impostiamo un flag e sappiamo di doverlo copiare sul layer bitmap superiore. Con funzioni come questa, possiamo essere veramente flessibili, utilizzando anche più strati disposti in qualsiasi ordine.

Ora qui memorizziamo il gid, che avevamo analizzato all'inizio, in una matrice 2D. Notate l'inizializzazioni della doppia matrice; questo è semplicemente un modo di gestire array 2D in AS3.

Dietro c'è un pò di matematica. Ricordate quando sopra abbiamo inizializzato l'array tiles, e di come abbiamo mantenuto l'indice? Ora possiamo utilizzare l'indice per calcolare la coordinata a cui il gid appartiene. Questa immagine mostra quello che sta succedendo:

In questo esempio, si ottiene il gid all'indice 27 nell'array tiles e lo conserviamo a tileCoordinates[7][1]. Perfetto!

E' qui che finalmente arriviamo a copiare il tileset nella nostra mappa.

Inizialmente scorriamo ogni coordinata di tile sulla mappa e per ogni coordinata di tile otteniamo il gid e controlliamo il tileset memorizzato a cui corrisponde, verificando se si trova tra il firstgid e la nostra lastgid calcolate.

Se avete capito la sezione precedente Capire i "gid", questi calcoli dovrebbero avere un senso. Nei termini più elementari, prendiamo la coordinata tile sul tileset (sourceX e sourceY) e la copiamo sulla nostra mappa nella posizione della tile che abbiamo ciclato a (destX e destY).

Infine, al termine chiamiamo la funzione copyPixel per copiare l'immagine tile sul entrambe i layer superiore e quello base.


Aggiunta di Oggetti

Ora che la copia dei layers sulla mappa è fatta, guardiamo come caricare gli oggetti per la collisione. Questo proprietà è molto potente perché la possiamo usare oltre che per gli oggetti di collisione, anche per qualsiasi altro oggetto, come ad esempio power-up o un percorso di spawn del giocatore, così come l'abbiamo disegnata con Tiled.

Quindi, alla fine della funzione addTileBitmapData, mettiamo il codice seguente:

Così cicliamo attraverso gli strati degli oggetti, cercando un livello con il nome "Collision". Quando lo troviamo, prendiamo ogni oggetto in quel livello, creiamo un rettangolo in quella posizione e lo memorizziamo nell'array collisionTiles. In questo modo abbiamo un riferimento ad esso e siamo in grado di scorrerlo per controllare le collisioni se abbiamo un giocatore.

(A seconda di come il vostro sistema gestisce le collisioni, si consiglia di fare qualcosa di diverso.)


Visualizzazione della Mappa

Alla fine, per visualizzare la mappa, vogliamo disegnare prima lo sfondo e poi il primo piano, in modo da ottenere la corretta stratificazione. In altri linguaggi, è semplicemente una questione di disegno di una immagine.

Ho aggiunto un pò di codice tra i layer giusto per dimostrare con un rettangolo che la stratificazione effettivamente funziona. Ecco il risultato finale:

Grazie per aver dedicato del tempo nel completare il tutorial. Ho incluso una zip che contiene un progetto completo FlashDevelop con tutto il codice sorgente e le risorse.


Letture aggiuntive

Se siete interessati a fare più cose con Tiled, una cosa che non ho approfondito sono le properties. Usare le proprietà consiste in un piccolo passaggio nel parsing dei nomi dei layer e permette di impostare un gran numero di opzioni. Ad esempio, se si vuole un punto di spawn dei nemici, è possibile specificare il tipo di nemico, il formato, il colore, tutto dentro l'editor di mappe Tiled!

Per ultimo, come avrete notato, l'XML non è il formato più efficiente per memorizzare i dati TMX. I file CSV sono a metà tra un facile parsing ed una migliore archiviazione, ma c'è anche formato base64 (non compresso, compresso zlib e compresso gzip). Se siete interessati ad utilizzare questi formati invece del XML, controllate la pagina del wiki di Tiled sul formato TMX.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.