Eccoci arrivati all'ultima parte del nostro "remake" di Bow and Arrow! 😎
Nella scorsa puntata abbiamo mosso il nostro protagonista il quale può, alla pressione di Z, tendere l'arco. Inoltre abbiamo creato uno sfondo in movimento, un cielo azzurro con alcune nuvole bianche.
Come promesso, in quest'ultima parte avremo il succo del gioco: prima di proseguire quindi vi avverto che questa puntata può essere più complessa da seguire: armatevi di pazienza, e se qualcosa non vi è chiaro date un occhio al codice negli screenshot. Andiamo!
Carichiamo come al solito il nostro file robinhoody.tic e creiamo una table chiamata "arrows". Come prima cosa aggiorniamo la funzione processPlayer(): aggiungiamo un controllo alla pressione del tasto Z (btn(4)) e creiamo una freccia solo se la lunghezza della table arrows (#arrows) è 0 e le munizioni (player.ammo) sono maggiori di 0. Per comodità in questo tutorial sarà possibile avere una sola freccia a schermo. Ogni volta che creiamo una freccia dobbiamo decrementare la variabile player.ammo.
Andiamo in fondo al nostro code editor e aggiungiamo le due classiche funzioni process e draw anche per le nostre arrows. Nella prima le disegniamo, scorrendo la table e disegnando con spr lo sprite all'indice 262 per ogni arrow che troviamo. Nella seconda faremo in modo che la loro coordinata x venga incrementata di 1. Prima di farlo però, controlleremo se la loro coordinata x è maggiore della larghezza della nostra finestra di gioco (w): in quel caso andremo a utilizzare la funzione table.remove per rimuovere dalla table arrows l'elemento alla posizione i.
Nella funzione TIC-80 aggiungiamo quindi le chiamate a processArrows() e drawArrows().
Ora che abbiamo le nostre frecce, dovremo anche avere un sistema di punteggio: diamo uno scopo al nostro Robin Hoody! :laugh: All'inizio del nostro codice inizializziamo una variabile score (ovviamente con valore 0). Aggiungiamo la stampa a video di questa variabile dopo la stampa della frecce rimanenti.
Ed ecco il risultato.
Ora il nostro gioco manca di un solo aspetto: il rilevamento della collisione tra freccia e palloncini! Aspetto che in questo nostro tutorial si presenta in maniera piuttosto banale, in quanto basterà controllare le coordinate della freccia e di ogni palloncino per poi eseguire le operazioni del caso, ovvero: far scoppiare il palloncino, far rompere la freccia e incrementare il punteggio. Aggiungiamo questo controllo nella funzione processArrows(): per ogni elemento della nostra table arrows faremo un controllo con ogni elemento della table ballons. Se le coordinate in qualche modo si "sovrappongono" (la freccia è alta un pixel e quindi risulta molto semplice effettuare questo controllo) allora con la funzione table.remove toglieremo i due elementi che collidono dalle rispettive tabelle e incrementeremo il punteggio di 5.
Ora però dobbiamo dare la possibilità al giocatore di rimediare se per sbaglio mancherà il bersaglio, cosa molto facile soprattutto agli inizi, ma senza aiutarlo troppo. Ecco quindi che se il conteggio dei palloncini sarà inferiore a 2 allora creeremo un palloncino in un'altra table che dichiareremo all'inizio, ovvero ammoBallons. Aggiorniamo anche drawBallons() in modo da disegnare questi nuovi palloncini, di colore giallo, che se colpiti daranno al giocatore nuove frecce.
Aggiorniamo anche la funzione processBallons che svolgerà anche su ammoBallons le stesse operazioni che vengono svolte sulla table ballons.
Ora è il momento di implementare la collisione delle frecce con questi palloncini "speciali". Ci posizioniamo quindi all'interno di processArrows(): per ogni freccia andremo a controllare, in maniera uguale a quanto fatto per i palloncini normali, la collisione con il palloncino giallo. Se si verifica, allora andremo a rimuovere freccia e palloncino dalle rispettive table, ma anche ad aggiungere 10 unità alla variabile player.ammo e ad aggiungere 10 alla variabile score.
Siamo quasi al termine, ma un termine non c'è: infatti manca la condizione di game over. Per realizzarla, dobbiamo agire all'interno della funzione TIC(), il nostro main, il nostro game loop. 😉 Se #arrows (la lunghezza della table) è maggiore di 0 (abbiamo una freccia in volo) o player.ammo è maggiore di 0 (abbiamo ancora frecce a disposizione) il nostro gioco può continuare, ed eseguiamo tutto quello che abbiamo implementato finora. Altrimenti diamo il game over, che consiste nello stampare a schermo il punteggio raggiunto.
Ecco quindi il nostro gioco in azione, completo di tutti quegli elementi fondamentali.
Ovviamente questo è un gioco completo, ma piuttosto povero. Ecco alcuni suggerimenti/spunti/idee tutti molto fattibili, in ordine di difficoltà crescente, per migliorare quanto abbiamo realizzato:
- Realizzare un title screen, che permette di iniziare la partita alla pressione di un tasto.
- Dare la possibilità di ricominciare la partita dopo un game over, magari alla pressione di un tasto.
- Salvataggio del punteggio record.
- Quando i palloncini vengono colpiti non spariscono, ma cadono verso il basso "sgonfi".
- Utilizzare il terzo sprite del protagonista mentre la freccia è in volo.
Spero che questo mini tutorial (per quanto basico) vi sia piaciuto, e se volete possiamo discuterne insieme qui sotto o su Discord. 😄 Grazie a tutti! 😉
Parte 1 | Parte 2 | Parte 3