-------------------------------------------------------------------------- Simple Pong -------------------------------------------------------------------------- rem ****************************************************************** rem * Simple Pong (1 Giocatore vs. CPU) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Questa è una versione classica del gioco Pong per un * rem * giocatore. L’utente controlla la racchetta destra (player0) * rem * muovendola verticalmente per respingere una palla (ball). * rem * La racchetta sinistra (player1) è controllata dal computer * rem * e segue semplicemente la posizione verticale della palla. * rem * L’obiettivo è segnare punti facendo passare la palla oltre la * rem * racchetta del computer. Si perde una vita se la palla supera * rem * la propria racchetta. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Fisica di Base: Il movimento della palla è gestito da due * rem * variabili di velocità (`ballxvelocity`, `ballyvelocity`). * rem * Quando la palla colpisce un muro o una racchetta, la sua * rem * velocità viene invertita (`velocita = 0 – velocita`) per * rem * simulare un rimbalzo. * rem * - Intelligenza Artificiale (IA) Semplice: La racchetta del * rem * computer non ha una vera logica, ma si limita a “inseguire” * rem * la palla. La sua coordinata Y (`player1y`) viene * rem * semplicemente impostata uguale a quella della palla (`bally`)* rem * ad ogni frame, rendendola imbattibile a meno che la palla * rem * non venga “spinta” via velocemente dopo una collisione. * rem * - Gestione delle Collisioni e Subroutine: Il comando * rem * `collision()` viene usato per rilevare i contatti. La * rem * logica di gestione degli eventi (punto segnato, vita persa, * rem * collisione) è organizzata in subroutine (`gosub…return`), * rem * mantenendo il `main_loop` pulito e leggibile. * rem * - Clamping: Vengono usati dei controlli `if` per “bloccare” * rem * (clamping) la posizione delle racchette, impedendo loro di * rem * uscire dai limiti superiore e inferiore del campo da gioco. * rem ****************************************************************** rem --- Direttive del Compilatore --- set romsize 4k rem --- Sezione Definizioni Variabili (Alias) --- rem Crea un alias per la velocità orizzontale della palla. dim ballxvelocity = a rem Crea un alias per la velocità verticale della palla. dim ballyvelocity = b rem ‘q’ è un flag per gestire il primo avvio del gioco. q=0 rem --- Impostazioni Iniziali Grafica --- rem Imposta il colore dello sfondo (verde). COLUBK = 198 rem Imposta il colore del playfield (bianco per i bordi). COLUPF = 14 rem Definisce la grafica del campo da gioco (bordi superiore e inferiore). playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Definisce la grafica della racchetta del giocatore (player0). player0: %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 end rem Definisce la grafica della racchetta del computer (player1). player1: %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 end rem --- Stato 1: Inizializzazione Partita / Round --- startNewGame rem Questa etichetta viene chiamata per iniziare una nuova partita o un nuovo round. rem Imposta la posizione iniziale della racchetta del giocatore. player0x = 140 player0y = 49 rem Imposta la posizione iniziale della racchetta del computer. player1x = 15 player1y = 49 rem Imposta la posizione iniziale della palla al centro dello schermo. ballx = 80 bally = 45 rem Imposta la velocità iniziale della palla. ballxvelocity = 1 ballyvelocity = 1 rem Inizializza il contatore delle vite (non usato nel codice ma presente). l=3 rem Imposta i colori delle racchette. Questi registri sono volatili. COLUP0 = 140 COLUP1 = 28 rem Controlla se non è la prima partita in assoluto. if q=1 then goto gameLoop rem Se è la prima partita, imposta il flag e vai alla schermata ‘premi fuoco’. q=1 firstgame COLUP0 = 140 COLUP1 = 28 drawscreen if joy0fire then goto gameLoop goto firstgame rem --- Ciclo di Gioco Principale --- gameLoop rem Reimposta i registri TIA volatili ad ogni frame. COLUP0 = 140 COLUP1 = 28 rem Disegna il fotogramma corrente. drawscreen rem --- Gestione Input Giocatore --- if joy0up then player0y = player0y-1 if joy0down then player0y = player0y+1 rem Clamping: impedisce alla racchetta del giocatore di uscire dallo schermo. if player0y < 16 then player0y = 16 if player0y > 79 then player0y = 79 rem --- IA del Computer --- rem La racchetta del computer segue perfettamente la posizione Y della palla. player1y = bally rem Clamping: impedisce anche alla racchetta del computer di uscire. if player1y < 16 then player1y = 16 if player1y > 79 then player1y = 79 rem --- Fisica della Palla --- rem Aggiorna la posizione della palla in base alla sua velocità. ballx = ballx + ballxvelocity bally = bally + ballyvelocity rem Fa rimbalzare la palla sui bordi superiore e inferiore. if bally < 9 then ballyvelocity = 0 - ballyvelocity if bally > 77 then ballyvelocity = 0 - ballyvelocity rem --- Gestione Collisioni --- rem Se la palla colpisce la racchetta del giocatore, chiama la subroutine di collisione. if collision(player0, ball) then gosub playercollision rem Se la palla colpisce la racchetta del computer, chiama la sua subroutine. if collision(player1, ball) then gosub computercollision rem --- Gestione Punti e Vite --- rem Se la palla supera la racchetta del giocatore, chiama la subroutine ‘vita persa’. if ballx > 150 then gosub playerlostlife rem Se la palla supera la racchetta del computer, chiama la subroutine ‘punto segnato’. if ballx < 5 then gosub playerscores rem --- Condizione di Fine Partita --- rem Se le vite sono esaurite, vai alla schermata di Game Over. if l < 1 then goto gameover rem Ripete il ciclo di gioco. goto gameLoop rem --- Sezione delle Subroutine --- playercollision rem Gestisce la collisione tra la palla e il giocatore. rem Inverte la velocità orizzontale della palla. ballxvelocity = 0 - ballxvelocity rem Sposta la palla di qualche pixel per evitare collisioni multiple nello stesso frame. ballx = ballx + ballxvelocity*5 bally = bally + ballyvelocity*5 return computercollision rem Gestisce la collisione tra la palla e il computer. rem Inverte la velocità orizzontale della palla. ballxvelocity = 0 - ballxvelocity rem Sposta la palla per evitare collisioni multiple. ballx = ballx + ballxvelocity*5 bally = bally + ballyvelocity*5 return playerscores rem Gestisce l’evento in cui il giocatore segna un punto. rem Resetta la posizione della palla al centro. ballx = 80 bally = 45 rem Resetta la velocità della palla. ballxvelocity = 1 ballyvelocity = 1 rem Incrementa lo score del giocatore. score = score + 10 return playerlostlife rem Gestisce l’evento in cui il giocatore perde una vita. rem Decrementa il contatore delle vite. l = l - 1 rem Resetta la posizione della palla. ballx = 80 bally = 45 return rem --- Stato Finale: Game Over --- gameover rem attende fire per ricominciare. rem fai sparire la palla bally = 110 COLUP0 = 140 COLUP1 = 28 drawscreen if joy0fire then goto startNewGame goto gameover   -------------------------------------------------------------------------- Advanced Pong -------------------------------------------------------------------------- rem ****************************************************************** rem * Advanced Pong (1 Giocatore vs. CPU con Ostacoli) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Questa è una variante del classico Pong, con delle aggiunte * rem * per renderlo più dinamico. Il giocatore controlla liberamente * rem * la sua racchetta (player0) in quattro direzioni all’interno * rem * del campo. Il campo da gioco contiene ostacoli statici * rem * (playfield) contro cui la palla può rimbalzare. La racchetta * rem * del computer (player1) continua a seguire la palla solo * rem * verticalmente. L’obiettivo e la gestione di punti/vite sono * rem * identici alla versione base. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Movimento a 4 Direzioni: A differenza del Pong classico, il * rem * giocatore può muovere la sua racchetta sia in orizzontale * rem * che in verticale, aggiungendo un elemento strategico. * rem * - Interazione con il Playfield: Il campo da gioco non è più * rem * solo un bordo, ma contiene ostacoli. Il gioco utilizza * rem * `collision(ball, playfield)` per rilevare quando la palla * rem * colpisce questi ostacoli. * rem * - Fisica di Rimbalzo Avanzata: Quando la palla colpisce un * rem * ostacolo del playfield, vengono invertite entrambe le sue * rem * componenti di velocità (`ballxvelocity` e `ballyvelocity`), * rem * simulando un rimbalzo più complesso rispetto a quello sui * rem * bordi. * rem * - Definizione di Sprite Complessi: Gli sprite per le * rem * racchette sono più grandi e dettagliati rispetto a una * rem * semplice linea, utilizzando più righe di dati binari. * rem * - Tutte le altre tecniche (IA, gestione collisioni, clamping, * rem * subroutine) sono simili alla versione base di Pong. * rem ****************************************************************** rem --- Direttive del Compilatore --- set romsize 4k rem --- Sezione Definizioni Variabili (Alias) --- rem Crea un alias per la velocità orizzontale della palla. dim ballxvelocity = a rem Crea un alias per la velocità verticale della palla. dim ballyvelocity = b rem ‘q’ è un flag per gestire il primo avvio del gioco. q=0 rem --- Impostazioni Iniziali Grafica --- rem Imposta il colore dello sfondo. COLUBK = $81 rem Imposta il colore del playfield (bordi e ostacoli). COLUPF = 68 rem Definisce la grafica del campo da gioco con ostacoli interni. rem Nota: ‘x’ minuscolo viene trattato come ‘X’ maiuscolo. playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X............................... X............X........X......... ................................ ................................ ................................ ............................X... ......X......................... ...............................X ...X......X........X...........X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Definisce la grafica della racchetta del giocatore (player0). player0: %11111111 %00011000 %00011000 %00011000 %00111100 %00111100 %00111100 %00011000 %00011000 %00011000 %11111111 end rem Definisce la grafica della racchetta del computer (player1). player1: %01111000 %00011000 %00011000 %00011100 %00011111 %00011100 %00011000 %00011000 %01111000 end rem --- Stato 1: Inizializzazione Partita / Round --- startNewGame rem Questa etichetta viene chiamata per iniziare una nuova partita o un nuovo round. rem Imposta la posizione iniziale della racchetta del giocatore. player0x = 135 player0y = 45 rem Imposta la posizione iniziale della racchetta del computer. player1x = 20 player1y = 45 rem Imposta la posizione iniziale della palla al centro. ballx = 80 bally = 45 rem Imposta la velocità iniziale della palla. ballxvelocity = 1 ballyvelocity = 1 rem Inizializza il contatore delle vite. l=3 rem Imposta i colori delle racchette. Questi registri sono volatili. COLUP0 = 140 COLUP1 = 28 rem Controlla se è la prima partita in assoluto. if q=1 then goto gameLoop rem Se è la prima partita, imposta il flag e vai alla schermata ‘premi fuoco’. q=1 firstgame rem Imposta i colori e attende l’input del giocatore. COLUP0 = 140 COLUP1 = 28 drawscreen if joy0fire then goto gameLoop goto firstgame rem --- Ciclo di Gioco Principale --- gameLoop rem Reimposta i registri TIA volatili ad ogni frame. COLUP0 = 140 COLUP1 = 28 rem Disegna il fotogramma corrente. drawscreen rem --- Gestione Input Giocatore (4 Direzioni) --- if joy0up then player0y = player0y-1 if joy0down then player0y = player0y+1 if joy0left then player0x = player0x-1 if joy0right then player0x = player0x+1 rem Clamping Orizzontale: impedisce alla racchetta di uscire lateralmente. if player0x < 20 then player0x = 20 if player0x > 140 then player0x = 140 rem Clamping Verticale: impedisce di uscire dall’alto e dal basso. if player0y < 16 then player0y = 16 if player0y > 79 then player0y = 79 rem --- IA del Computer --- rem L’IA è la stessa: la racchetta del computer segue la palla verticalmente. player1y = bally rem Clamping per la racchetta del computer. if player1y < 16 then player1y = 16 if player1y > 79 then player1y = 79 rem --- Fisica della Palla --- rem Aggiorna la posizione della palla. ballx = ballx + ballxvelocity bally = bally + ballyvelocity rem Fa rimbalzare la palla sui bordi superiore e inferiore del campo. if bally < 9 then ballyvelocity = 0 - ballyvelocity if bally > 77 then ballyvelocity = 0 - ballyvelocity rem --- Gestione Collisioni --- rem Se la palla colpisce la racchetta del giocatore… if collision(player0, ball) then gosub playercollision rem Se la palla colpisce la racchetta del computer… if collision(player1, ball) then gosub computercollision rem Se la palla colpisce gli ostacoli del playfield… if collision(ball,playfield) then gosub ballplayfieldcollision rem --- Gestione Punti e Vite --- if ballx > 154 then gosub playerlostlife if ballx < 5 then gosub playerscores rem --- Condizione di Fine Partita --- if l < 1 then goto gameover rem Ripete il ciclo di gioco. goto gameLoop rem --- Sezione delle Subroutine --- playercollision rem Gestisce la collisione palla-giocatore. rem Inverte la velocità orizzontale. ballxvelocity = 0 - ballxvelocity rem Sposta la palla per evitare collisioni multiple. ballx = ballx + ballxvelocity*3 bally = bally + ballyvelocity*3 return computercollision rem Gestisce la collisione palla-computer. rem Inverte la velocità orizzontale. ballxvelocity = 0 - ballxvelocity rem Sposta la palla per evitare collisioni multiple. ballx = ballx + ballxvelocity*3 bally = bally + ballyvelocity*3 return playerscores rem Gestisce il punto segnato dal giocatore. rem Resetta palla e velocità. ballx = 80 bally = 45 ballxvelocity = 1 ballyvelocity = 1 rem Aumenta il punteggio. score = score + 10 return playerlostlife rem Gestisce la vita persa dal giocatore. rem Decrementa le vite. l = l - 1 rem Resetta la palla. ballx = 80 bally = 45 return ballplayfieldcollision rem Gestisce la collisione della palla con gli ostacoli. rem Inverte entrambe le componenti della velocità per un rimbalzo diagonale. ballxvelocity = 0 - ballxvelocity ballyvelocity = 0 - ballyvelocity rem Sposta la palla per evitare che rimanga “incastrata” nell’ostacolo. ballx = ballx + ballxvelocity*3 bally = bally + ballyvelocity*3 return rem --- Stato Finale: Game Over --- gameover rem Mostra la schermata finale e attende l’input per ricominciare. COLUP0 = 140 COLUP1 = 28 bally = 110 drawscreen if joy0fire then goto startNewGame goto gameover  -------------------------------------------------------------------------- Dynamic Pong -------------------------------------------------------------------------- rem ****************************************************************** rem * Dynamic Pong (Racchetta che si Accorcia) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Questa variante di Pong introduce una meccanica di difficoltà * rem * crescente. Il giocatore controlla la racchetta destra (player0)* rem * e affronta una racchetta controllata dal computer (player1). * rem * La caratteristica distintiva di questa versione è che la * rem * racchetta del giocatore si accorcia ogni volta che perde una * rem * vita, rendendo il gioco progressivamente più difficile. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Grafica Dinamica dello Sprite: La dimensione (altezza) dello * rem * sprite del giocatore (player0) non è fissa. Il programma * rem * utilizza una logica `if` nel `main_loop` per controllare il * rem * numero di vite rimanenti (`l`). In base a questo valore, * rem * viene chiamata una diversa subroutine (`pll3`, `pll2`, `pll1`)* rem * che ridefinisce la grafica di `player0:` con altezze diverse.* rem * - Organizzazione del Codice con Subroutine: Le diverse * rem * definizioni grafiche dello sprite sono incapsulate in * rem * subroutine separate. Questo mantiene il `main_loop` pulito e * rem * rende chiara la logica di selezione dello sprite. * rem * - Indicatore di Stato Visivo: La dimensione della racchetta * rem * funge da indicatore visivo immediato per il giocatore del * rem * numero di vite rimaste, integrando l'HUD (Heads-Up Display) * rem * direttamente nell'elemento di gioco principale. * rem * - Le altre tecniche (fisica della palla, IA, collisioni, etc.) * rem * sono identiche alla versione base del Pong. * rem ****************************************************************** rem --- Direttive del Compilatore --- set romsize 4k rem --- Sezione Definizioni Variabili (Alias) --- rem Crea un alias per la velocità orizzontale della palla. dim ballxvelocity = a rem Crea un alias per la velocità verticale della palla. dim ballyvelocity = b rem 'q' è un flag per gestire il primo avvio del gioco. q=0 rem --- Impostazioni Iniziali Grafica --- rem Imposta il colore dello sfondo (verde). COLUBK = 198 rem Imposta il colore del playfield (bianco per i bordi). COLUPF = 14 rem Definisce la grafica del campo da gioco (bordi superiore e inferiore). playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Definisce la grafica della racchetta del computer (player1). player1: %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 end rem --- Stato 1: Inizializzazione Partita / Round --- startNewGame rem Questa etichetta viene chiamata per iniziare una nuova partita o un nuovo round. rem Imposta la posizione iniziale della racchetta del giocatore. player0x = 140 player0y = 48 rem Imposta la posizione iniziale della racchetta del computer. player1x = 15 player1y = 45 rem Imposta la posizione iniziale della palla al centro. ballx = 80 bally = 41 rem Imposta la velocità iniziale della palla. ballxvelocity = 1 ballyvelocity = 1 rem Inizializza il contatore delle vite. l=3 rem Imposta i colori delle racchette. Questi registri sono volatili. COLUP0 = 140 COLUP1 = 28 rem Imposta la grafica iniziale della racchetta del giocatore (grandezza massima). gosub pll3 rem Controlla se è la prima partita in assoluto. if q=1 then goto gameLoop rem Se è la prima partita, imposta il flag e vai alla schermata 'premi fuoco'. q=1 firstgame COLUP0 = 140 COLUP1 = 28 drawscreen if joy0fire then goto gameLoop goto firstgame rem --- Ciclo di Gioco Principale --- gameLoop rem Reimposta i registri TIA volatili ad ogni frame. COLUP0 = 140 COLUP1 = 28 rem Grafica Dinamica: seleziona la dimensione della racchetta in base alle vite. if l=3 then gosub pll3 if l=2 then gosub pll2 if l=1 then gosub pll1 rem Disegna il fotogramma corrente. drawscreen rem --- Gestione Input Giocatore --- if joy0up then player0y = player0y-1 if joy0down then player0y = player0y+1 rem Clamping: impedisce alla racchetta del giocatore di uscire dallo schermo. if player0y < 16 then player0y = 16 if player0y > 79 then player0y = 79 rem --- IA del Computer --- rem La racchetta del computer segue la posizione Y della palla. player1y = bally rem Clamping per la racchetta del computer. if player1y < 16 then player1y = 16 if player1y > 79 then player1y = 79 rem --- Fisica della Palla --- rem Aggiorna la posizione della palla. ballx = ballx + ballxvelocity bally = bally + ballyvelocity rem Fa rimbalzare la palla sui bordi. if bally < 9 then ballyvelocity = 0 - ballyvelocity if bally > 77 then ballyvelocity = 0 - ballyvelocity rem --- Gestione Collisioni --- if collision(player0, ball) then gosub playercollision if collision(player1, ball) then gosub computercollision rem --- Gestione Punti e Vite --- if ballx > 150 then gosub playerlostlife if ballx < 5 then gosub playerscores rem --- Condizione di Fine Partita --- if l < 1 then goto gameover rem Ripete il ciclo di gioco. goto gameLoop rem --- Sezione delle Subroutine di Gioco --- playercollision rem Gestisce la collisione palla-giocatore. ballxvelocity = 0 - ballxvelocity ballx = ballx + ballxvelocity*5 bally = bally + ballyvelocity*5 return computercollision rem Gestisce la collisione palla-computer. ballxvelocity = 0 - ballxvelocity ballx = ballx + ballxvelocity*5 bally = bally + ballyvelocity*5 return playerscores rem Gestisce il punto segnato dal giocatore. rem Resetta la palla e la sua velocità. ballx = 80 bally = 45 ballxvelocity = 1 ballyvelocity = 1 rem Incrementa lo score. score = score + 10 return playerlostlife rem Gestisce la vita persa. rem Decrementa il contatore delle vite. l = l - 1 rem Resetta la palla. ballx = 80 bally = 45 return rem --- Stato Finale: Game Over --- gameover rem Mostra l'ultimo stato e attende l'input per ricominciare. COLUP0 = 140 COLUP1 = 28 bally = 110 drawscreen if joy0fire then goto startNewGame goto gameover rem --- Subroutine Grafiche: Dimensioni Racchetta Giocatore --- pll3 rem Racchetta a grandezza massima (16 pixel di altezza) quando le vite sono 3. player0: %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 end return pll2 rem Racchetta a grandezza media (8 pixel di altezza) quando le vite sono 2. player0: %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 %00011000 end return pll1 rem Racchetta a grandezza minima (4 pixel di altezza) quando la vita è 1. player0: %00011000 %00011000 %00011000 %00011000 end return  -------------------------------------------------------------------------- Killer Acorn -------------------------------------------------------------------------- rem ****************************************************************** rem * Killer Acorn (Ghianda Assassina) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Il giocatore controlla una ghianda (player0) in un'arena * rem * chiusa. Un nemico (player1) insegue costantemente il * rem * giocatore. Il giocatore può sparare un proiettile (missile0) * rem * per colpire il nemico, guadagnando punti e facendolo * rem * riapparire in una posizione casuale. Se il nemico tocca il * rem * giocatore, si perde una vita e punti. Il gioco termina * rem * quando le vite si esauriscono. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Intelligenza Artificiale (IA) Semplice: Il nemico (player1) * rem * implementa una logica di inseguimento ("chasing logic") * rem * basata su semplici confronti tra le sue coordinate e quelle * rem * del giocatore, muovendosi di un pixel alla volta verso di * rem * lui. * rem * - Animazione a Frame Multipli: L'animazione del nemico è * rem * realizzata alternando quattro definizioni grafiche * rem * diverse (`player1:`). Un contatore (`v`) rallenta * rem * l'animazione per renderla visibile, mentre un secondo * rem * contatore (`w`) tiene traccia del frame corrente da * rem * visualizzare. * rem * - Gestione Proiettile Singolo: Il gioco permette di avere un * rem * solo proiettile attivo alla volta. La sua posizione verticale* rem * (`missile0y`) viene usata come flag: un valore alto (>240) * rem * indica che il proiettile è "inattivo" e se ne può sparare * rem * un altro. * rem * - Gestione Vite e Punteggio: Il gioco utilizza variabili * rem * standard per le vite (`a`) e lo score (`score`). * rem * - Uso di `rand`: Il comando `rand` viene usato per far * rem * riapparire il nemico in una posizione orizzontale casuale * rem * dopo essere stato colpito. * rem ****************************************************************** set romsize 4k rem --- Stato 1: Schermata Titolo --- opening rem Definisce la grafica statica del titolo. playfield: ................................ ....X..X.XXX..X...X...XXX.XX.... ....X.X...X...X...X...X...X.X... ....XX....X...X...X...XX..XX.... ....X.X...X...X...X...X...X.X... ....X..X.XXX..XXX.XXX.XXX.X..X.. ................................ .......XXX.XXX.XXX.XXX.X.X...... .......X.X.X...X.X.X.X.X.X...... .......XXX.X...X.X.XX..XXX...... .......X.X.XXX.XXX.X.X.X.X...... end title rem Imposta i colori per il titolo. COLUBK = $60 COLUPF = 212 rem Disegna lo schermo e attende l'input del giocatore per iniziare. drawscreen if joy0fire || joy1fire then goto skiptitle goto title skiptitle rem --- Inizializzazione Partita --- rem Imposta i colori di gioco: sfondo blu, playfield (muri) neri. COLUPF = 0 COLUBK = 212 rem Imposta la posizione iniziale del giocatore e del nemico. player0x = 50 player0y = 70 player1x = 20 player1y = 8 rem Imposta un valore iniziale per lo score e il suo colore. score = 103 scorecolor = 1 rem Imposta le proprietà del missile: altezza e posizione iniziale fuori schermo. missile0height=1 missile0y=255 rem Imposta la dimensione dello sprite del giocatore a larghezza doppia. NUSIZ0 = 2 rem Inizializza il contatore delle vite. a = 3 rem Definisce la grafica del playfield di gioco (l'arena). playfield: X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem --- Ciclo di Gioco Principale --- main rem Incrementa il contatore 'v' per rallentare l'animazione del nemico. v = v + 1 rem Logica di animazione: se 'v' raggiunge la soglia (7), cambia il frame rem dello sprite del nemico in base al valore di 'w'. if v = 7 && w = 0 then goto ax if v = 7 && w = 1 then goto bx if v = 7 && w = 2 then goto cx if v = 7 && w = 3 then goto dx goto nextstep rem --- Subroutine di Animazione Nemico --- rem Queste quattro sezioni (ax, bx, cx, dx) definiscono i 4 frame di rem animazione per player1. Ognuna reimposta il contatore 'v' e rem aggiorna il contatore di frame 'w'. ax v = 0 w = 1 player1: %00001000 %01101000 %00101000 %01010000 %01011110 %01110000 %00011000 %00011000 end goto nextstep bx v = 0 w = 2 player1: %00100000 %01110000 %00101000 %01010000 %01011110 %01110000 %00011000 %00011000 end goto nextstep cx v = 0 w = 3 player1: %00011000 %00011000 %00101000 %01010000 %01011110 %01110000 %00011000 %00011000 end goto nextstep dx v = 0 w = 0 player1: %00100000 %01110000 %00101000 %01010000 %01011110 %01110000 %00011000 %00011000 end goto nextstep nextstep rem Definizione grafica dello sprite del giocatore (la ghianda). player0: %00111100 %01011010 %00100100 %00111100 %00011000 %00011000 %00010000 %00010000 end rem --- Logica del Proiettile --- checkfire rem Controlla se un missile è già attivo (missile0y <= 240). if missile0y>240 then goto skip rem Se è attivo, lo muove verso l'alto. missile0y = missile0y - 2 goto draw skip rem Se non ci sono missili attivi, controlla se il giocatore preme 'fuoco'. rem Se sì, crea un nuovo missile alla posizione del giocatore. if joy0fire then missile0y=player0y-2:missile0x=player0x+4 draw rem Disegna il fotogramma corrente. drawscreen rem --- Logica di Movimento e Limiti --- rem Clamping: impedisce al giocatore di uscire dai bordi dello schermo. if player0x < 18 then player0x = 18 if player0x > 136 then player0x = 136 if player0y < 8 then player0y = 8 if player0y > 80 then player0y = 80 rem IA Semplice: il nemico (player1) insegue il giocatore (player0). if player1y < player0y then player1y = player1y + 1 if player1y > player0y then player1y = player1y - 1 if player1x < player0x then player1x = player1x + 1 if player1x > player0x then player1x = player1x - 1 rem --- Gestione Collisioni --- rem Rileva la collisione tra il missile e il nemico. if collision(missile0,player1) then goto point rem Rileva la collisione tra il nemico e il giocatore. if collision(player0,player1) then goto dead rem --- Gestione Input Giocatore --- if joy0up then player0y = player0y-1 if joy0down then player0y = player0y+1 if joy0left then player0x = player0x-1 if joy0right then player0x = player0x +1 rem Ripete il ciclo di gioco. goto main rem --- Subroutine di Evento: Nemico Colpito --- point rem Incrementa lo score. score=score+100 rem Fa riapparire il nemico in una nuova posizione casuale in cima allo schermo. player1x=rand/2 player1y=0 rem Disattiva il missile. missile0y=255 rem Torna al ciclo principale. goto main rem --- Subroutine di Evento: Giocatore Colpito --- dead rem Decrementa lo score. score=score-1 rem Fa riapparire il nemico in una nuova posizione casuale. player1x=rand/2 player1y=0 rem Disattiva il missile. missile0y=255 rem Decrementa il contatore delle vite. a=a-1 rem Se le vite sono esaurite, passa alla schermata di Game Over. if a = 0 then goto resetfire rem Altrimenti, torna al ciclo principale. goto main rem --- Stato Finale: Game Over / Riavvio --- resetfire rem Nasconde il giocatore. player0y=200 rem Usa un flag temporaneo 'f' per rilevare una singola pressione del fuoco. f = 0 if joy0fire || joy1fire then f = 1 rem Se il giocatore non preme fuoco, rimane in un loop che mostra la schermata titolo. if f = 0 then goto opening rem Se preme fuoco, esce dal loop e riavvia. drawscreen goto resetfire  -------------------------------------------------------------------------- Simple Soccer -------------------------------------------------------------------------- rem ****************************************************************** rem * Simple Soccer (2 Giocatori) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Un gioco di calcio/hockey a due giocatori. Ogni giocatore * rem * controlla il proprio personaggio (player0 e player1) in * rem * quattro direzioni. I giocatori possono "dribblare" la palla * rem * (ball) tenendola vicina a sé e tirare premendo il pulsante * rem * di fuoco. L'obiettivo è segnare nella porta avversaria. Le * rem * porte sono le aree aperte ai lati del campo. Il gioco * rem * gestisce il possesso palla e il tiro. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Kernel Option `player1colors`: Questa opzione avanzata del * rem * kernel viene usata per dare a `player1` un aspetto * rem * multicolore, permettendo di definire un colore diverso per * rem * ogni linea dello sprite. Questo sacrifica l'uso del * rem * missile1, ma arricchisce notevolmente la grafica. * rem * - Gestione del Possesso Palla: Una variabile (`p`) funge da * rem * flag per determinare quale giocatore ha il possesso della * rem * palla. Quando la palla non è in fase di tiro, la sua * rem * posizione viene costantemente aggiornata per "attaccarsi" * rem * al giocatore in possesso. * rem * - Gestione del Tiro: Una variabile (`z`) funge da flag di * rem * stato per il tiro. Se `z` è 0, la palla è in possesso. Se è 1,* rem * la palla è stata tirata da player0 e si muove da sola. Se è 2,* rem * la palla è stata tirata da player1. * rem * - Logica di Salvataggio Posizione: Per gestire le collisioni * rem * con i muri, il programma salva le coordinate "valide" dei * rem * giocatori all'inizio di ogni frame (`e, f, g, h`). Se viene * rem * rilevata una collisione, le coordinate vengono ripristinate * rem * a quelle precedenti, impedendo al giocatore di passare * rem * attraverso i muri. * rem * - Gioco a Due Giocatori: Il codice legge l'input da entrambi i * rem * joystick (`joy0` e `joy1`), permettendo a due persone di * rem * giocare contemporaneamente. * rem ****************************************************************** rem --- Direttive del Compilatore --- rem Abilita l'opzione del kernel per avere uno sprite player1 multicolore. set romsize 4k set kernel_options player1colors rem --- Definizioni Grafiche Iniziali --- rem Definisce il campo da gioco con le due porte laterali. playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X....X...................X....X X.............................X X.............................X X.............................X X.............................X X.............................X X.............................X X.............................X X....X...................X....X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Definisce la grafica per il giocatore 1 (player0). player0: %00100010 %00010100 %00001000 %00111110 %00001000 %00011100 %00011100 %00011100 end rem Definisce la grafica per il giocatore 2 (player1). player1: %01000100 %00101000 %00010000 %01111100 %00010000 %00111000 %00111000 %00111000 end rem --- Impostazioni di Gioco Iniziali --- rem Imposta il colore di sfondo iniziale. COLUBK = $0F rem Imposta la larghezza del missile0 (non usato per sparare ma il registro esiste). NUSIZ0 = $30 rem Azzera lo score e imposta il colore del testo. score = 00000 scorecolor = $08 rem --- Inizializzazione Variabili --- rem Le variabili non hanno alias 'dim', ma rappresentano: rem a, b: coordinate x, y del giocatore 0. a = 75 b = 75 rem c, d: coordinate x, y del giocatore 1. c = 75 d = 25 rem z: stato della palla (0=in possesso, 1=tiro p0, 2=tiro p1). z = 0 rem p: possesso palla (0=p0, 1=p1). p = 0 rem Imposta le posizioni iniziali degli oggetti di gioco. player0x = a : player0y = b player1x = c : player1y = d ballx = x : bally = y rem --- Ciclo di Gioco Principale --- main rem Imposta i registri TIA volatili ad ogni frame. COLUP1 = $80 COLUP0 = $40 COLUBK = $C4 COLUPF = $0E rem Salva le coordinate correnti dei giocatori prima di ogni movimento. e = a f = b g = c h = d rem Tabella colori per lo sprite multicolore player1. player1color: $38; $3A; $F4; $F6; $0C; $1A; $D8; $D2; end rem Disegna il fotogramma corrente. drawscreen rem --- Gestione Input Giocatori --- rem Legge l'input dal joystick 0 per muovere il giocatore 0. if joy0left then a = a - 1 if joy0up then b = b - 1 if joy0down then b = b + 1 if joy0right then a = a + 1 rem Legge l'input dal joystick 1 per muovere il giocatore 1. if joy1left then c = c - 1 if joy1up then d = d -1 if joy1down then d = d + 1 if joy1right then c = c + 1 rem --- Logica della Palla (Possesso e Tiro) --- rem Se il giocatore in possesso preme 'fuoco', imposta lo stato 'tiro'. if p = 0 && joy0fire then z = 1 if p = 1 && joy1fire then z = 2 rem Se la palla è in possesso (z=0), la "attacca" al giocatore corretto. if z = 0 && p = 0 then ballx = a + 5 : bally = b - 10 if z = 0 && p = 1 then ballx = c + 4 : bally = d + 2 rem Se la palla è in stato 'tiro', la muove in verticale. if z = 1 then bally = bally - 1 if z = 2 then bally = bally + 1 rem Aggiorna le coordinate finali degli sprite. player0x = a : player0y = b player1x = c : player1y = d rem --- Gestione Reset e Collisioni --- rem Controlla se il pulsante di reset è stato premuto. if switchreset then goto hardReset rem Se la palla tocca un giocatore, quel giocatore ne ottiene il possesso. if collision(ball, player0) then goto save0 if collision(ball, player1) then goto save1 rem Se un giocatore tocca i muri... if collision(player0, playfield) then goto player0HitWall if collision(player1, playfield) then goto player1HitWall rem Impedisce ai giocatori di entrare nelle porte avversarie. if player0y < 30 then goto player0HitWall if player1y > 66 then goto player1HitWall rem Se la palla tocca il playfield (muri o porte)... if collision(ball, playfield) then goto shoot rem Ripete il ciclo di gioco. goto main rem --- Subroutine di Gestione Collisioni Muri --- player0HitWall rem Ripristina la posizione del giocatore 0 a quella valida precedente. a = e b = f goto main player1HitWall rem Ripristina la posizione del giocatore 1 a quella valida precedente. c = g d = h goto main rem --- Subroutine di Gestione Possesso Palla --- save0 rem Il giocatore 0 ora ha il possesso. p = 0 rem La palla smette di essere in 'tiro'. z = 0 goto main save1 rem Il giocatore 1 ora ha il possesso. p = 1 rem La palla smette di essere in 'tiro'. z = 0 goto main rem --- Subroutine di Gestione Tiro in Porta --- shoot rem Controlla se la palla ha colpito un muro laterale o una delle porte. rem Le porte si trovano tra x=41 e x=119. if ballx > 41 && ballx < 119 then goto hit rem Se ha colpito un muro laterale, resetta le posizioni. goto reset hit rem Controlla in quale metà del campo si trova la palla per determinare chi ha segnato. if bally < 50 then goto player0Score if bally > 50 then goto player1Score goto reset player0Score rem Il giocatore 0 ha segnato. score = score + 1 rem La palla passa al giocatore 1. p = 1 goto reset player1Score rem Il giocatore 1 ha segnato. score = score + 1000 rem La palla passa al giocatore 0. p = 0 goto reset rem --- Subroutine di Reset Posizioni --- reset rem Riporta i giocatori alle posizioni iniziali. a = 75 b = 75 c = 75 d = 25 rem Resetta lo stato della palla a 'in possesso'. z = 0 goto main rem --- Subroutine di Hard Reset --- hardReset rem Azzera completamente lo score. score = 000000 rem Restituisce il possesso iniziale al giocatore 0. p = 0 rem Chiama la subroutine di reset delle posizioni. goto reset   -------------------------------------------------------------------------- The Watch -------------------------------------------------------------------------- rem ****************************************************************** rem * The Watch (Il Guardiano del Castello) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Il giocatore controlla un cavaliere (il Ranger, player0) che * rem * deve difendere un muro da un mostro (il Wright, player1). Il * rem * mostro insegue il giocatore e tenta di distruggerlo. Il * rem * giocatore può attaccare con la sua spada (missile0) per * rem * respingere e infine sconfiggere il mostro. Il giocatore deve * rem * anche raccogliere mattoni (ball) e portarli sul muro per * rem * ricostruirlo. Il gioco diventa progressivamente più difficile, * rem * con il mostro che diventa più veloce e resistente. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Kernel Options Avanzate: `pfcolors` e `pfheights` vengono * rem * usate per creare un playfield multicolore e con blocchi di * rem * altezze diverse, permettendo una grafica di sfondo più ricca.* rem * - IA con Difficoltà Crescente: La velocità del nemico è * rem * controllata da un timer (`d`). Ad ogni livello completato, * rem * il valore di `d` diminuisce, rendendo il nemico più veloce. * rem * Anche la sua resistenza (`a`, colpi per ucciderlo) aumenta. * rem * - Interazione Dinamica con il Playfield: Il giocatore può * rem * modificare il playfield in tempo reale. Raccoglie un mattone * rem * (ball) e, quando tocca il muro, usa `pfpixel ... on` per * rem * "disegnare" un nuovo blocco, ricostruendo la fortificazione. * rem * Il comando `pfread` viene usato per verificare se un blocco * rem * è già stato posato. * rem * - Animazione a Frame Multipli: Il giocatore ha un'animazione * rem * di camminata (frame1, frame2) e una di attacco (dosword). * rem * - Gestione del Punteggio BCD: Viene usato l'approccio * rem * consigliato con alias ai singoli byte dello score (`_sc1`, * rem * `_sc2`, `_sc3`) per controllare in modo sicuro condizioni * rem * come il Game Over (score < 0). * rem * - Effetti Sonori Temporizzati: Gli effetti sonori per colpi e * rem * vittorie sono gestiti tramite loop che si ripetono per un * rem * numero fisso di frame, creando suoni di breve durata. * rem ****************************************************************** rem --- Sezione Definizioni Variabili (Commenti originali mantenuti) --- rem a: numero di colpi per uccidere i wright rem b: posizione orizzontale del ranger (p0_x) rem c: posizione verticale del ranger (p0_y) rem d: velocita' con cui il wright insegue il disertore (in funzione di t) rem e: suono dell'uccisione di Wright rem f: timer per l'animazione del player0 che cammina rem g: suono wright colpito rem h: distanza del wright dopo essere stato pugnalato (colpo) rem i: possesso mattone (ball) rem j-u: flag per le sezioni del muro ricostruite rem t: timer per velocita' wright inseguimento del ranger (vedi d) rem v: movimento player1 (wright) orizzontalmente rem w: movimento player1 (wright) in verticale rem y: suono del castello costruito rem --- Direttive del Compilatore --- set romsize 4k set kernel_options pfcolors pfheights rem --- Stato 0: Inizializzazione Globale e Schermata Titolo --- init rem Imposta i colori iniziali. COLUP1 = $A6 COLUBK = $0E rem Definizione grafica iniziale del nemico (Wright). player1: %11110111 %01110111 %00011011 %00011011 %00011011 %00110011 %00110110 %00110110 %10111100 %10111101 %10111101 %10111101 %10111101 %10111101 %10111101 %11111110 %11111000 %01111000 %00100100 %00101100 %01000010 %01101010 %01000010 %00111100 end rem Posiziona il nemico fuori dallo schermo. player1x = 0 : player1y = 200 rem Definisce le altezze per ogni linea del playfield. pfheights: 8 8 8 8 8 8 8 8 8 8 8 end rem Definisce i colori per ogni linea del playfield. pfcolors: $00 $AA $AA $AA $AC $AC $AC $AE $AE $AE $AE end rem Posiziona palla e giocatore fuori schermo. ballx = 0 bally = 200 player0x = 0 : player0y = 200 rem --- Alias per le variabili di gioco principali --- dim p0_x = b dim p0_y = c v=152 w=40 rem Alias per i byte dello score (gestione BCD). dim _sc1 = score dim _sc2 = score+1 dim _sc3 = score+2 rem Inizializzazione parametri di difficoltà. a = 4 d = 30 h = 20 rem Grafica della schermata titolo. playfield: .XXXX.......................X.X XX........XXX.X.X.XXX.....XXXXX .XX........X..X.X.X..........XX ..XX.......X..XXX.XXX.......X.. ..X.X......X..X.X.X........X.X. ..XX.......X..X.X.XXX.......X.X .X...........................XX XX....X...X.XXX.XXX.XXX.X.X...X .XX...X.X.X.X.X..X..X...XXX...X X.XX...X.X..XXX..X..X...X.X..XX XXXX...X.X..X.X..X..XXX.X.X...X end rem Silenzia i canali audio. AUDV1 = 0 AUDC1 = 0 AUDF1 = 0 firstscreen rem Loop della schermata titolo: attende la pressione di 'fuoco'. drawscreen if joy0fire then goto preloop goto firstscreen rem --- Stato 1: Preparazione del Livello --- preloop rem Posiziona il giocatore, il nemico e il mattone per l'inizio del round. player0x = 56 : player0y = 96 player1x = 80 : player1y = 60 ballx = 81 bally = 78 rem Definisce la grafica del muro da ricostruire. playfield: X.X.X........................... .XXXX........................... X.XXX........................... XXX.X........................... XX.XX........................... X.XXX........................... X.XXX........................... XXX.X........................... .XXXX........................... X.XXX........................... XXXXX........................... end rem Resetta la posizione del nemico e i flag di costruzione del muro. v= 152 : w = 40 j = 0 : k = 0 : l = 0 : o = 0 : p = 0 : q = 0 : r = 0 : s = 0 : u = 0 drawscreen rem --- Ciclo di Gioco Principale --- loop rem Controlla la pressione del tasto Reset della console. if switchreset then goto init rem Se tutte le sezioni del muro sono costruite, passa allo stato di 'livello completato'. if j = 1 && k = 1 && l = 1 && o = 1 && p = 1 && q = 1 && r = 1 && s = 1 && u = 1 then goto castlecompleted rem Impostazioni dei registri TIA per il gioco. ballheight = 3 CTRLPF = $21 player1x=v player1y=w rem --- Logica di Animazione e Timer --- rem Incrementa i timer per l'animazione e la velocità del nemico. f=f+1 t=t+1 if t>30 then t=0 rem Controlla la condizione di Game Over (score andato in negativo). if _sc1 = $99 && _sc2 = $99 && _sc3 <= $99 then score = score +1 : goto firstscreen rem --- Gestione Movimento e Animazione Giocatore --- rem Azzera il contatore di animazione. if f = 20 then f = 0 rem Seleziona il frame di animazione in base al timer 'f'. if f < 10 then gosub frame1 if f > 10 && f < 20 then gosub frame2 if f > 10 && f < 20 && !joy0left && !joy0right && !joy0up && !joy0down then gosub frame1 rem Gestione input per movimento. Usa l'aritmetica a complemento a due per il movimento. p0_x = 0 if joy0left && !joy0fire then REFP0 = 8 : p0_x = 255 : player0x = player0x + p0_x : if i = 1 then ballx = player0x - 3 : bally = player0y - 11 if joy0right && !joy0fire then REFP0 = 0 : p0_x = 1 : player0x = player0x + p0_x : if i = 1 then ballx = player0x - 3 : bally = player0y - 11 p0_y = 0 if joy0up then p0_y = 255 : player0y = player0y + p0_y : if i = 1 then ballx = player0x - 3 : bally = player0y - 11 if joy0down then p0_y = 1 : player0y = player0y + p0_y : if i = 1 then ballx = player0x - 3 : bally = player0y - 11 rem --- Gestione Attacco Giocatore --- rem Imposta la dimensione orizzontale della spada. NUSIZ0 = $30 rem Se preme fuoco, mostra la spada e perde il possesso del mattone. if joy0fire then missile0x = player0x + 9 : missile0y = player0y - 7 : i = 0 : gosub dosword else missile0x = 0 : missile0y = 0 rem Clamping: impedisce a giocatori e oggetti di uscire dallo schermo. if player0x < 38 then player0x = 38 if player0x > 124 then player0x = 124 if player0y < 17 then player0y = 17 if player0y > 89 then player0y = 89 if ballx < 37 then ballx = 37 if bally < 11 then bally = 11 if bally > 78 then bally = 78 if player1x > 152 then player1x = 152 rem Imposta i colori di gioco. COLUBK = $0E COLUP1 = $A6 rem Disegna il fotogramma. drawscreen rem --- Gestione delle Collisioni --- rem Collisione spada-nemico: se il nemico ha ancora vita, lo respinge. if collision(missile0,player1) && a <> 0 then v = v + h : a = a - 1: goto strikewright rem Se il nemico non ha più vita, lo sconfigge. if collision(missile0,player1) && a = 0 then v = 152 : score = score + 1 : goto killwright rem Collisione giocatore-nemico: resetta posizione, perde punti. if collision(player0,player1) then player0x = 56 : player0y = 96 : i = 0 : score = score -1 : if d = 30 then v = v + 5 rem Collisione giocatore-mattone: prende possesso del mattone. if collision(ball,player0) then ballx = player0x - 3 : bally = player0y - 11 : i = 1 rem Collisione mattone-muro: posa il mattone. if collision(ball, playfield) then gosub putoncastle rem --- IA del Nemico --- rem Muove il nemico verso il giocatore solo se il timer 't' supera la soglia 'd'. if t player0x then v=v-1 : AUDV1 = 4 if w < player0y then w=w+1 if w > player0y then w=w-1 : AUDV1 = 4 skipmovement rem Ripete il ciclo di gioco. goto loop rem --- Subroutine per Costruire il Castello --- putoncastle rem Controlla la posizione del mattone e, se lo spazio è libero (!pfread), disegna un nuovo pixel. if bally > 11 && bally < 17 && !pfread(0,1) then pfpixel 0 1 on : i = 0 : ballx = 81 : bally = 39 : j = 1 if bally >= 17 && bally < 25 && !pfread(1,2) then pfpixel 1 2 on : i = 0 : ballx = 81 : bally = 75 : k = 1 if bally >= 25 && bally < 35 && !pfread(3,3) then pfpixel 3 3 on : i = 0 : ballx = 81 : bally = 11 : l = 1 if bally >= 35 && bally < 41 && !pfread(2,4) then pfpixel 2 4 on : i = 0 : ballx = 81 : bally = 59 : o = 1 if bally >= 41 && bally < 49 && !pfread(1,5) then pfpixel 1 5 on : i = 0 : ballx = 81 : bally = 19 : p = 1 if bally >= 49 && bally < 56 && !pfread(1,6) then pfpixel 1 6 on : i = 0 : ballx = 81 : bally = 53 : q = 1 if bally >= 56 && bally < 65 && !pfread(3,7) then pfpixel 3 7 on : i = 0 : ballx = 81 : bally = 27 : r = 1 if bally >= 65 && bally < 73 && !pfread(0,8) then pfpixel 0 8 on : i = 0 : ballx = 81 : bally = 19 : s = 1 if bally >= 73 && bally < 78 && !pfread(1,9) then pfpixel 1 9 on : i = 0 : ballx = 81 : bally = 65 : u = 1 return rem --- Subroutine Grafiche Giocatore --- frame1 rem Primo frame dell'animazione di camminata. player0: %11111100 %11011000 %11011000 %11011000 %11011000 %11111000 %10011010 %11001010 %11101111 %11111010 %01111010 %10110010 %11001010 %01001010 %01001010 %00110000 end return frame2 rem Secondo frame dell'animazione di camminata. player0: %11101100 %11001110 %11001100 %11011100 %11011000 %11111000 %10011010 %11001010 %11101111 %11111010 %01111010 %10110010 %11001010 %01001010 %01001010 %00110000 end return dosword rem Frame per l'animazione di attacco con la spada. player0: %11111100 %11011000 %11011000 %11011000 %11011000 %11111001 %10011001 %11001111 %11101001 %11111001 %01111000 %10110000 %11001000 %01001000 %01001000 %00110000 end return rem --- Subroutine Audio ed Eventi --- killwright rem Suono per la sconfitta del nemico. AUDV1 = 4 AUDC1 = 7 AUDF1 = e e = e + 1 drawscreen if e < 10 then killwright e = 0 AUDV1 = 0 : AUDC1 = 0 : AUDF1 = 0 score = score + 1 rem Aggiorna la resistenza del nemico per il prossimo livello. if d <= 30 then a = 4 if d <= 20 then a = 2 if d <= 10 then a = 0 goto loop strikewright rem Suono per il nemico colpito. AUDV1 = 4 AUDC1 = 7 AUDF1 = 2 g = g + 1 drawscreen if g < 5 then strikewright g = 0 AUDV1 = 0 : AUDC1 = 0 : AUDF1 = 0 goto loop castlecompleted rem Suono per il completamento del muro. AUDV1 = y AUDC1 = 4 AUDF1 = y y = y + 1 drawscreen if y < 64 then goto castlecompleted rem Aumenta la difficoltà per il livello successivo. y = 0 d = d - 1 score = score + 2 if d <= 30 then a = 4 if d <= 20 then a = 2 : h = 40 if d <= 10 then a = 1 : h = 60 if d = 0 then d = 1 AUDV1 = 0 : AUDC1 = 0 : AUDF1 = 0 goto preloop -------------------------------------------------------------------------- Minotaur -------------------------------------------------------------------------- rem ****************************************************************** rem * Minotaur * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Il giocatore controlla un eroe (player0) in un labirinto a * rem * schermate multiple. Lo scopo è esplorare, raccogliere oggetti * rem * (lancia, scudo), sconfiggere un Minotauro (player1) e * rem * raccogliere monete per aumentare il punteggio. Il mondo è * rem * composto da diverse stanze interconnesse. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Esplorazione a Schermate Multiple: Il gioco gestisce il * rem * passaggio tra diverse stanze (`room`). Quando il giocatore * rem * raggiunge un bordo dello schermo, la variabile `room` viene * rem * aggiornata, viene chiamata la subroutine della nuova stanza * rem * e il giocatore viene riposizionato sul lato opposto. * rem * - Sistema di Inventario e Stati: Variabili come `haslance`, * rem * `hasshield` e `hascoin` fungono da flag per tenere traccia * rem * degli oggetti raccolti e degli stati del giocatore (es. può * rem * attaccare, è protetto, ha raccolto la moneta). * rem * - Logica di Combattimento: Il giocatore può attaccare con una * rem * lancia (missile0), la cui forma e direzione cambiano in * rem * base all'orientamento del giocatore. Il Minotauro ha una * rem * sorta di "punti vita" (`minotauro`) e cambia aspetto quando * rem * viene colpito. * rem * - IA di Pattugliamento: Il Minotauro non insegue direttamente * rem * il giocatore, ma si muove lungo un percorso predefinito, * rem * pattugliando l'area. * rem * - Gestione di Oggetti Multipli con Sprite: Il gioco usa gli * rem * oggetti TIA in modo creativo. `player0` è l'eroe, `player1` è* rem * il Minotauro O la moneta, `missile0` è la lancia e `ball` è * rem * lo scudo. Il codice gestisce quale oggetto visualizzare in * rem * base allo stato del gioco. * rem * - Logica di Collisione Avanzata: Il movimento del giocatore * rem * viene bloccato dalle pareti del `playfield` ripristinando la * rem * sua posizione precedente in caso di collisione. * rem ****************************************************************** set romsize 4k set smartbranching on rem --- Sezione Definizioni Variabili (Alias) --- rem Flag per bloccare il movimento dopo una collisione con i muri. dim nodown = a dim noup = b dim noleft = c dim noright = d rem Numero della stanza corrente. dim room = e rem Stato della lancia (0=non posseduta, 1=in mano, 2=lanciata, 3=a terra). dim haslance = f rem Flag per il possesso dello scudo (0=no, 1=sì). dim hasshield = g rem Flag per indicare se la moneta nella stanza è stata raccolta. dim hascoin = h rem Variabile temporanea per i numeri casuali. dim randnumber = i rem Valore della moneta corrente (1, 5, o 32). dim coinvalue = j rem Direzione del giocatore (1=su, 2=destra, 3=giù, 4=sinistra). dim compass = k rem "Punti vita" del Minotauro (2=sano, 1=ferito, 0=morto). dim minotauro = m rem Contatore per l'invulnerabilità temporanea del giocatore dopo essere stato colpito. dim hitted = n init rem --- Inizializzazione Globale --- score = 0 COLUBK = $F4 rem --- Inizializzazione Variabili di Stato --- haslance = 0 hasshield = 0 hascoin = 0 coinvalue = 1 hitted = 0 room = 0 nodown = 0 noup = 0 noleft = 0 noright = 0 rem --- Impostazioni Iniziali Oggetti di Gioco --- player0x = 24 player0y = 76 missile0height = 8 missile0x = 83 missile0y = 48 ballheight = 4 rem CTRLPF=$21 imposta la palla (scudo) dietro al playfield. CTRLPF = $21 ballx = 0 bally = 0 rem per inizializzare le collisioni drawscreen rem --- Ciclo di Gioco Principale --- mainloop rem Carica la stanza 1 se il gioco è appena iniziato (room=0). if room = 0 then gosub room1 : gosub moverderecha : gosub minoheridados : COLUP0 = $86 rem Imposta la dimensione dello sprite del nemico. NUSIZ1 = $10 rem Imposta il colore del nemico/moneta. Cambia colore in base al valore della moneta. COLUP1 = $4A if coinvalue = 5 then COLUP1 = $0A if coinvalue = 32 then COLUP1 = $1E rem Gestisce l'invulnerabilità del giocatore: se è stato colpito, lampeggia. if hitted > 0 then hitted = hitted - 1 : COLUP0 = $40 else COLUP0 = $86 rem --- Logica di Raccolta Oggetti --- rem Raccoglie la lancia (missile0). if collision(missile0,player0) && haslance = 0 then haslance = 1 : NUSIZ0 = $00 : missile0height = 8 rem Raccoglie la lancia dopo averla lanciata. if collision(missile0,player0) && haslance = 3 then haslance = 1 : NUSIZ0 = $00 : missile0height = 8 rem Raccoglie lo scudo (ball). if collision(ball,player0) && hasshield = 0 then hasshield = 1 rem --- Logica delle Collisioni Principali --- rem Collisione con Minotauro: se ha lo scudo, lo perde. Se non ce l'ha, muore (non implementato). if minotauro > 0 && hitted = 0 && collision(player1,player0) && hasshield = 1 then hasshield = 0 : ballx = 0 : bally = 0 : gosub hit if minotauro > 0 && hitted = 0 && collision(player1,player0) && hasshield = 0 then goto gameover rem Collisione con moneta (quando il minotauro è morto). if minotauro = 0 && collision(player1,player0) && hascoin = 0 then hascoin = 1 : score = score + coinvalue : gosub colocarmoneda rem --- Gestione Input Giocatore (Movimento e Attacco) --- if joy0left && !joy0right && !joy0up && !joy0down && noleft = 0 then gosub moverizquierda if !joy0left && joy0right && !joy0up && !joy0down && noright = 0 then gosub moverderecha if !joy0left && !joy0right && joy0up && !joy0down && noup = 0 then gosub moverarriba if !joy0left && !joy0right && !joy0up && joy0down && nodown = 0 then gosub moverabajo if joy0fire && haslance = 1 then haslance = 2 rem --- Logica della Lancia --- rem Muove la lancia se è stata lanciata. if haslance = 2 && !collision(playfield,missile0) then gosub moverlanza rem Ferma la lancia se colpisce un muro. if haslance = 2 && collision(playfield,missile0) && compass = 2 then haslance = 3 : missile0x = missile0x - 0 if haslance = 2 && collision(playfield,missile0) then haslance = 3 rem Ferisce il Minotauro se lo colpisce. if haslance = 2 && collision(player1,missile0) then haslance = 3 : minotauro = minotauro - 1 rem --- Logica del Nemico --- rem Aggiorna la posizione e l'aspetto del Minotauro. if minotauro > 0 then gosub moverenemigo else gosub minomuerto if minotauro = 1 then gosub minoheridauno rem --- Logica Grafica della Lancia --- rem Cambia la forma della lancia (orizzontale/verticale) in base alla direzione. if compass = 1 && haslance = 3 then NUSIZ0 = $00 : missile0height = 8 if compass = 2 && haslance = 3 then NUSIZ0 = $30 : missile0height = 0 if compass = 3 && haslance = 3 then NUSIZ0 = $00 : missile0height = 8 if compass = 4 && haslance = 3 then NUSIZ0 = $30 : missile0height = 0 rem --- Gestione Posizione Oggetti Nelle Stanze --- rem Posiziona/nasconde la lancia e lo scudo a seconda della stanza in cui si trova il giocatore. if room = 1 && haslance = 0 then missile0x = 83 : missile0y = 48 if room <> 1 && haslance = 0 then missile0x = 0 : missile0y = 0 if room = 2 && hasshield = 0 then ballx = 83 : bally = 45 if room <> 2 && hasshield = 0 then ballx = 0 : bally = 0 rem --- Logica di Transizione tra le Stanze --- rem Controlla se il giocatore ha raggiunto un bordo per cambiare stanza. if room = 1 && player0x > 145 then gosub room2 : player0x = 22 if room = 2 && player0x < 5 then gosub room1 : player0x = 140 if room = 1 && player0y < 10 then gosub room3 : player0y = 80 if room = 3 && player0y > 85 then gosub room1 : player0y = 10 if room = 3 && player0x > 145 then gosub room4 : player0x = 22 if room = 4 && player0x < 5 then gosub room3 : player0x = 140 if room = 2 && player0y < 5 then gosub room4 : player0y = 80 if room = 4 && player0y > 85 then gosub room2 : player0y = 10 if room = 3 && player0y < 10 then gosub room5 : player0y = 80 if room = 5 && player0y > 85 then gosub room3 : player0y = 10 if room = 4 && player0x > 145 then gosub room6 : player0x = 22 if room = 6 && player0x < 5 then gosub room4 : player0x = 140 if room = 6 && player0x > 145 then gosub room7 : player0x = 22 if room = 7 && player0x < 5 then gosub room6 : player0x = 140 if room = 7 && player0x > 145 then gosub room9 : player0x = 22 if room = 9 && player0x < 5 then gosub room7 : player0x = 140 if room = 8 && player0y < 5 then gosub room7 : player0y = 80 if room = 7 && player0y > 85 then gosub room8 : player0y = 10 rem Disegna il fotogramma e ripete il ciclo. drawscreen goto mainloop gameover if joy0fire then goto gameover gameover2 COLUBK = $08 drawscreen if joy0fire then goto init goto gameover2 rem --- Subroutine di Movimento e Collisione con i Muri --- moverizquierda player0: %01101100 %00100100 %00100100 %00011000 %11111111 %10011001 %00100100 %00111100 %00110110 end rem Imposta la direzione e controlla la collisione con il playfield. if haslance = 1 then compass = 4 if collision(playfield,player0) then gosub x001 else gosub x002 rem Aggiorna la posizione di lancia e scudo per "attaccarli" al giocatore. if haslance = 1 then missile0x = player0x : missile0y = player0y - 2 if hasshield = 1 then ballx = player0x + 7 : bally = player0y - 3 return x001 rem Se c'è collisione, spinge indietro il giocatore. player0x = player0x + 1 : noright = 0 : noleft = 1 : noup = 0 nodown = 0 return x002 rem Se non c'è collisione, esegue il movimento. player0x = player0x - 1 : noright = 0 : noleft = 0 noup = 0 : nodown = 0 return x003 player0x = player0x - 1 : noright = 1 : noleft = 0 noup = 0 : nodown = 0 return x004 player0x = player0x + 1: noright = 0 : noleft = 0 : noup = 0 : nodown = 0 return x005 player0y = player0y + 1 : noright = 0 : noleft = 0 : noup = 1 : nodown = 0 return x006 player0y = player0y - 1: noright = 0 : noleft = 0 : noup = 0 : nodown = 0 return x007 player0y = player0y - 1 : noright = 0 : noleft = 0 : noup = 0 : nodown = 1 return x008 player0y = player0y + 1: noright = 0 : noleft = 0 : noup = 0 : nodown = 0 return moverderecha player0: %00110110 %00100100 %00100100 %00011000 %11111111 %10011001 %00100100 %00111100 %01101100 end if haslance = 1 then compass = 2 if collision(playfield,player0) then gosub x003 else gosub x004 if haslance = 1 then missile0x = player0x + 9 : missile0y = player0y - 2 if hasshield = 1 then ballx = player0x - 1 : bally = player0y - 3 return moverarriba player0: %01100110 %00100100 %00100100 %00011000 %11111111 %10011001 %00100100 %00111100 %00100100 end if haslance = 1 then compass = 1 if collision(playfield,player0) then gosub x005 else gosub x006 if haslance = 1 then missile0x = player0x : missile0y = player0y - 2 if hasshield = 1 then ballx = player0x + 7 : bally = player0y - 3 return moverabajo player0: %01100110 %00100100 %00100100 %10011001 %11111111 %00011000 %00100100 %00111100 %00100100 end if haslance = 1 then compass = 3 if collision(playfield,player0) then gosub x007 else gosub x008 if haslance = 1 then missile0x = player0x : missile0y = player0y - 2 if hasshield = 1 then ballx = player0x + 7 : bally = player0y - 3 return rem --- Subroutine di Gioco --- hit rem Attiva l'invulnerabilità temporanea del giocatore. if hitted = 0 then hitted = 100 return colocarmoneda rem Posiziona una moneta in un punto casuale della stanza. gosub minoheridados if hascoin = 1 then player1x = 0 : player1y = 0 randnumber = rand if hascoin = 0 && randnumber <= 153 then coinvalue = 1 if hascoin = 0 && randnumber > 153 && randnumber <= 204 then coinvalue = 5 if hascoin = 0 && randnumber > 204 && randnumber <= 255 then coinvalue = 32 randnumber = rand if hascoin = 0 && randnumber <= 64 then player1x = 28 : player1y = 22 if hascoin = 0 && randnumber > 65 && randnumber <= 128 then player1x = 118 : player1y = 22 if hascoin = 0 && randnumber > 129 && randnumber <= 192 then player1x = 28 : player1y = 77 if hascoin = 0 && randnumber > 193 && randnumber <= 255 then player1x = 118 : player1y = 77 return moverlanza rem Muove la lancia in base alla direzione del giocatore. if compass = 1 then NUSIZ0 = $00 : missile0height = 8 : missile0y = missile0y - 2 if compass = 2 then NUSIZ0 = $30 : missile0height = 0 : missile0x = missile0x + 2 if compass = 3 then NUSIZ0 = $00 : missile0height = 8 : missile0y = missile0y + 2 if compass = 4 then NUSIZ0 = $30 : missile0height = 0 : missile0x = missile0x - 2 return moverenemigo rem IA di pattugliamento: il Minotauro si muove lungo un percorso rettangolare. if minotauro > 0 && player1y = 22 && player1x < 118 then player1x = player1x + 1 if minotauro > 0 && player1y = 77 && player1x > 28 then player1x = player1x - 1 if minotauro > 0 && player1x = 118 && player1y < 77 then player1y = player1y + 1 if minotauro > 0 && player1x = 28 && player1y > 22 then player1y = player1y - 1 return rem --- Subroutine Grafiche Nemico --- minoheridados rem Sprite del Minotauro sano. player1: %01101100 %01101100 %00100100 %00100100 %00011000 %00011000 %11011011 %11111111 %00011000 %00100100 %01111110 %01000010 end minotauro = 2 return minoheridauno rem Sprite del Minotauro ferito. player1: %01101100 %01101100 %00100100 %00100100 %00011000 %00011000 %11011011 %11111111 %00011000 %00100100 %00111100 end return minomuerto rem Sprite del Minotauro sconfitto (ora appare la moneta al suo posto). player1: %00010000 %00001000 %11101011 %00011101 %00011101 %11101011 %00001000 %00010000 end return rem --- Subroutine di Definizione delle Stanze --- rem Ognuna di queste subroutine definisce la grafica di una stanza rem e la logica per la generazione delle monete al suo interno. room1 room = 1 hascoin = 0 COLUPF = $C0 playfield: XXXXXXXXXXXXX.......XXXXXXXXXXXX X..............................X X..............................X X............XXXXXXX...........X X..................X............ X..................X............ X..................X............ X............XXXXXXX...........X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if haslance = 1 then gosub colocarmoneda else hascoin = 1 : gosub colocarmoneda if haslance = 3 then haslance = 0 : NUSIZ0 = $00 : missile0height = 8 return room2 room = 2 hascoin = 0 playfield: XXXXXXXXXXXXX.......XXXXXXXXXXXX X..............................X X..............................X X............XXXXXXX...........X .............X.................X .............X.................X .............X.................X X............XXXXXXX...........X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if hasshield = 1 then gosub colocarmoneda else hascoin = 1 : gosub colocarmoneda if haslance = 3 then haslance = 0 return room3 room = 3 hascoin = 0 playfield: X......XXXXXXXXX.......XXXXXXXXX X..............................X X..............................X X............XXXXXXX...........X X............................... X............................... X............................... X............XXXXXXX...........X X..............................X X..............................X XXXXXXXXXXXXX.......XXXXXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return room4 room = 4 hascoin = 0 playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X...........X.......X..........X ............X.......X........... ............X.......X........... ............X.......X........... X...........X.......X..........X X..............................X X..............................X XXXXXXXXXXXXX.......XXXXXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return room5 room = 5 hascoin = 0 playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............................X X......XXXXXXXXXXXXXXXXXXXXXXXXX X......X.......................X X......X.......................X X......X.......................X X......X.......................X X......X.......................X X......XXXXXXXXX.......XXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return room6 room = 6 hascoin = 1 playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXX........ XXXXXXXXXXXXXXXXXXXXXXXX........ XXXXXXXXXXXXXXXXXXXXXXXX........ .........XXXXXXXXXXXXXXX.......X .........XXXXXXXXXXXXXXX.......X .........XXXXXXXXXXXXXXX.......X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return room7 room = 7 hascoin = 1 playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ....................XXXXXXXXXXXX ....................XXXXXXXXXXXX ....................XXXXXXXXXXXX XXXXXXXXXXXXX..................X XXXXXXXXXXXXX..................X XXXXXXXXXXXXX..................X XXXXXXXXXXXXX.......XXXXXXXXXXXX XXXXXXXXXXXXX.......X........... XXXXXXXXXXXXX.......X........... XXXXXXXXXXXXX.......X..........X end gosub colocarmoneda if haslance = 3 then haslance = 0 return room8 room = 8 hascoin = 0 playfield: XXXXXXXXXXXXX.......XX.........X X...................XX.........X X...................XX.........X X...................XX.........X X...................XX.........X X...................XX.........X X.......XXXXXXXXXXXXXX.........X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return room9 room = 9 hascoin = 0 playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X............XXXXXXX...........X X............X.................X X............X.................X X............X.................X X............XXXXXXX...........X ...............................X ...............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end gosub colocarmoneda if haslance = 3 then haslance = 0 return -------------------------------------------------------------------------- Snappy -------------------------------------------------------------------------- rem ****************************************************************** rem * Snappy * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Il giocatore controlla un esploratore (player0) che deve * rem * attraversare una voragine usando una liana (playfield). Il * rem * tempismo è cruciale: se l'esploratore salta al momento * rem * sbagliato, cadrà nella voragine dove un coccodrillo * rem * (Snappy, player1) lo attende. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Macchina a Stati (State Machine): Il cuore del programma. * rem * La variabile `gamestate` controlla lo stato attuale del * rem * giocatore (in caduta, in attesa, in corsa, sulla liana, * rem * etc.). Il `main_loop` delega la logica a una subroutine * rem * "centralino" (`handlestate`) che esegue solo il codice * rem * relativo allo stato corrente, mantenendo il programma * rem * organizzato ed efficiente. * rem * - Animazione basata su Timer: L'animazione della liana, del * rem * giocatore e del coccodrillo è gestita da contatori * rem * (`frame`, `playerframe`, `snappyframe`) che vengono * rem * incrementati a ogni ciclo. Questo permette di alternare * rem * le definizioni grafiche per creare l'illusione del * rem * movimento. * rem * - Gestione Audio con Subroutine: Gli effetti sonori sono * rem * incapsulati in piccole subroutine (`playvinesound`, * rem * `playdeathsound`, etc.) e attivati in punti specifici del * rem * codice per sincronizzarli con l'azione. * rem * - Generazione del Seme Casuale (Seed): Nella schermata del * rem * titolo, un contatore (`randseed`) viene incrementato. * rem * Questo valore viene poi usato per inizializzare il * rem * generatore di numeri casuali `rand`, garantendo che la * rem * posizione iniziale del giocatore cambi a ogni partita. * rem ****************************************************************** rem --- Direttive del Compilatore --- set romsize 4k rem --- Sezione Definizioni Variabili (Alias) --- rem Contatore per l'animazione della liana (0-119). Determina la posizione della liana. dim frame = d rem Contatore per l'animazione del giocatore. Decide quale frame di animazione dell'eroe mostrare. dim playerframe = e rem Gestore dello stato di gioco. La variabile "cervello" che controlla la logica corrente. dim gamestate = f rem Contatore per l'animazione del coccodrillo 'Snappy'. dim snappyframe = g rem Variabile per l'effetto cambio colore nella schermata del titolo. dim introcolour = h rem Contatore per l'animazione di Snappy che mangia il giocatore. dim snappyeatingframe = i rem Contatore delle vite del giocatore. dim life = j rem Contatore usato per generare un seme casuale per il comando 'rand'. dim randseed = k rem --- Inizializzazione delle Variabili di Gioco (eseguita una sola volta) --- rem Imposta la posizione iniziale della liana. frame = 30 rem Azzera il contatore per il seme casuale. randseed = 0 rem Inizia con il primo frame di animazione del giocatore. playerframe = 0 rem --- Definizione degli Stati della Macchina a Stati (gamestate) --- rem 1 = Il giocatore sta cadendo con il paracadute. rem 2 = Il giocatore è a terra e in attesa dell'input. rem 3 = Il giocatore sta correndo verso la voragine. rem 4 = Il giocatore è aggrappato alla liana. rem 5 = Il giocatore corre verso il traguardo dopo la liana. rem 6 = Il giocatore è al sicuro (stato iniziale o dopo aver completato un round). rem 7 = Il giocatore sta cadendo nella voragine (morte). rem 8 = Il coccodrillo 'Snappy' sta mangiando il giocatore. rem Inizia il gioco nello stato 'sicuro'. gamestate = 6 rem --- Impostazioni Iniziali HUD --- rem Imposta il colore per il punteggio. scorecolor = 22 rem Imposta il colore iniziale per l'effetto del titolo. introcolour = 0 rem Salta direttamente al ciclo di gioco principale. goto main rem ========================================================== rem ====== Sottoprogramma: Schermata Titolo e Attesa ========= rem ========================================================== showintro rem Definisce la grafica statica del titolo (testo "SNAPPY"). playfield: ................................ ...XXX.......................... ..X...X......................... ..X............................. ...XXX..XX...XXX..XX..XX..X..X.. ......X.X.X.X..X..X.X.X.X.X..X.. ..X...X.X.X.X..X..X.X.X.X.X..X.. ...XXX..X.X..XX.X.XX..XX...XXX.. ..................X...X......X.. ..................X...X....XX... ................................ end rem --- Logica della Schermata Titolo --- rem Incrementa la variabile per creare un effetto di cambio colore arcobaleno. introcolour = introcolour + 1 COLUPF = introcolour rem Imposta i registri TIA: sfondo e sprite neri per nasconderli. COLUBK = 0 COLUP0 = 0 COLUP1 = 0 rem Nasconde fisicamente gli sprite posizionandoli fuori dallo schermo. player0x = 0 player0y = 0 player1x = 0 player1y = 0 rem Incrementa il seme per il generatore di numeri casuali mentre il giocatore attende. randseed = randseed + 1 rem Silenzia entrambi i canali audio. gosub stopvoiceone gosub stopvoicezero rem Disegna lo schermo e attende l'input del giocatore. drawscreen rem Se il giocatore preme fuoco, inizia il gioco. if joy0fire then goto initialize rem Altrimenti, continua a mostrare la schermata del titolo. goto showintro rem ================================================== rem ====== Sottoprogramma: Inizializzazione Partita ====== rem ================================================== initialize rem Azzera il punteggio e imposta le vite. score = 0 life = 10 rem Inizializza il generatore di numeri casuali con il seme raccolto durante la schermata del titolo. if randseed = 0 then rand = 1 else rand = randseed rem Torna al ciclo di gioco principale per iniziare la partita. goto main rem =================================================== rem ====== Sottoprogramma: Animazione di Snappy ======= rem =================================================== animatesnappy rem Alterna due sprite per il coccodrillo in base al contatore 'snappyframe' per creare un'animazione a 2 frame. if snappyframe = 0 then player1: %00111100 %00111100 %00111100 %00111100 %01100111 %01100110 %01100110 %11000011 %11000011 %11000011 %10000001 end if snappyframe = 10 then player1: %00111100 %00111100 %00111100 %00111100 %00111110 %00111100 %00111100 %00111100 %00011100 %00011100 %00011000 end return rem ==================================================== rem ====== Sottoprogramma: Animazione della Liana ====== rem ==================================================== swingvine rem Questa lunga catena di 'if' disegna una diversa grafica del playfield in base al valore del contatore 'frame', simulando l'oscillazione della liana. if frame = 0 then playfield: ..................XXXXXXXXX..... ......................X......... .....................X.......... ....................X........... ...................X............ ..................X............. ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 10 || frame = 110 then playfield: ..................XXXXXXXXX..... ......................X......... .....................X.......... .....................X.......... ....................X........... ...................X........... ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 20 || frame = 100 then playfield: ..................XXXXXXXXX..... ......................X......... ......................X......... .....................X.......... .....................X.......... .....................X.......... ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 30 || frame = 90 then playfield: ..................XXXXXXXXX..... ......................X......... ......................X......... ......................X......... ......................X......... ......................X......... ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 40 || frame = 80 then playfield: ..................XXXXXXXXX..... ......................X......... ......................X......... .......................X........ .......................X........ .......................X........ ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 50 || frame = 70 then playfield: ..................XXXXXXXXX..... ......................X......... .......................X........ .......................X........ ........................X....... .........................X...... ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end if frame = 60 then playfield: ..................XXXXXXXXX..... ......................X......... .......................X........ ........................X....... .........................X...... ..........................X..... ................................ XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXX.........XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Sincronizza l'audio con l'animazione della liana. if frame = 0 then gosub playvinesound if frame = 60 then gosub playvinesecondsound rem Spegne il suono dopo pochi frame per creare un effetto breve. if frame = 3 then gosub stopvoicezero if frame = 63 then gosub stopvoicezero return rem =================================== rem ==== Sottoprogrammi Audio ========= rem =================================== playvinesound AUDV0=4:AUDC0=12:AUDF0=28 return playvinesecondsound AUDV0=4:AUDC0=12:AUDF0=20 return playdeathsound AUDV1=4:AUDC1=14:AUDF1=20 return playvictorysound AUDV1=4:AUDC1=4:AUDF1=10 return stopvoicezero AUDV0=0 return stopvoiceone AUDV1=0 return rem ==================================================== rem ====== Sottoprogrammi Grafici: Disegno del Giocatore ====== rem ==================================================== drawplayer rem Alterna due sprite per l'animazione di corsa del giocatore in base al timer 'playerframe'. if playerframe = 0 then player0: %00110110 %00100100 %00100100 %00011000 %01111110 %00011000 %00111100 %00111100 end if playerframe = 10 then player0: %00011100 %00011000 %00011000 %00011010 %00111100 %01011000 %00111100 %00111100 end return drawplayerparachute rem Sprite speciale per il giocatore quando si lancia col paracadute. player0: %00110110 %00100100 %00100100 %00011000 %00111100 %01011010 %01111110 %01111110 %00100100 %00100100 %01000010 %10000001 %11111111 %11111111 %01111110 %00111100 end return drawplayerbeingeaten rem Sprite del giocatore mentre viene mangiato. player0: %00000000 %00000000 %00000000 %00000000 %00011110 %00011000 %00111100 %00111100 end return rem ================================= rem ====== CICLO DI GIOCO PRINCIPALE ====== rem ================================= main rem Controlla se il gioco e' finito (Game Over). Se si, torna alla schermata del titolo. if life = 0 then goto showintro rem Aggiorna la grafica della liana (playfield). gosub swingvine rem Aggiorna la grafica di Snappy (player1). gosub animatesnappy rem Seleziona lo sprite corretto per il giocatore (player0) in base allo stato attuale del gioco. rem Se sta cadendo, disegna il paracadute. if gamestate = 1 then gosub drawplayerparachute rem Se viene mangiato, disegna l'animazione corrispondente. if gamestate = 8 then gosub drawplayerbeingeaten rem In tutti gli altri casi, disegna l'animazione di corsa. if gamestate <> 1 && gamestate <> 8 then gosub drawplayer rem Incrementa i contatori per le animazioni. frame=frame+1 playerframe=playerframe+1 snappyframe=snappyframe+1 rem Accelera l'animazione di Snappy quando sta mangiando il giocatore. if gamestate = 8 then snappyframe=snappyframe+1 rem Azzera i contatori quando raggiungono il loro limite per creare un loop. if playerframe >= 20 then playerframe=0 if frame>=120 then frame=0 if snappyframe >= 20 then snappyframe=0 rem Esegue la logica dello stato di gioco corrente ("Centralino" della Macchina a Stati). gosub handlestate rem Imposta i registri TIA volatili ad ogni frame. rem Colore di Snappy COLUP1 = 206 rem Colore del Giocatore COLUP0 = 28 rem Colore dello Sfondo (cielo/acqua) COLUBK = 192 rem Colore del Playfield (liana/terreno) COLUPF = 88 rem Comando che dice al TIA di disegnare l'intero frame. drawscreen rem Torna all'inizio del ciclo di gioco. goto main rem =========================================================== rem = Sottoprogramma: Centralino della Macchina a Stati = rem = Esegue la subroutine corretta in base al valore di 'gamestate' = rem =========================================================== handlestate if gamestate = 6 then gosub createplayer : return if gamestate = 1 then gosub dropplayer : return if gamestate = 2 then gosub playerwaiting : return if gamestate = 3 then gosub playerrunning : return if gamestate = 4 then gosub playeronvine : return if gamestate = 7 then gosub playerdying : return if gamestate = 5 then gosub playerruntosafety : return if gamestate = 8 then gosub snappyeating : return return snappyeating rem Gestisce l'animazione di Snappy che mangia il giocatore. snappyeatingframe = snappyeatingframe + 1 playerframe=0 rem Dopo 60 frame, il round finisce e il giocatore perde una vita. if snappyeatingframe = 60 then gosub stopvoiceone : gamestate = 6 : life=life-1 return playerdying rem Il giocatore cade verso il basso nella voragine. player0y = player0y + 1 rem Quando raggiunge il fondo, passa allo stato 'snappyeating'. if player0y = 74 then gamestate = 8 : gosub playdeathsound return playerruntosafety rem Il giocatore corre verso il bordo destro dello schermo per completare il livello. player0x = player0x + 1 rem Se ha raggiunto la salvezza alla fine dello schermo, il round è vinto. if player0x = 139 then gamestate = 6 : score = score + 1 : gosub stopvoiceone : life=life-1 return playeronvine rem Aggiorna la posizione orizzontale del giocatore per seguire l'oscillazione della liana. if frame = 20 then player0x = 98 if frame = 30 then player0x = 106 if frame = 40 then player0x = 111 if frame = 50 then player0x = 116 if frame = 60 then player0x = 121 rem Quando la liana raggiunge l'altro lato, il giocatore si stacca. if frame = 60 then gamestate = 5 : gosub playvictorysound return playerrunning rem Il giocatore corre verso la voragine. player0x = player0x + 1 rem Controlla se il giocatore afferra la liana quando raggiunge il bordo della voragine. if player0x = 90 then gosub didplayercatchvine return didplayercatchvine rem Controlla se la liana ('frame') è nella posizione giusta per essere afferrata. Se non lo è, il giocatore cade. if frame <= 10 || frame >= 115 then gamestate = 4 else gamestate = 7 : player1x = 90 return playerwaiting rem Blocca l'animazione del giocatore in attesa dell'input. playerframe = 0 rem Se il giocatore preme 'fuoco', inizia a correre. if joy0fire then gamestate = 3 return dropplayer rem Il giocatore scende con il paracadute. player0y = player0y + 1 rem Quando raggiunge il terreno, passa allo stato di attesa. if player0y = 56 then gamestate = 2 rem Blocca l'animazione durante la discesa per mostrare il giocatore fermo. playerframe = 0 return createplayer rem Inizia un nuovo round. Genera il giocatore in una posizione casuale. player0x = 20 + (rand / 4) player0y = 10 rem Imposta lo stato iniziale su 'dropplayer' (caduta col paracadute). gamestate = 1 playerframe = 0 rem Resetta la posizione di Snappy in fondo alla voragine. player1x = 102 player1y = 80 snappyeatingframe = 0 return   -------------------------------------------------------------------------- Gnamm -------------------------------------------------------------------------- rem ****************************************************************** rem * Gnamm * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Una versione semplificata del classico vidogame. Il giocatore * rem * (player0) si muove in un labirinto statico, mangiando palline. * rem * Un fantasma (player1) insegue il giocatore attraverso il * rem * labirinto. Il gioco include la musica di inizio, i suoni per * rem * le palline e una sequenza di animazione per la morte del * rem * giocatore. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - IA di Inseguimento Semplice: Il fantasma non si muove a * rem * caso, ma cerca attivamente di raggiungere il giocatore. * rem * Ad ogni incrocio, decide se dare priorità al movimento * rem * orizzontale o verticale per ridurre la distanza dal suo * rem * bersaglio, pur rispettando i vincoli del labirinto. * rem * - Uso Intensivo dei Bit-Flag: Quasi tutta la logica di stato * rem * del gioco è gestita tramite singoli bit della variabile b, * rem * controllando movimento, suoni, animazioni e logica. * rem * - Movimento su Griglia: Il movimento del giocatore è vincolato * rem * a una griglia invisibile. I bit-flag `b{0}` e `b{1}` * rem * verificano se il giocatore è a un "incrocio" e può cambiare * rem * direzione. * rem * - Animazione a Frame Multipli per Direzione: Il giocatore ha * rem * set di animazioni diversi per ogni direzione di movimento * rem * (su, giù, sinistra/destra), creando un effetto più realistico. * rem * - Interazione Dinamica con il Playfield: Le palline da * rem * mangiare sono parte del `playfield`. Il comando `pfpixel` * rem * viene usato per "cancellarle" dinamicamente. * rem * - Kernel Option `pfcolors`: Questa opzione viene usata per * rem * dare al labirinto un aspetto bicolore. * rem ****************************************************************** rem --- Direttive del Compilatore --- set romsize 4k set kernel_options pfcolors set smartbranching on rem --- Alias delle Variabili --- dim player_x = player0x dim player_y = player0y dim ghost_x = player1x dim ghost_y = player1y dim player_dir = c dim ghost_dir = r dim ghost_can_h = t dim ghost_can_v = u dim tmp1 = v dim tmp2 = w dim framecounter = z rem bit-flags: rem b{0} = giocatore a incrocio orizzontale rem b{1} = giocatore a incrocio verticale rem b{2} = toggle movimento giocatore (per rallentare) rem b{3} = direzione orizzontale giocatore (0=destra,1=sinistra) rem b{4} = sequenza di fine livello rem b{5} = suono "waka-waka" attivo rem b{6} = animazione di morte attiva rem b{7} = sequenza di inizio partita attiva rem Imposta il flag b{7} per indicare che siamo nella sequenza di inizio. b{7}=1 rem --- Stato 0: Inizio Partita / Animazione Iniziale --- beginning g=0 rem Definisce la grafica del labirinto. playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..X.X.......X.X..X.X.......X.X.. ..XXXXXXXXXXXXX..XXXXXXXXXXXXX.. ..X.X.X.X.X.X.X..X.X.X.X.X.X.X.. ..XXXXXXXXXXXXX..XXXXXXXXXXXXX.. ......X.X.X..........X.X.X...... ..XXXXXXXXXXXXX..XXXXXXXXXXXXX.. ..X.X.X.X.X.X.X..X.X.X.X.X.X.X.. ..XXXXXXXXXXXXX..XXXXXXXXXXXXX.. ..X.X.......X.X..X.X.......X.X.. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Definisce i colori per ogni linea del playfield. pfcolors: 130 26 130 26 130 26 130 26 130 26 130 130 end rem Imposta i colori, la posizione iniziale del giocatore e attiva il suono di inizio. COLUPF=h : COLUP0=26 : scorecolor=14 player_x=77 : player_y=48 : h=130 if b{7} then AUDV0=8 : AUDV1=8 : AUDC0=4 : AUDC1=4 b{6}=0 drawscreen rem Definizione grafica del giocatore player0: %00111100 %01111110 %11111111 %11100000 %11111111 %01011110 %00111100 end rem Definizione grafica del nemico (Fantasma) player1: %01010100 %11111110 %11111110 %11111110 %11010110 %01111100 %00111000 end rem Posiziona il nemico e imposta il suo colore. ghost_x=77 : ghost_y=80 COLUP1 = $32 noise rem Gestisce la musica di inizio partita. if b{7} then a=a+1 if !b{7} then c=0 : goto main if a>16 then a=0 : c=c+1 if c=1 then AUDF0=4 : AUDF1=18 if c=2 then AUDF0=12 : AUDF1=14 if c=3 then AUDF0=4 : AUDF1=18 if c=4 then AUDF0=8 : AUDF1=14 if c=5 then k=0 : c=0 : goto anim goto beginning rem --- Ciclo di Gioco Principale --- main rem Disattiva il flag della sequenza di inizio. b{7}=0 rem Esegui la logica del fantasma gosub update_ghost_ai rem Imposta il volume del suono (k è il contatore del suono "waka-waka"). AUDV0=k : AUDV1=0 rem Controlla la collisione con le palline del playfield. if collision(player0,playfield) && g<50 then k=9 : b{5}=1 : score=score+1 : g=g+1 : pfpixel e f off if !collision(player0,playfield) && b{5} then b{5}=1 rem Gestisce il suono "waka-waka" quando si mangia. if b{5} then k=k-1 : AUDC0=9 : AUDF0=9 if b{5} && k<1 then k=0 : b{5}=0 rem Controlla se tutte le palline sono state mangiate (g=70). if collision(player0,playfield) && g=50 then g=0 : b{5}=0 : k=0 : b{4}=1 : c=0 : a=0 : b{3}=0 : AUDV0=0 if b{4} then j=j+1 rem Gestisce l'animazione e il suono della morte del giocatore. if b{6} then AUDV0=k : AUDF0=m : AUDC0=4 : n=n+1 if n=4 then k=k-1 : n=0 : o=o+1 : p=p+1 if n=3 then m=m-1 if o>5 then k=0 if o>6 then o=0 : k=15 if b{6} && m=2 then o=0 : p=0 : k=0 if b{6} && m=2 then b{6}=0 : n=0 : c=0 : q{0}=1 rem --- Logica di Movimento su Griglia (Giocatore) --- b{0}=0 : b{1}=0 if player_x=17 then b{1}=1 if player_x=77 then b{1}=1 if player_x=137 then b{1}=1 if player_y=16 then b{0}=1 if player_y=32 then b{0}=1 if player_y=48 then b{0}=1 if player_y=64 then b{0}=1 if player_y=80 then b{0}=1 rem Imposta i colori volatili. COLUP0=26 : scorecolor=14 COLUP1 = $32 drawscreen rem Se il flag q{0} è attivo, entra in pausa dopo la morte. if q{0} then goto pause rem Se il flag b{6} è attivo, continua l'animazione di morte. if b{6} then goto anim_death rem Gestisce l'animazione di movimento del giocatore. if !b{4} then a=a+1 if a>20 then a=0 rem Gestisce la sequenza di fine livello. if b{4} && j=20 then j=0 : i=i+1 if b{4} && i=5 then i=0 : b{4}=0 : AUDV0=0 : goto beginning if b{4} then goto main rem --- Gestione Collisione Giocatore-Fantasma --- if collision(player0,player1) && !b{6} && !b{5} then k=15 : m=31 : b{6}=1 : c=0 rem --- Gestione Input Giocatore --- if joy0left && b{0} then player_dir=1 if joy0right && b{0} then player_dir=2 if joy0up && b{1} then player_dir=3 if joy0down && b{1} then player_dir=4 rem salta un frame se il giocatore ha mangiato una pallina if k = 8 then goto chomp_delay rem Muove il giocatore nella direzione `c` memorizzata. if b{2} then b{2}=0 else b{2}=1 if b{2} && player_dir=1 && player_x>17 then player_x=player_x-1 : b{3}=1 if b{2} && player_dir=2 && player_x<137 then player_x=player_x+1 : b{3}=0 if b{2} && player_dir=3 && player_y>16 then player_y=player_y-1 if b{2} && player_dir=4 && player_y<80 then player_y=player_y+1 chomp_delay rem Specchia lo sprite (REFP0) in base alla direzione orizzontale. if b{3} then REFP0=8 else REFP0=0 rem Calcola la coordinata del playfield sotto il giocatore per cancellare le palline. if b{3} then e=(player_x-17)/4 if !b{3} then e=(player_x-10)/4 f=(player_y-1)/8 goto anim pause rem Pausa dopo la morte, prima di ricominciare. r=r+1 : player_x=77 : player_y=48 if r>60 then r=0 : b{7}=1 : q{0}=0 : AUDF0=4 : AUDF1=18 : a=0 : c=1 : score = 0 : goto beginning goto anim rem ========= SUBROUTINE IA FANTASMA ========= update_ghost_ai rem Non muovere il fantasma se il giocatore è morto if b{6} || q{0} then return rem Non muovere il fantasma durante lo schema di fine livello if b{4} then return rem --- Logica di Movimento su Griglia per il Fantasma --- ghost_can_h=0 : ghost_can_v=0 if ghost_x=17 then ghost_can_v=1 if ghost_x=77 then ghost_can_v=1 if ghost_x=137 then ghost_can_v=1 if ghost_y=16 then ghost_can_h=1 if ghost_y=32 then ghost_can_h=1 if ghost_y=48 then ghost_can_h=1 if ghost_y=64 then ghost_can_h=1 if ghost_y=80 then ghost_can_h=1 rem --- Logica Decisionale del Fantasma --- rem Se il fantasma è a un incrocio (può cambiare direzione) if ghost_can_h || ghost_can_v then goto update_ghost_ai2 goto update_ghost_ai3 update_ghost_ai2 rem Logica di Inseguimento: scegli la direzione migliore rem Priorità al movimento orizzontale se è la distanza maggiore if player_x > ghost_x then tmp1 = player_x - ghost_x if player_x <= ghost_x then tmp1 = ghost_x - player_x if player_y > ghost_y then tmp2 = player_y - ghost_y if player_y <= ghost_y then tmp2 = ghost_y - player_y if tmp1 > tmp2 then goto update_ghost_ai2c rem Altrimenti, priorità al movimento verticale if ghost_y < player_y && ghost_can_v && ghost_dir <> 1 then ghost_dir = 2 if ghost_y > player_y && ghost_can_v && ghost_dir <> 2 then ghost_dir = 1 if ghost_x < player_x && ghost_can_h && ghost_dir <> 3 then ghost_dir = 4 if ghost_x > player_x && ghost_can_h && ghost_dir <> 4 then ghost_dir = 3 goto update_ghost_ai3 update_ghost_ai2c if ghost_x < player_x && ghost_can_h && ghost_dir <> 3 then ghost_dir = 4 if ghost_x > player_x && ghost_can_h && ghost_dir <> 4 then ghost_dir = 3 if ghost_y < player_y && ghost_can_v && ghost_dir <> 1 then ghost_dir = 2 if ghost_y > player_y && ghost_can_v && ghost_dir <> 2 then ghost_dir = 1 update_ghost_ai3 framecounter = framecounter + 1 rem Muovi il fantasma solo ogni due frame if framecounter{0} then return rem --- Muove il Fantasma nella sua direzione corrente --- if ghost_dir = 1 && ghost_can_v then ghost_y = ghost_y - 1 if ghost_dir = 2 && ghost_can_v then ghost_y = ghost_y + 1 if ghost_dir = 3 && ghost_can_h then ghost_x = ghost_x - 1 if ghost_dir = 4 && ghost_can_h then ghost_x = ghost_x + 1 return rem --- Centralino Animazioni --- anim rem Seleziona il set di animazioni corretto in base alla direzione di movimento. if c<3 then goto anim_lr if c=3 then goto anim_up if c=4 then goto anim_dn anim_lr rem Animazione per il movimento orizzontale (bocca che si apre e chiude). if a<5 then goto frame_1 if a>4 && a<10 then goto frame_2 if a>9 && a<15 then goto frame_3 if a>14 then goto frame_2 anim_up rem Animazione per il movimento verso l'alto. if a<5 then goto frame_1_up if a>4 && a<10 then goto frame_2_up if a>9 && a<15 then goto frame_3_up if a>14 then goto frame_2_up anim_dn rem Animazione per il movimento verso il basso. if a<5 then goto frame_1_down if a>4 && a<10 then goto frame_2_down if a>9 && a<15 then goto frame_3_down if a>14 then goto frame_2_down anim_death rem Seleziona il frame per l'animazione di morte. if p<4 then goto death_frame_1 if p>3 && p<8 then goto death_frame_2 if p>7 && p<12 then goto death_frame_3 if p>11 && p<16 then goto death_frame_4 if p>15 && p<20 then goto death_frame_5 if p>19 && p<24 then goto death_frame_6 if p>23 then goto death_frame_7 rem --- Subroutine Grafiche: Animazione di Morte --- death_frame_1 player0: %0011100 %0111110 %1100011 %1100011 %1100011 %0110110 %0010100 end goto main death_frame_2 player0: %0011100 %0011100 %0110110 %0110110 %1110111 %1110111 %1100011 end goto main death_frame_3 player0: %0011100 %0110110 %1110111 %1100011 %0000000 %0000000 %0000000 end goto main death_frame_4 player0: %1111111 %0111110 %0000000 %0000000 %0000000 %0000000 %0000000 end goto main death_frame_5 player0: %0000000 %0000000 %0010100 %0001000 %0010100 %0000000 %0000000 end goto main death_frame_6 player0: %1000001 %0100010 %0010100 %0000000 %0010100 %0100010 %1000001 end goto main death_frame_7 player0: %0010100 %0000000 %0100010 %0000000 %0100010 %0000000 %0010100 end goto main rem --- Subroutine Grafiche: Animazione Movimento --- frame_1_down player0: %0110110 %1110111 %1110111 %1110111 %1111111 %0111010 %0011100 end goto main frame_2_down player0: %0100010 %1100011 %1110111 %1110111 %1111111 %0111010 %0011100 end goto main frame_3_down player0: %0100010 %1100011 %1100011 %1110111 %1111111 %0111010 %0011100 end goto main frame_1_up player0: %0011100 %0111010 %1111111 %1110111 %1110111 %1110111 %0110110 end goto main frame_2_up player0: %0011100 %0111010 %1111111 %1110111 %1110111 %1100011 %0100010 end goto main frame_3_up player0: %0011100 %0111010 %1111111 %1110111 %1100011 %1100011 %0100010 end goto main frame_1 player0: %00111100 %01111110 %11111111 %11100000 %11111111 %01011110 %00111100 end goto main frame_2 player0: %00111100 %01111110 %11111100 %11100000 %11111100 %01011110 %00111100 end goto main frame_3 player0: %00111100 %01111100 %11110000 %11100000 %11110000 %01011100 %00111100 end goto main   -------------------------------------------------------------------------- Highway Racer -------------------------------------------------------------------------- rem ****************************************************************** rem * Highway Racer (Corse in Autostrada) * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Un gioco di corse con visuale dall'alto e scrolling verticale. * rem * Il giocatore controlla un'auto (player0) e deve evitare le * rem * auto nemiche (player1) e i posti di blocco (ball) che * rem * appaiono sulla strada. Il giocatore può sparare (missile0) per * rem * distruggere le auto nemiche e ottenere punti. Anche le auto * rem * nemiche possono sparare (missile1). La velocità aumenta * rem * progressivamente. Il gioco termina quando i "danni" subiti, * rem * rappresentati da un contatore, raggiungono una soglia. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - Aritmetica a Virgola Fissa (Fixed-Point Math): Il gioco * rem * include `fixed_point_math.asm` per utilizzare variabili 8.8. * rem * `scroll` (per lo scrolling della strada e nemici) e `mis` * rem * (per il proiettile nemico) usano questa tecnica per ottenere * rem * un movimento e un'accelerazione fluidi e graduali. * rem * - Scrolling Verticale del Playfield: Il comando `pfscroll down`* rem * viene usato per creare l'illusione del movimento continuo * rem * della strada. * rem * - IA con Comportamento Casuale: Le auto nemiche non si * rem * limitano a scorrere, ma possono muoversi lateralmente e * rem * "sbandare" in modo casuale grazie all'uso del comando `rand`.* rem * Anche i posti di blocco appaiono in posizioni casuali. * rem * - Gestione Dinamica degli Sprite: Le auto nemiche cambiano * rem * aspetto (`CarCreate`) e colore in base al livello di * rem * difficoltà. L'auto del giocatore cambia forma quando sterza. * rem * - Sistema di "Punti Vita"/Danno: Invece di vite discrete, il * rem * gioco usa un contatore di danni (`c`). Ogni collisione * rem * incrementa il contatore. Al raggiungimento di una soglia, * rem * si attiva la sequenza di Game Over. * rem * - Oggetti Multipli e Power-up: Il gioco gestisce 4 oggetti * rem * mobili contemporaneamente: l'auto del giocatore (player0), * rem * l'auto nemica (player1), il proiettile del giocatore * rem * (missile0) e il proiettile nemico (missile1). C'è anche una * rem * meccanica di power-up (invincibilità temporanea). * rem ****************************************************************** set romsize 4k init rem Include la libreria per la matematica a virgola fissa (8.8). include fixed_point_math.asm rem --- Sezione Definizioni Variabili (Alias) --- rem 'scroll' (m.n) è la variabile 8.8 per la posizione Y dell'auto nemica. dim scroll=m.n m=0 : n=0 scroll=1.0 rem 'mis' (k.j) è la variabile 8.8 per la posizione Y del missile nemico. dim mis=k.j j=0 : k=0 mis=1.0 rem --- Mappa delle Variabili (Commenti originali mantenuti) --- rem a: Posizione X dell'auto nemica per calcoli rem b: Posizione X del posto di blocco (ball) rem c: Contatore dei danni subiti dal giocatore rem d: Flag per il movimento laterale dell'auto nemica (0=dritto, 1=dx, 2=sx) rem f: Contatore generico rem h: Flag per power-up attivo rem i: Flag per la schermata titolo rem o: Contatore generico rem p: Posizione Y del giocatore rem q: Timer per il proiettile del giocatore rem r: Timer per la pausa (es. game over) rem t: Contatore di scrolling (aumenta la difficoltà) rem u: Posizione X dell'auto nemica rem w: Flag per il colore (power-up) rem x: Posizione X del giocatore rem y: Contatore per il ciclo dei colori rem z: Flag per nemico colpito a=0 : b=82 : c=0 : d=0 : f=0 : h=0 : i=0 : o=0 p=85 : q=0 : r=0 : t=0 : u=94 : W=0 : x=75 : y=16 : z=0 rem --- Impostazioni Iniziali Oggetti e Colori --- missile0x=0:missile0y=0 missile1x=0:missile1y=0 COLUP0=0 COLUP1=208 COLUPF=160 COLUBK=0 CTRLPF=$35 scorecolor=246 AUDV0=0 AUDV1=0 rem --- Stato 0: Schermata Titolo --- intro rem Fa scorrere lo sfondo per un effetto dinamico. g=g+1 if g=2 then pfscroll down :g=0 rem Cicla i colori per un effetto "attract mode". y=y+1 if y<17 then y=16 if y>29 then y=16 rem Disegna i bordi della strada per la schermata titolo. pfpixel 7 1 on : pfpixel 25 1 on pfpixel 7 2 on : pfpixel 25 2 on pfpixel 7 3 on : pfpixel 25 3 on pfpixel 7 4 on : pfpixel 25 4 on pfpixel 7 5 on : pfpixel 25 5 on pfpixel 7 6 on : pfpixel 25 6 on pfpixel 7 7 on : pfpixel 25 7 on pfpixel 7 8 on : pfpixel 25 8 on pfpixel 7 9 on : pfpixel 25 9 on drawscreen rem Attende l'input del giocatore o il reset per iniziare il gioco. if joy0down then i=1 : score=0 : g=0:i=0:goto intro2 if switchreset then i=1 : score=0 : g=0:i=0:goto intro2 if joy0fire then i=1: score=0 : g=0:i=0:goto intro2 goto intro rem --- Inizializzazione della Partita --- intro2 rem Posiziona le auto per l'inizio. player1x=68:player1y=82 player0x=88:player0y=83 rem Genera la prima auto nemica. gosub MakeNewCar1 rem Azzera i contatori di gioco. g=0 e=0 missile0x=0:missile0y=0 rem --- Ciclo di Gioco Principale --- main y=y+1 if y>250 then y=1 if c<1 then c=1 rem Attiva il suono del motore del giocatore se non sta accelerando/frenando. if joy0up then goto audskip if joy0down then goto audskip AUDF0=18:AUDC0=14:AUDV0=10 rem Aumenta la difficoltà massima dopo un certo tempo. if t>240 then t=31 audskip rem Resetta i flag quando l'auto nemica esce dallo schermo. if scroll > 90 then o=0 if scroll > 96 then w=0 : h=0 if scroll > 96 then u=94 rem --- Logica dello Scrolling Verticale (Virgola Fissa) --- rem 'scroll' è la posizione Y dell'auto nemica. e=e+1 if e=2 && t < 10 then e=0:goto skipscroll rem Incrementa la posizione verticale. Se esce dallo schermo, la resetta e aumenta la difficoltà ('t'). if scroll < 97 then scroll=scroll+1.0 else scroll=0.0 : t=t+1 rem Aumenta la velocità di scrolling ai livelli più alti. if scroll < 97 && t > 35 then scroll=scroll+0.9 : mis=mis+0.9 skipscroll rem Controlla se è necessario creare una nuova auto nemica. gosub CarCreate rem --- Logica IA e Generazione Ostacoli --- v=rand rem Ai livelli più alti, l'auto nemica può "sbandare" casualmente. if t > 30 then skipmv if t < 8 then goto skipmv if t > 20 && v < 35 then u=u+1 skipmv rem Genera casualmente un posto di blocco (ball) in una delle 8 posizioni. if v=2 && scroll > 86 then b = 75 if v=234 && scroll > 86 then b = 105 if v=112 && scroll > 86 then b = 89 if v=50 && scroll > 86 then b = 81 if v=188 && scroll > 86 then b = 115 if v=166 && scroll > 86 then b = 79 if v=132 && scroll > 86 then b = 95 if v=176 && scroll > 86 then b = 111 rem Fa muovere l'auto nemica lateralmente in modo casuale. if v < 10 then u=u+1 if v > 245 then u=u-2 rem Cambia il colore dell'auto nemica in base al livello di difficoltà. if t>20 && t<36 then COLUP1=104 if t>35 then COLUP1=68 rem Se l'auto nemica ha colpito un bordo, la fa muovere nella direzione opposta. if d=1 then u=u+1 if d=2 then u=u-1 skiplr rem Se un'auto nemica colpita da un missile esce dallo schermo, resetta il flag 'z'. if scroll > 96 then z=0 rem Se il flag 'z' è 0, l'auto nemica è visibile (NUSIZ1=1). if z=0 then NUSIZ1=$01 rem Aggiorna la posizione dell'auto nemica usando la variabile a virgola fissa. player1y=scroll : player1x=u skiplrm rem Seleziona lo sprite del giocatore in base alla sterzata. if joy0left then goto TurnCar1 if joy0right then goto TurnCar2 player0: %01111110 %01000010 %00111100 %10100101 %11100111 %10111101 %00111100 %10011001 %11111111 %10011001 end turned rem --- Gestione Grafica e Scrolling --- rem Fa scorrere la strada. if joy0down then skipscrl pfscroll down skipscrl g=g+1 if g=2 then pfscroll down:g=0 skipsc rem Imposta il colore del giocatore, che cambia in base ai danni subiti ('c'). if c < 11 then COLUP0=128 if c > 10 && c < 21 then COLUP0=60 if c > 20 && c < 31 then COLUP0=30 if c > 30 && c < 41 then COLUP0=64 if c > 40 && c < 61 then COLUP0=y player0x=x : player0y=p rem Disegna i bordi della strada usando pfpixel. pfpixel 7 1 on : pfpixel 25 1 on pfpixel 7 3 on : pfpixel 25 3 on pfpixel 7 5 on : pfpixel 25 5 on pfpixel 7 7 on : pfpixel 25 7 on pfpixel 7 9 on : pfpixel 25 9 on drawscreen rem Posiziona il posto di blocco (ball). ballx=b : bally=scroll+15 : ballheight=2 rem --- Gestione Input Giocatore (Movimento) --- if joy0left then x=x-1 if joy0right then x=x+1 rem Accelerare e frenare modifica la velocità di scrolling e il punteggio. if joy0up then scroll=scroll+0.3 : mis=mis+0.5 : score=score+10 : AUDF0=12:AUDC0=14:AUDV0=10 if joy0down && scroll >=1 then scroll=scroll-0.3 : mis=mis-0.5 : score=score-10: AUDF0=24:AUDC0=14:AUDV0=10 rem --- Logica dei Proiettili --- rem Gestisce il proiettile del giocatore. if joy0fire && q<1 then AUDF1=8:AUDC1=1:AUDV1=15 : goto playerfires if q>0 then q=q-2 : missile0y=q if q>50 then AUDV1=0 rem Gestisce il proiettile dell'auto nemica. if scroll >35 && t<10 then goto fireskip if scroll >50 && t<36 then goto fireskip if scroll >60 && t>35 then goto fireskip if h=1 then goto fireskip if scroll<=1 then mis=1.0 : AUDF1=13:AUDC1=1:AUDV1=9 if mis > 18 then AUDV1=0 missile1y=mis : missile1x=u : missile1height=6 mis=mis+2.0 goto pskip fireskip missile1y=0: missile1x=0 pskip rem --- Logica delle Collisioni --- rem Collisione giocatore-bordo strada. if collision(playfield,player0) && x > 75 then x=x-2 if collision(playfield,player0) && x < 75 then x=x+2 rem Collisione nemico-bordo strada (cambia la sua direzione). if collision(player1,playfield) && u > 100 then d=2 if collision(player1,playfield) && u < 80 then d=1 rem Rallenta il giocatore se tocca il bordo. if collision(player0,playfield) && scroll >=1 then scroll=scroll-0.5 : mis=mis-0.5 rem Collisione giocatore-nemico: aumenta i danni. Se troppi, game over. if collision(player1,player0) && w=1 then gosub addhitpoints if w=1 then goto damageskip if collision(player1,player0) then c=c+1 : if c=60 then r=120: goto thisisit if collision(player1,player0) && scroll >=1 then scroll=scroll-1.5 : mis=mis-1.5 rem Collisione missile del giocatore-nemico. if collision(player1,missile0) then missile0y=1 : goto carhit rem Collisione missile nemico-giocatore. if collision(player0,missile1) && x > 75 then c=c+1 : x=x-2 : if c=60 then r=160: goto thisisit if collision(player0,missile1) && x < 75 then c=c+1 : x=x+2 : if c=60 then r=160: goto thisisit damageskip rem Collisione giocatore-posto di blocco. if collision(player0,ball) && u > 90 then x=x-6 if collision(player0,ball) && u < 90 then x=x+6 rem Aumenta il punteggio per il tempo sopravvissuto. score=score+20 goto main rem --- Sezione delle Subroutine --- playerfires rem Crea il proiettile del giocatore. if !switchleftb then missile0x=x+10 else missile0x=x+4 q=80 : missile0y=75 missile0height=6 goto main thisisit rem Prepara la schermata di Game Over. AUDV0=0 goto eog carhit rem Gestisce l'evento di un'auto nemica colpita. a=u z=1 : score = score + 1000 : missile0y=0 : q=0 a=u+8 if o<1 then goto skipblank if o>0 then goto blankcar skipblank rem Fa scomparire l'auto nemica e può generare un power-up. if missile0x < a then NUSIZ1=0 : o=o+1 : u=u+16 if missile0x > a then NUSIZ1=0 : o=o+1 199 l=rand:if l>215 then 199 l=l/8:l=l+1 if joy0up then goto main if l < 10 && scroll > 1 then gosub powerup : w=1 goto main eog rem Sequenza di animazione e suono per il Game Over. if r<1 then r=88:goto eog2 r=r-1 gosub explode COLUPF=r AUDF0=160-r:AUDC0=1:AUDV0=6 drawscreen goto eog eog2 rem Loop finale che attende il riavvio del gioco. COLUP0=68 AUDV0=0 r=r-1 e=e+1 if e=2 then pfscroll up:e=0 player0y=r player1y=0 missile0y=0 missile1y=0 COLUPF=160 drawscreen if r<1 then pfclear:goto init ballx=0:bally=0 scroll=0 t=0 goto eog2 CarCreate rem Seleziona casualmente uno dei 5 modelli di auto nemiche da creare. if scroll<96 then return 200 l=rand:if l>215 then 200 l=l/8:l=l+1 if l>1 && l<6 then gosub MakeNewCar1 : return if l>5 && l<11 then gosub MakeNewCar2 : return if l>10 && l<16 then gosub MakeNewCar3 : return if l>15 && l<21 then gosub MakeNewCar4 : return if l>20 && l<28 then gosub MakeNewCar5 : return return rem --- Subroutine Grafiche --- MakeNewCar1 player1: %10011001 %11111111 %10011001 %00011000 %10111101 %11111111 %10011001 %00111100 end return MakeNewCar2 player1: %10111101 %11111111 %10111101 %00100100 %11100111 %10111101 %01000010 %01111110 end return MakeNewCar3 player1: %10011001 %11111111 %10011001 %00011000 %11011011 %11111111 %11011011 %00100100 end return MakeNewCar4 player1: %10011001 %11111111 %10011001 %00011000 %00011000 %10011001 %11111111 %10011001 end return MakeNewCar5 player1: %10011001 %11111111 %10011001 %00111100 %10100101 %11111111 %10011001 %00100100 end return TurnCar1 rem Sprite del giocatore che sterza a sinistra. player0: %01111110 %01000010 %00111100 %10100101 %11100111 %10111101 %00111100 %01011001 %11111111 %10011010 end goto turned TurnCar2 rem Sprite del giocatore che sterza a destra. player0: %01111110 %01000010 %00111100 %10100101 %11100111 %10111101 %00111100 %10011010 %11111111 %01011001 end goto turned powerup rem Attiva il power-up e cambia lo sprite nemico in quello del power-up. h=1 missile0y=0: q=0 player1: %11111111 %10000001 %10011001 %10011001 %10111101 %10111101 %10011001 %10011001 %10000001 %11111111 end return addhitpoints rem Se il power-up è attivo, il giocatore non subisce danni. if h=1 then c=c-1 return blankcar rem Fa scomparire l'auto nemica dopo essere stata colpita. u=94 player1: %00000000 end goto main explode rem Sprite per l'animazione di esplosione del giocatore. COLUPF=70 COLUP0=64 player0: %01111110 %01000010 %00111100 %10100101 %11110111 %00111000 %10001100 %10011001 %01101110 %00000000 end return player0: %10000001 %00100100 %00000000 %00011001 %10011000 %00000000 %00100100 %10000001 End -------------------------------------------------------------------------- Disc Dog -------------------------------------------------------------------------- rem ****************************************************************** rem * Disc Dog * rem * * rem * DESCRIZIONE DEL GIOCO: * rem * Un gioco ispirato allo sport del "disc dog". Il giocatore * rem * controlla un cane (player0) che deve prendere al volo un frisbee* rem * (player1) prima che cada a terra. Il gioco è a tempo e si * rem * perdono vite se il frisbee non viene preso. * rem * * rem * TECNICHE DI PROGRAMMAZIONE UTILIZZATE: * rem * - IA dell'Oggetto: Il frisbee segue una traiettoria complessa * rem * e la sua velocità cambia casualmente. * rem * - Animazione Dinamica: Lo sprite del cane cambia in base alla * rem * direzione del movimento. * rem * - Manipolazione del Playfield: Vite e timer sono disegnati * rem * manualmente sullo sfondo con `pfpixel`. * rem * - Gestione degli Stati: Il codice usa variabili per tracciare * rem * lo stato del cane (salto, corsa) e del disco (preso, in volo).* rem ****************************************************************** rem Etichetta di inizio gioco, usata per il riavvio completo. begin rem --- Definizioni Grafiche Iniziali --- rem Disegna 3 blocchi per le 3 vite iniziali rem Marcatori di bordo per il campo rem Linea di terra playfield: ................................ .X.X.X.......................... ................................ ................................ ................................ ................................ ................................ ................................ ................................ ...............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem Grafica iniziale del cane (fermo) player0: %01000100 %01000100 %01111100 %01111100 %01111100 %10000111 %00000111 %00000100 end rem Grafica del frisbee player1: %01111110 %00011000 end rem --- Impostazioni Iniziali dei Registri --- rem Colore del playfield (es. l'erba) COLUPF = 176 rem Colore del punteggio (non usato ma impostato) scorecolor = 52 score = 0 rem Posizione iniziale del cane player0x = 21 player0y = 80 rem Posizione iniziale del frisbee player1x = 138 player1y = 65 rem Posizione iniziale dell'ombra del cane missile0x = 82 missile0y = 79 missile0height = 5 rem --- Alias delle Variabili (mappatura su a-z) --- rem Stato del salto del cane (0=a terra, 1=sale, 2=scende) dim perrosalto = a rem Direzione del frisbee (1=da dx a sx, 2=da sx a dx) dim discodireccion = b rem Stato del frisbee (1=in volo, 2=preso dal cane) dim discocogido = c rem Punteggio (non usato, ma c'è la variabile) dim puntos = d rem Direzione in cui è rivolto il cane (1=dx, 2=sx) dim perrodireccion = e rem Velocità orizzontale del frisbee dim discovelocidad = f rem Variabile temporanea per valori casuali dim aleatorio = g rem Altezza massima dell'arco del frisbee dim discoaltura = h rem Contatore delle vite del cane dim perrovidas = i rem Timer di gioco (conto alla rovescia disegnato su schermo) dim cuentaatras = j rem Coordinata X in cui il frisbee inizia a scendere dim discoalturasube = k rem Coordinata X in cui il frisbee inizia a salire dim discoalturabaja = l rem Timer per rallentare il movimento verticale del frisbee dim discoalturapaso = m rem --- Inizializzazione delle Variabili di Gioco --- puntos = 0 discocogido = 1 discodireccion = 1 perrodireccion = 1 discovelocidad = 2 perrovidas = 3 cuentaatras = 0 rem Calcola un'altezza casuale per il lancio discoaltura = (rand & 10) + 1 discoalturasube = 18 + discoaltura discoalturabaja = 138 - discoaltura discoalturapaso = 4 rem Ciclo di gioco principale. mainloop rem Silenzia il canale audio 0 all'inizio di ogni frame. AUDV0 = 0 rem Colore del cane (player0) COLUP0 = 4 rem Colore del frisbee (player1) COLUP1 = 132 rem --- Logica di Game Over --- rem Se le vite sono finite, cambia colore e pulisce lo schermo. if perrovidas = 0 then COLUPF = 52 : gosub limpiarpantalla rem Disegna la scritta "GAME" if perrovidas = 0 then gosub game rem Disegna la scritta "OVER" if perrovidas = 0 then gosub over rem Se il gioco è finito e si preme fuoco, riavvia tutto. if perrovidas = 0 && joy0fire then goto begin rem --- Lettura Input Giocatore --- if joy0left && player0x > 21 && perrovidas > 0 then gosub moverizquierda if joy0right && player0x < 133 && perrovidas > 0 then gosub moverderecha rem Inizia la sequenza di salto if joy0up && perrosalto = 0 && perrovidas > 0 then perrosalto = 1 rem --- Aggiornamento Timer Visivo ( disegna una barra che si riempie ) --- if cuentaatras = 25 then pfpixel 21 1 on : missile0height = 6 if cuentaatras = 50 then pfpixel 22 1 on if cuentaatras = 75 then pfpixel 23 1 on : missile0height = 7 if cuentaatras = 100 then pfpixel 24 1 on if cuentaatras = 125 then pfpixel 25 1 on : missile0height = 8 if cuentaatras = 150 then pfpixel 26 1 on if cuentaatras = 175 then pfpixel 27 1 on : missile0height = 9 if cuentaatras = 200 then pfpixel 28 1 on if cuentaatras = 225 then pfpixel 29 1 on : missile0height = 10 if cuentaatras = 250 then pfpixel 30 1 on rem Se il timer arriva alla fine, il gioco termina. if cuentaatras = 250 then perrovidas = 0 rem --- Logica di Stato del Frisbee --- rem Se il cane ha il disco, lo tiene; altrimenti, muovi il disco. if discocogido = 2 then gosub cogerdisco else gosub moverdisco rem --- Logica del Salto del Cane --- rem Se sta saltando (fase di salita) if perrosalto = 1 then gosub saltarsubida rem Se sta saltando (fase di discesa) if perrosalto = 2 then gosub saltarbajada rem --- Controllo Collisioni --- rem Se il cane tocca il frisbee, lo prende. if collision(player0,player1) then discocogido = 2 rem Se il cane con il frisbee raggiunge uno dei bordi, lancia di nuovo. if player0x = 21 && collision(playfield,player1) && discocogido = 2 then gosub lanzardisco2 if player0x = 133 && collision(playfield,player1) && discocogido = 2 then gosub lanzardisco1 rem Se il cane tocca la sua ombra (missile0), perde una vita (è una meccanica di gioco per aggiungere difficoltà). if collision(player0,missile0) then AUDV0 = 15 : AUDC0 = 6 : AUDF0 = 4 : player0x = 21 : perrovidas = perrovidas - 1 rem --- Aggiornamento Vite Visive --- rem Spegne un blocco-vita se ne rimangono 2. if perrovidas = 2 then pfpixel 5 1 off rem Spegne un altro blocco-vita se ne rimane 1. if perrovidas = 1 then pfpixel 3 1 off rem Spegne l'ultimo blocco-vita. if perrovidas = 0 then pfpixel 1 1 off drawscreen goto mainloop rem Subroutine per lanciare il frisbee da destra verso sinistra. lanzardisco1 rem Pulisce vecchi pixel del playfield pfpixel 31 9 off pfpixel 0 9 on rem Suono di lancio AUDV0 = 5 : AUDC0 = 12 : AUDF0 = 4 rem Imposta lo stato del disco a "in volo". discocogido = 1 player1y = 65 player1x = 18 rem Imposta la direzione del disco. discodireccion = 2 rem Calcola una velocità casuale. aleatorio = (rand & 3) + 1 if aleatorio = 4 then discovelocidad = 4 if aleatorio = 3 then discovelocidad = 2 if aleatorio = 2 then discovelocidad = 1 if aleatorio = 1 then discovelocidad = 1 score = score + 100 puntos = puntos + 100 cuentaatras = cuentaatras + 1 rem Calcola una nuova traiettoria casuale. discoaltura = (rand & 10) + 1 discoalturasube = 138 - (discoaltura * 4) discoalturabaja = 18 + (discoaltura * 4) discoalturapaso = 4 return rem Subroutine per lanciare il frisbee da sinistra verso destra. lanzardisco2 rem Pulisce vecchi pixel del playfield pfpixel 31 9 on pfpixel 0 9 off rem Suono di lancio AUDV0 = 5 : AUDC0 = 12 : AUDF0 = 4 discocogido = 1 player1y = 65 player1x = 138 discodireccion = 1 rem Calcola una velocità casuale. aleatorio = (rand & 3) + 1 if aleatorio = 4 then discovelocidad = 4 if aleatorio = 3 then discovelocidad = 2 if aleatorio = 2 then discovelocidad = 1 if aleatorio = 1 then discovelocidad = 1 score = score + 100 puntos = puntos + 100 cuentaatras = cuentaatras + 1 rem Calcola una nuova traiettoria casuale. discoaltura = (rand & 10) + 1 discoalturabaja = 18 + (discoaltura * 4) discoalturasube = 138 - (discoaltura * 4) discoalturapaso = 4 return rem Cambia la grafica del cane per il movimento a sinistra. moverizquierda player0: %00100010 %00100010 %00111110 %00111110 %00111111 %11100000 %11100000 %00100000 end rem Imposta la direzione del cane. perrodireccion = 2 rem Muove il cane. player0x = player0x - 1 return rem Cambia la grafica del cane per il movimento a destra. moverderecha player0: %01000100 %01000100 %01111100 %01111100 %01111100 %10000111 %00000111 %00000100 end player0x = player0x + 1 perrodireccion = 1 return rem Fase di salita del salto. saltarsubida player0y = player0y - 1 rem Se raggiunge l'apice, passa alla fase di discesa. if player0y = 62 then perrosalto = 2 rem Meccanica di penalità if puntos >= 10 && perrosalto = 2 then score = score - 10 : puntos = puntos - 10 return rem Fase di discesa del salto. saltarbajada player0y = player0y + 1 rem Se tocca terra, fine del salto. if player0y = 80 then perrosalto = 0 return rem Logica di movimento del frisbee in volo. moverdisco rem Rallenta il movimento verticale if discoalturapaso > 1 then discoalturapaso = discoalturapaso - 1 rem --- Simulazione della traiettoria parabolica del frisbee --- if discoalturapaso = 1 && player1x <= discoalturabaja && discovelocidad = 1 && discodireccion = 1 then player1y = player1y + 1 : discoalturapaso = 4 if discoalturapaso = 1 && player1x >= discoalturasube && discovelocidad = 1 && discodireccion = 1 then player1y = player1y - 1 : discoalturapaso = 4 if discoalturapaso = 1 && player1x >= discoalturasube && discovelocidad = 1 && discodireccion = 2 then player1y = player1y + 1 : discoalturapaso = 4 if discoalturapaso = 1 && player1x <= discoalturabaja && discovelocidad = 1 && discodireccion = 2 then player1y = player1y - 1: discoalturapaso = 4 rem --- Movimento orizzontale e inversione ai bordi --- if player1x <= 138 && discodireccion = 1 then player1x = player1x - discovelocidad if player1x >= 18 && discodireccion = 2 then player1x = player1x + discovelocidad rem Se tocca il bordo, inverte e aggiorna il timer. if player1x <= 18 then discodireccion = 2 : cuentaatras = cuentaatras + 1 : player1y = 65 if player1x >= 138 then discodireccion = 1 : cuentaatras = cuentaatras + 1 : player1y = 65 AUDV0 = 0 return rem Logica per quando il cane ha preso il frisbee. cogerdisco rem Il frisbee segue il cane. if perrodireccion = 1 then player1x = player0x + 6 if perrodireccion = 2 then player1x = player0x - 6 player1y = player0y - 5 return rem Pulisce i pixel usati per l'HUD. limpiarpantalla pfpixel 5 1 off pfpixel 3 1 off pfpixel 1 1 off pfpixel 22 1 off pfpixel 23 1 off pfpixel 24 1 off pfpixel 25 1 off pfpixel 26 1 off pfpixel 27 1 off pfpixel 28 1 off pfpixel 29 1 off pfpixel 30 1 off pfpixel 31 1 off drawscreen return rem Disegna "GAME" sul playfield. game pfpixel 6 0 on pfpixel 7 0 on pfpixel 8 0 on pfpixel 11 0 on pfpixel 12 0 on pfpixel 13 0 on pfpixel 15 0 on pfpixel 19 0 on pfpixel 21 0 on pfpixel 22 0 on pfpixel 23 0 on pfpixel 24 0 on pfpixel 5 1 on pfpixel 10 1 on pfpixel 13 1 on pfpixel 15 1 on pfpixel 16 1 on pfpixel 18 1 on pfpixel 19 1 on pfpixel 21 1 on pfpixel 5 2 on pfpixel 7 2 on pfpixel 8 2 on pfpixel 10 2 on pfpixel 13 2 on pfpixel 15 2 on pfpixel 17 2 on pfpixel 19 2 on pfpixel 21 2 on pfpixel 22 2 on pfpixel 5 3 on pfpixel 8 3 on pfpixel 10 3 on pfpixel 11 3 on pfpixel 12 3 on pfpixel 13 3 on pfpixel 15 3 on pfpixel 19 3 on pfpixel 21 3 on pfpixel 6 4 on pfpixel 7 4 on pfpixel 10 4 on pfpixel 13 4 on pfpixel 15 4 on pfpixel 19 4 on pfpixel 21 4 on pfpixel 22 4 on pfpixel 23 4 on pfpixel 24 4 on drawscreen return rem Disegna "OVER" sul playfield. over pfpixel 6 6 on pfpixel 7 6 on pfpixel 10 6 on pfpixel 14 6 on pfpixel 16 6 on pfpixel 17 6 on pfpixel 18 6 on pfpixel 19 6 on pfpixel 21 6 on pfpixel 22 6 on pfpixel 23 6 on pfpixel 24 6 on pfpixel 5 7 on pfpixel 8 7 on pfpixel 10 7 on pfpixel 14 7 on pfpixel 16 7 on pfpixel 21 7 on pfpixel 24 7 on pfpixel 5 8 on pfpixel 8 8 on pfpixel 10 8 on pfpixel 14 8 on pfpixel 16 8 on pfpixel 17 8 on pfpixel 21 8 on pfpixel 22 8 on pfpixel 23 8 on pfpixel 5 9 on pfpixel 8 9 on pfpixel 11 9 on pfpixel 13 9 on pfpixel 16 9 on pfpixel 21 9 on pfpixel 23 9 on pfpixel 4 10 off pfpixel 5 10 off pfpixel 8 10 off pfpixel 9 10 off pfpixel 10 10 off pfpixel 11 10 off pfpixel 13 10 off pfpixel 14 10 off pfpixel 15 10 off pfpixel 20 10 off pfpixel 22 10 off pfpixel 23 10 off pfpixel 25 10 off drawscreen return