Proseguiamo con il nostro seguito spirituale di Bow and Arrow dopo la prima puntata. 😉
La scorsa volta abbiamo imparato come generare nuovi elementi e salvarli in una table, utilizzare ipairs per iterare su questa lista e disegnare sprite con dimensioni diverse dal default 8x8.
Carichiamo il nostro file .tic e riprendiamo proprio dagli sprite.
Il nostro protagonista andrà a muoversi solo verticalmente (sull'asse Y) e per giustificare ciò creiamo una piattaforma fantascientifica che lo sosterrà a mezz'aria. Inoltre, andiamo a creare lo sfondo per il nostro livello di gioco, ovvero un tileset contenente un cielo (azzurro, con alcune nuvole) nella tab BG (in alto a destra). Non siete ovviamente obbligati ad averlo, ma renderà il tutto meno scarno e potete sbizzarrirvi con colori o elementi: tenete presente che verrà mosso da destra verso sinistra, come se ci fosse del vento a spostare le nuvole.
Nella tab Map Editor, ovvero la terza in alto a sinistra, andiamo a disegnare effettivamente sulla map il nostro sfondo. L'editor è molto semplice e consente, tramite mouse, di selezionare le tile da disegnare (con il click sulla freccia in alto a destra) o di variare la dimensione del pennello. Ci sono anche altre funzionalità , come la selezione ad area e il riempimento automatico. Una volta completato il disegno, siamo pronti per andare ad occuparci del nostro protagonista, che momentaneamente se ne sta lì a mezz'aria.
Andiamo quindi a creare due funzioni, drawPlayer() e processPlayer(). All'interno della prima spostiamo la funzione spr con cui disegniamo il player nella funzione TIC(). Inoltre aggiungiamo un'ulteriore chiamata a spr per disegnare la piattaforma fantascientifica che sosterrà il nostro Robin.
Nella seconda funzione appena creata invece gestiremo l'input dell'utente, intercettando la pressione dei tasti su e giù con la funzione btn. L'indice 0 e l'indice 1 corrispondono ai tasti FRECCIA SU e FRECCIA GIÙ, permettendo così di stabilire se l'utente vuole variare la posizione del protagonista. Ovviamente teniamo tutto dentro dei limiti specifici, limitando la modifica di player.y solo se ad una certa distanza dai limiti superiore e inferiore della schermata.
Aggiorniamo ora la funzione TIC(). All'inizio cominciamo col disegnare la nostra mappa tramite la funzione map. I parametri di questa funzione vanno ad individuare l'inizio dell'area della map da disegnare, le dimensioni in caselle (8x8) da disegnare, le coordinate a schermo e l'indice del colore da rendere trasparente. Per la descrizione completa rimando alla wiki.
Mi soffermo solo sul parametro che specifica la coordinata x per il disegno a schermo. Come vedete viene calcolato "0 - t % 240", ovvero "0 - t % <larghezza finestra>" il che ci consente, visto che t cresce ad ogni frame, di muovere verso sinistra il nostro sfondo. La successiva chiamata viene utilizzata per sopperire al mancato disegno della prima funzione andando a disegnare senza sottrarre a 0 il "t % 240". Un trucchetto semplice per realizzare uno sfondo mobile: ecco quindi il nostro sfondo animato! Cambiamo inoltre l'indice del colore di stampa della funzione print che fino ad ora non era impostato: lo settiamo a 0, che corrisponde al colore nero.
Ora aggiungiamo un piccolo dettaglio grafico, ovvero il personaggio che tende l'arco alla pressione del tasto "Z" (btn(4)). Sarà necessaria la presenza di una nuova variabile aiming all'interno della table player, settata a false di default. Questa variabile ci sarà utile anche quando implementeremo il rilascio della freccia al rilascio del pulsante.
Nella funzione processPlayer() andremo ad aggiungere un controllo: alla pressione del tasto Z impostiamo player.aiming a true, quando invece il tasto non è premuto sarà reimpostata a false. Nella funzione drawPlayer() effettuiamo un check sulla nuova variabile e cambiamo l'indice dello sprite disegnato a seconda del valore.
Il risultato può essere apprezzato in questa GIF che mostra il movimento del player e del background, e la pressione del tasto Z con conseguente variazione dello sprite del protagonista.
Alla prossima e ultima parte! 😎
Parte 1 | Parte 2 | Parte 3