------------------------------------------------------- rem Il mio primo programma bB set romsize 2k main drawscreen goto main ------------------------------------------------------- rem Sfondo semplice set romsize 2k main COLUBK = $86 ; Imposta lo sfondo a un bel blu drawscreen goto main ------------------------------------------------------- rem Primo programma bB - Hello Player! set romsize 2k main player0: %11111111 %11111111 %11111111 %11111111 end COLUP0 = $1E ; colore del player0 (giallo) player0x = 80 ; posizione orizzontale player0y = 50 ; posizione verticale COLUBK = $86 ; colore di sfondo (blu) drawscreen goto main ------------------------------------------------------- rem Primo programma bB - Hello Player! set romsize 2k main player0: %11111111 %11111111 %11111111 %11111111 end if joy0left then player0x = player0x - 1 if joy0right then player0x = player0x + 1 COLUP0 = $1E ; colore del player0 (giallo) player0y = 50 ; posizione verticale (per ora fissa) COLUBK = $86 ; colore di sfondo (blu) drawscreen goto main ------------------------------------------------------- rem Sprite che si specchia, clamp ai bordi set romsize 2k rem 'a' memorizza lo stato di riflessione (0=normale, 8=specchiato) a = 0 rem posizione iniziale x del player0 player0x = 80 main rem --- Definizione Grafica --- player0: %01111100 %00111111 %01111100 end rem --- Logica di Movimento e Riflessione --- if joy0left && player0x > 8 then player0x = player0x - 1 : a = 0 if joy0right && player0x < 152 then player0x = player0x + 1 : a = 8 rem --- Inizializzazione Registri prima del disegno --- REFP0 = a ; Applica lo stato di riflessione memorizzato in 'a' COLUP0 = $1E ; colore del player0 (giallo brillante) player0y = 50 ; posizione verticale (per ora fissa) COLUBK = $86 ; colore di sfondo (blu ciano) rem --- Disegno --- drawscreen goto main ------------------------------------------------------- rem Il Mondo di Mattoni Digitali set romsize 2k a = 0 ; Variabile per la riflessione dello sprite rem --- Definizioni Grafiche --- player0: %01111100 %00111111 %01111100 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem --- Posizione iniziale del giocatore --- player0x = 80 player0y = 50 main rem --- Inizializzazione Registri per il frame --- COLUBK = $04 ; sfondo: Grigio scuro COLUPF = $B6 ; playfield: Verde giungla COLUP0 = $1E ; player: Giallo brillante REFP0 = a ; Applica lo stato di riflessione rem --- Logica di Gioco --- if joy0left && player0x > 18 then player0x = player0x - 1 : a = 8 if joy0right && player0x < 142 then player0x = player0x + 1 : a = 0 rem --- Disegno --- drawscreen goto main ------------------------------------------------------- rem Il Mondo di Mattoni Digitali - con collisioni! set romsize 2k a = 0 ; Variabile per la riflessione dello sprite rem --- Definizioni Grafiche --- player0: %01111100 %00111111 %01111100 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end rem --- Posizione iniziale del giocatore --- player0x = 80 player0y = 50 main rem 1. SALVA la posizione sicura x = player0x y = player0y rem --- Inizializzazione Registri --- COLUBK = $04 ; Grigio scuro COLUPF = $B6 ; Verde giungla COLUP0 = $1E ; Giallo brillante REFP0 = a ; Applica lo stato di riflessione rem 2. MUOVI il personaggio if joy0left && player0x > 18 then player0x = player0x - 1 : a = 8 if joy0right && player0x < 142 then player0x = player0x + 1 : a = 0 if joy0up && player0y > 10 then player0y = player0y - 1 if joy0down && player0y < 85 then player0y = player0y + 1 rem --- Disegno --- drawscreen rem 3. CONTROLLA e RIPRISTINA if collision(player0, playfield) then player0x = x : player0y = y goto main ------------------------------------------------------- rem Collisione con Suono set romsize 2k a = 0 ; Variabile per la riflessione s = 0 ; Variabile per il sound timer (s=sound) rem --- Definizioni Grafiche --- player0: %01111100 %00111111 %01111100 end playfield: XXXXXXXXXXXXXXXXXXXX X.....X............X X.....X............X X....XX.........X..X X...............X..X X............XXXX..X X..................X X...X..............X XXXXX.........XXXXXX X.............X..... XXXXXXXXXXXXXXX..... end rem --- Posizione iniziale player0 --- player0x = 80 player0y = 50 main rem 1. SALVA la posizione sicura x = player0x y = player0y rem --- Gestione del Sound Timer --- if s > 0 then s = s - 1 if s = 0 then AUDV0 = 0 ; Spegni il suono quando il timer scade rem --- Inizializzazione Registri --- COLUBK = $04 ; Grigio scuro COLUPF = $B6 ; Verde giungla COLUP0 = $1E ; Giallo brillante REFP0 = a ; Applica lo stato di riflessione rem 2. MUOVI il personaggio if joy0left && player0x > 18 then player0x = player0x - 1 : a = 8 if joy0right && player0x < 142 then player0x = player0x + 1 : a = 0 if joy0up && player0y > 10 then player0y = player0y - 1 if joy0down && player0y < 85 then player0y = player0y + 1 rem --- Disegno --- drawscreen rem 3. CONTROLLA, RIPRISTINA e SUONA if collision(player0, playfield) then player0x = x : player0y = y : gosub play_hit_sound goto main rem --- SUBROUTINE PER IL SUONO --- play_hit_sound s = 5 ; Durata del suono: 5 frame AUDV0 = 10 ; Volume AUDC0 = 2 ; Timbro "rombo" cupo AUDF0 = 30 ; Intonazione molto grave return ------------------------------------------------------- rem Animazione di Corsa set romsize 2k a = 0 ; Variabile per la riflessione f = 0 ; Variabile per il timer di animazione (f=frame) main_loop gosub handle_input gosub animate_player player0x = x player0y = y COLUP0 = $EA COLUBK = $84 REFP0 = a drawscreen goto main_loop rem --- SUBROUTINES DI GIOCO --- handle_input rem Posizioni iniziali se non definite if x = 0 then x = 80 : y = 50 if joy0left && x > 8 then x = x - 1 : a = 8 if joy0right && x < 152 then x = x + 1 : a = 0 return animate_player rem Se il giocatore si muove, incrementa il timer if joy0left || joy0right then f = f + 1 rem Se il giocatore è fermo, mostra il frame statico e azzera il timer if !joy0left && !joy0right then gosub anim_frame_static : f = 0 : return rem Logica di alternanza frame if f < 10 then gosub anim_frame_1 if f >= 10 then gosub anim_frame_2 if f >= 20 then f = 0 ; Azzera il timer per ricominciare il ciclo return rem --- DEFINIZIONI GRAFICHE --- anim_frame_static ; Frame per personaggio fermo player0: %0010100 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end return anim_frame_1 ; Corsa - Frame 1 player0: %0010100 %0010100 %0010100 %1001000 %0111111 %0001001 %0011100 %0011100 end return anim_frame_2 ; Corsa - Frame 2 player0: %0010000 %0010000 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end return ------------------------------------------------------- rem Fuga dal Castello Digitale set romsize 4k ; Imposta la dimensione della cartuccia virtuale a 4 kilobyte, necessaria per contenere tutto il codice. rem --- Mappa delle Variabili --- a = 0 ; Memorizza lo stato di riflessione dell'Eroe (0 = guarda a destra, 8 = guarda a sinistra, specchiato). b = 0 ; Timer per l'animazione dell'Eroe. Un contatore che cicla per decidere quale frame di animazione mostrare. c = 0 ; Timer per l'animazione del Guardiano. Simile a 'b', ma per il nemico. d = 0 ; Direzione del Guardiano (0 = si muove a destra, 1 = si muove a sinistra). Usato dall'IA di pattugliamento. e = 0 ; Stato del gioco (gamestate): 0=Inizializza, 1=In Gioco, 2=Vittoria, 3=Sconfitta. Il "cervello" del gioco. f = 0 ; Flag per la chiave: 0 = non posseduta, 1 = posseduta. i = 0 ; Flag di movimento: 1 se il giocatore sta muovendo il joystick, 0 se è fermo. s = 0 ; Sound Timer per il Canale Audio 0 (usato per l'Eroe). t = 0 ; Sound Timer per il Canale Audio 1 (usato per il Guardiano e le collisioni). x = 0 ; Posizione orizzontale (coordinata X) corrente dell'Eroe. y = 0 ; Posizione verticale (coordinata Y) corrente dell'Eroe. u = 0 ; Variabile temporanea per salvare l'ultima posizione X "sicura" dell'Eroe. v = 0 ; Variabile temporanea per salvare l'ultima posizione Y "sicura" dell'Eroe. z = 0 ; Posizione orizzontale (coordinata X) corrente del Guardiano. w = 0 ; Posizione verticale (coordinata Y) corrente del Guardiano. rem -- il playfield definisce la grafica statica del castello e non cambia durante il gioco -- playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......X........................X ......X........................X X....XX.....................X..X X...........................X..X X........................XXXX..X X..............................X X...X..........................X XXXXX.....................XXXXXX X.........................X..... XXXXXXXXXXXXXXXXXXXXXXXXXXX..... end main_loop ; Il cuore del gioco, un ciclo infinito che si ripete circa 60 volte al secondo. if e = 0 then gosub state_init_game ; Se il gioco è nello stato 0, esegui la routine di inizializzazione. if e = 1 then gosub state_gameplay ; Se il gioco è nello stato 1, esegui la logica principale del gameplay. if e = 2 then gosub state_win ; Se il gioco è nello stato 2, mostra la schermata di vittoria. if e = 3 then gosub state_game_over; Se il gioco è nello stato 3, mostra la schermata di game over. goto main_loop ; Torna all'inizio del ciclo per il prossimo frame. rem ========= SUBROUTINES DI STATO ========= state_init_game ; Questa subroutine viene eseguita solo una volta all'inizio di ogni partita. x = 30 : y = 80 ; Imposta la posizione di partenza dell'Eroe. z = 100 : w = 40 ; Imposta la posizione di partenza del Guardiano. f = 0 ; Resetta lo stato della chiave (non posseduta). e = 1 ; Cambia lo stato del gioco a "In Gioco". i = 0 ; Resetta il flag di movimento del giocatore. s = 0 ; Resetta i timer dei suoni. return ; Torna al main_loop. state_gameplay ; Questa subroutine contiene tutta la logica del gioco attivo. gosub handle_input ; Legge il joystick e gestisce il movimento/animazione dell'Eroe. gosub update_enemy_ai ; Muove e anima il Guardiano. gosub update_sounds ; Aggiorna i timer dei suoni e li spegne se necessario. gosub draw_world ; Disegna tutti gli elementi grafici sullo schermo. gosub check_collisions ; Controlla tutte le interazioni tra gli oggetti. return ; Torna al main_loop. state_win ; Schermata di vittoria. if s = 0 then gosub play_win_sound ; Suona l'effetto di vittoria, ma solo una volta. COLUBK = $9E ; Imposta lo sfondo a verde. player0y = 200 : player1y = 200 ; Nasconde i personaggi spostandoli fuori dallo schermo. if s > 1 then s = s - 1 else AUDV0 = 0 ; Fa durare il suono di vittoria per il suo tempo, poi lo spegne. drawscreen ; Continua a disegnare lo schermo per evitare il "roll". if joy0fire then e = 0 ; Se il giocatore preme fuoco, riavvia il gioco tornando allo stato di inizializzazione. return state_game_over ; Schermata di Game Over. if s = 0 then gosub play_lose_sound ; Suona l'effetto di sconfitta, ma solo una volta. COLUBK = $44 ; Imposta lo sfondo a rosso. player0y = 200 : player1y = 200 ; Nasconde i personaggi. if s > 1 then s = s - 1 else AUDV0 = 0 ; Fa durare il suono di sconfitta per il suo tempo, poi lo spegne. drawscreen ; Continua a disegnare lo schermo. if joy0fire then e = 0 ; Se il giocatore preme fuoco, riavvia il gioco. return rem ========= SUBROUTINES DI GIOCO ========= handle_input rem -- salviamo la posizione attuale dell'eroe per la logica "salva e ripristina" -- u = x : v = y i = 0 ; All'inizio di ogni frame, assumiamo che il giocatore sia fermo. rem -- Legge il joystick e aggiorna la posizione e la riflessione dell'Eroe -- if joy0left && x > 0 then x = x - 1 : a = 8 : i = 1 ; Se premi sinistra e non sei al bordo, muoviti a sinistra, imposta la riflessione e il flag di movimento. if joy0right && x < 159 then x = x + 1 : a = 0 : i = 1 ; Se premi destra... if joy0up && y > 0 then y = y - 1 : i = 1 ; Se premi su... if joy0down && y < 95 then y = y + 1 : i = 1 ; Se premi giù... rem -- Gestisce l'animazione dell'Eroe e il suono dei passi -- if i = 1 then b = b + 1 : if b > 20 then b = 0 ; Se l'eroe si sta muovendo, incrementa il suo timer di animazione. if i = 1 && s = 0 then gosub play_hero_step_sound ; Se si muove e il canale audio 0 è libero, riproduci il suono del passo. if i = 0 then b = 0 ; Se l'eroe è fermo, resetta il suo timer di animazione per mostrare il frame statico. return update_enemy_ai rem -- Logica di pattugliamento semplice: si muove avanti e indietro tra z = 20 e 120 -- if d = 0 then z = z + 1 ; Se la direzione è 0 (destra), incrementa la posizione X. if z > 120 then d = 1 ; Se raggiunge il limite destro, cambia direzione. if d = 1 then z = z - 1 ; Se la direzione è 1 (sinistra), decrementa la posizione X. if z < 20 then d = 0 ; Se raggiunge il limite sinistro, cambia direzione. rem -- Gestisce l'animazione del Guardiano e il suono dei passi -- c = c + 1 : if c > 20 then c = 0 ; Incrementa il timer di animazione del guardiano. if t = 0 then gosub play_enemy_step_sound ; Se il canale audio 1 è libero, riproduci un passo return update_sounds rem -- Gestisce i contatori alla rovescia per entrambi i canali audio -- if s > 0 then s = s - 1 else AUDV0 = 0 ; Decrementa il timer del canale 0. Se arriva a 0, spegne il volume. if t > 0 then t = t - 1 else AUDV1 = 0 ; Decrementa il timer del canale 1. Se arriva a 0, spegne il volume. return draw_world rem -- Seleziona e chiama la subroutine grafica corretta per l'Eroe in base al suo timer di animazione 'b' -- if b = 0 then gosub player0_static if b > 0 && b <= 10 then gosub player0_frame1 if b > 10 then gosub player0_frame2 rem -- Seleziona e chiama la subroutine grafica corretta per il Guardiano in base al timer 'c' -- if c <= 10 then gosub player1_frame1 if c > 10 then gosub player1_frame2 rem -- Posiziona la chiave (la 'ball') sullo schermo. Se è stata raccolta (f=1), la sposta fuori dall'area visibile -- ballheight = 4 : if f = 0 then ballx = 120 : bally = 50 else bally = 150 rem -- Aggiorna le posizioni finali degli sprite e imposta tutti i registri TIA prima di disegnare -- player0x = x : player0y = y : player1x = z : player1y = w COLUBK = $08 : COLUPF = $1A : COLUP0 = $AE : COLUP1 = $44 : REFP0 = a drawscreen ; Comando che dice al TIA di disegnare l'intero frame. return check_collisions rem -- Controlla se l'Eroe tocca il Guardiano. Se sì, suona un suono e imposta lo stato a Game Over -- if collision(player0, player1) then gosub play_hit_sound : e = 3 : s = 0 rem -- Controlla se l'Eroe tocca i muri del Playfield. Se sì, ripristina la sua posizione e suona un suono -- if collision(player0, playfield) then x = u : y = v : if t = 0 then gosub play_hit_sound rem -- Controlla se l'Eroe tocca la chiave (la 'ball'). Se sì, imposta il flag 'f' a 1 e suona un suono -- if f = 0 && collision(player0, ball) then f = 1 : gosub play_pickup_sound rem -- Controlla se l'Eroe, con la chiave in mano, raggiunge l'area della porta. Se sì, imposta lo stato a Vittoria -- if f = 1 && x < 20 && y < 28 then e = 2 : s = 0 return rem ====== SUBROUTINES AUDIO (impostano timer e registri audio per ogni effetto) ====== play_hero_step_sound s = 3 : AUDV0 = 8 : AUDC0 = 12 : AUDF0 = 25 : return play_enemy_step_sound t = 3 : AUDV1 = 6 : AUDC1 = 14 : AUDF1 = 28 : return play_hit_sound t = 10 : AUDV1 = 12 : AUDC1 = 2 : AUDF1 = 30 : return play_pickup_sound s = 15 : AUDV0 = 15 : AUDC0 = 12 : AUDF0 = 10 : return play_win_sound s = 20 : AUDV0 = 15 : AUDC0 = 12 : AUDF0 = 5 : AUDV1 = 0 : return play_lose_sound s = 20 : AUDV0 = 15 : AUDC0 = 2 : AUDF0 = 25 : AUDV1 = 0 : return rem ====== SUBROUTINES GRAFICHE (contengono i dati binari per ogni frame di animazione) ====== player0_static ; Frame per l'Eroe quando è fermo. player0: %0010100 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end return player0_frame1 ; Primo frame dell'animazione di corsa dell'Eroe. player0: %0010100 %0010100 %0010100 %1001000 %0111111 %0001001 %0011100 %0011100 end return player0_frame2 ; Secondo frame dell'animazione di corsa dell'Eroe. player0: %0010000 %0010000 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end return player1_frame1 ; Primo frame dell'animazione del Guardiano. player1: %0010100 %0010100 %1010101 %1011101 %0111110 %0001000 %0111110 %0011100 end return player1_frame2 ; Secondo frame dell'animazione del Guardiano. player1: %1000001 %0100010 %0010100 %0011100 %0111110 %1001001 %1011101 %0111110 end return ------------------------------------------------------- rem La Palla Rimbalzante set romsize 2k dim ball_x = a dim ball_y = b dim vel_x = c dim vel_y = d rem --- Inizializzazione --- ball_x = 80 ; Posizione iniziale ball_y = 50 vel_x = 1 ; Velocità iniziale vel_y = 1 main_loop rem --- Aggiorna Posizione --- ball_x = ball_x + vel_x ball_y = ball_y + vel_y rem --- Logica di Rimbalzo sui Bordi --- if ball_x < 10 || ball_x > 150 then vel_x = 0 - vel_x ; inverte velocità x if ball_y < 10 || ball_y > 85 then vel_y = 0 - vel_y ; inverte velocità y rem --- Disegno --- ballx = ball_x ; Assegna la posizione X calcolata al registro hardware bally = ball_y ; Assegna la posizione Y calcolata al registro hardware ballheight = 4 ; Altezza di 4 pixel CTRLPF = 32 ; Larghezza di 4 pixel (vedi Appendice B) COLUBK = $08 ; Sfondo grigio COLUPF = $1E ; Il colore della palla sarà giallo drawscreen goto main_loop ------------------------------------------------------- rem La Spada dell'Eroe set romsize 2k dim hero_x = a dim hero_y = b rem --- Inizializzazione --- hero_x = 80 hero_y = 50 player0: %11100111 %01100110 %01100110 %00111100 %11111111 %00011000 %00011000 end main_loop rem --- Logica di Movimento --- if joy0left then hero_x = hero_x - 1 if joy0right then hero_x = hero_x + 1 if joy0up then hero_y = hero_y - 1 if joy0down then hero_y = hero_y + 1 rem --- Logica della Spada --- ; se giocatore preme fuoco: ; Allinea la spada verticalmente al centro dell'eroe ; Posiziona la spada a destra dell'eroe ; Altezza minima, la trasforma in una linea ; Larghezza di 8 pixel (M=3, P=0 - vedi Appendice B) if joy0fire then missile0y = hero_y - 5: missile0x = hero_x + 8 : missile0height = 0 : NUSIZ0 = $30 ; se giocatore non preme fuoco: ; Nascondi la spada fuori dallo schermo if !joy0fire then missile0y = 200 rem --- Disegno --- player0x = hero_x player0y = hero_y COLUP0 = $1E ; Colore dell'eroe e della spada (giallo) COLUBK = $04 ; Sfondo grigio drawscreen goto main_loop ------------------------------------------------------- rem Progetto: Tiro al Bersaglio set romsize 2k rem --- Alias delle Variabili --- dim player_x = a dim missile_y = b dim target_x = c dim target_y = d dim game_over = e dim timer_caduta = f rem --- Inizializzazione del Gioco --- gosub reset_game main_loop rem se il gioco non è finito, continua con la logica di gioco if game_over = 0 then goto main_loop2 rem Se il gioco è finito, attendi l'input per riavviare if joy0fire then gosub reset_game goto draw_frame ; Salta la logica di gioco main_loop2 rem --- Logica di Gioco --- rem 1. Movimento del Giocatore if joy0left && player_x > 10 then player_x = player_x - 1 if joy0right && player_x < 150 then player_x = player_x + 1 rem 2. Logica dello Sparo rem Se il pulsante è premuto E non c'è già un missile attivo (missile_y > 0) if joy0fire && missile_y = 0 then missile_y = 85 : missile0x = player_x + 4 ; Posizione di partenza del missile ; Allinea il missile al centro del giocatore rem 3. Movimento del Missile if missile_y > 0 then missile_y = missile_y - 3 : if missile_y < 10 then missile_y = 0 ; Muovi il missile verso l'alto ; Se raggiunge la cima, disattivalo rem 4. Movimento del Bersaglio timer_caduta = timer_caduta + 1 ; ogni frame incrementa il timer di caduta if timer_caduta = 3 then timer_caduta = 0 : target_y = target_y + 1 ; Fai cadere il bersaglio solo quando timer_caduta è uguale a 3 ; questo rallenta la caduta if target_y > 90 then game_over = 1 ; Se il bersaglio tocca il fondo il gioco finisce. rem 5. Controllo Collisioni rem La funzione collision() controlla se missile0 e ball si toccano if collision(missile0, ball) then score = score + 1 : gosub reset_target : missile_y = 0 ; Aumenta il punteggio ; Fai riapparire il bersaglio in un nuovo punto ; Disattiva il missile per poter sparare di nuovo draw_frame rem --- Sezione di Disegno --- rem Disegna il giocatore player0x = player_x player0y = 88 player0: ; Una semplice forma a "torretta" %11111111 %01111110 %00111100 end rem Posiziona il missile (se attivo) oppure nascondilo if missile_y > 0 then missile0y = missile_y if missile_y = 0 then missile0y = 200 missile0height = 8 ; Un missile alto e sottile rem Disegna il bersaglio (la ball) ballx = target_x bally = target_y ballheight = 4 CTRLPF = 32 ; Rende la palla larga 4 pixel, per farla quadrata rem Imposta i colori if game_over = 1 then COLUBK = $44 ; Sfondo rosso in game over if game_over = 0 then COLUBK = $08 ; Sfondo grigio durante il gioco COLUP0 = $9E ; azzurro per giocatore e missile COLUPF = $1E ; Giallo per il bersaglio (la ball condivide il colore del playfield) scorecolor = $1E ; Colore giallo per il testo dello score drawscreen goto main_loop rem ========= SUBROUTINES ========= reset_game rem Questa subroutine inizializza o ripristina lo stato del gioco player_x = 80 missile_y = 0 game_over = 0 score = 0 gosub reset_target return reset_target rem Riposiziona il bersaglio in un nuovo punto casuale in alto target_x = rand/2 + 20 ; Usa rand per la posizione X, con un offset target_y = 1 timer_caduta = 0 return ------------------------------------------------------- rem Il Ponte Magico set romsize 2k dim player_x = a dim player_y = b dim bricks = c dim floor = d dim retain = e rem --- Inizializzazione --- player_x = 20 player_y = 64 bricks = 5 ; Il giocatore ha 5 mattoni player0: %0010100 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ......X........................X ......X........................X X....XX.....................X..X X...........................X..X X........................XXXX..X X............................... X............................... XXXXXXXXXXXX.....XXXXXXXXXXXXXXX X..............................X X..............................X end main_loop if joy0left && player_x > 20 then player_x = player_x - 1 rem determina se il giocatore è sul ponte t = (player_x + 5 - 16) / 4 ; +5 perchè il piede destro finisce al pixel 5 if joy0right && player_x < 130 && pfread(t,8) then player_x = player_x + 1 rem Resetta il flag di ritenzione del fire if !joy0fire then retain = 0 rem Se il giocatore preme fuoco if joy0fire && bricks > 0 && retain = 0 then goto build_bridge goto continue_game build_bridge t = 17 - bricks pfpixel t 8 on ; ...costruisce un pezzo di ponte! bricks = bricks - 1 retain = 1 continue_game player0x = player_x player0y = player_y COLUP0 = $1E ; Colore player0 COLUBK = $04 ; Sfondo grigio COLUPF = $9E ; Colore playfield drawscreen goto main_loop ------------------------------------------------------- rem Movimento su Griglia set romsize 2k dim allow_h = a dim allow_v = b dim current_dir = c dim desired_dir = d player0x=77 : player0y=48 ; posizione iniziale playfield: ................................ ................................ ................................ ................................ ..XXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ..X..........................X.. ..XXXXXXXXXXXXX..XXXXXXXXXXXXX.. ..X..........................X.. ..XXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ................................ ................................ end player0: %00111100 %01111110 %11111111 %11100000 %11111111 %01011110 %00111100 end main_loop gosub check_grid_position gosub handle_grid_input gosub apply_grid_movement COLUP0 = $1E ; Giallo per il giocatore COLUPF = $9E ; Azzurro per lo sfondo drawscreen goto main_loop check_grid_position allow_h = 0 : allow_v = 0 rem Puoi cambiare direzione orizzontale solo sulle righe 48 o 64 if player0y = 48 || player0y = 64 then allow_h = 1 rem Puoi cambiare direzione verticale solo sulla colonna 77 if player0x = 77 then allow_v = 1 return handle_grid_input if joy0up then desired_dir = 1 if joy0down then desired_dir = 2 if joy0left then desired_dir = 3 if joy0right then desired_dir = 4 return apply_grid_movement rem Se sei su un incrocio orizzontale, puoi cambiare direzione orizzontale if allow_h && desired_dir = 3 then current_dir = desired_dir if allow_h && desired_dir = 4 then current_dir = desired_dir rem Se sei su un incrocio verticale, puoi cambiare direzione verticale if allow_v && desired_dir = 1 then current_dir = desired_dir if allow_v && desired_dir = 2 then current_dir = desired_dir rem Muovi sempre nella direzione corrente if current_dir = 1 then player0y = player0y - 1 if current_dir = 2 then player0y = player0y + 1 if current_dir = 3 then player0x = player0x - 1 if current_dir = 4 then player0x = player0x + 1 rem Limita i movimenti all'interno della griglia if player0y < 48 then player0y = 48 if player0y > 64 then player0y = 64 if player0x < 29 then player0x = 29 if player0x > 125 then player0x = 125 return ------------------------------------------------------- rem Le Due Stanze set romsize 2k dim player_x = a dim player_y = b dim room = c room = 1 ; si parte dalla stanza 1 player_x = 50 player0: %0010100 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end main_loop gosub handle_movement gosub handle_room_transition gosub draw_current_room goto main_loop rem ========= SUBROUTINES ========= handle_movement if joy0left then player_x = player_x - 1 if joy0right then player_x = player_x + 1 if player_x > 136 then player_x = 136 if player_x < 16 then player_x = 16 return handle_room_transition rem Se esci a destra dalla stanza 1, vai alla stanza 2 if room = 1 && player_x > 134 then room = 2 : player_x = 18 rem Se esci a sinistra dalla stanza 2, torna alla stanza 1 if room = 2 && player_x < 18 then room = 1 : player_x = 134 return draw_current_room player0x = player_x player0y = 64 COLUP0 = $08 rem Centralino grafico if room = 1 then gosub draw_room1 if room = 2 then gosub draw_room2 drawscreen return draw_room1 COLUBK = $86 ; Sfondo blu COLUPF = $1E playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X.....X........................X X.....X........................X X.....X.....................X..X X...........................X..X X........................XXXX..X X............................... X............................... XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ................................ ................................ end return draw_room2 COLUBK = $36 ; Sfondo rosso COLUPF = $1E playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X.....X........................X X.....X........................X X...XXX........................X X......................X.......X X......................XXXX....X ...............................X ...............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ................................ ................................ end return ------------------------------------------------------- rem Player0,Player1,playfield multicolor set kernel_options playercolors player1colors pfcolors set romsize 2k COLUBK = $00 ; Sfondo nero player0: %0010100 ; ultima riga player 0 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 ; prima riga player 0 end player1: ; ultima riga player1 %0010100 %0010100 %0010100 %1001000 %0111111 %0001001 %0011100 %0011100 ; prima riga player1 end player0color: $44 ; colore ultima riga player0 $44 $44 $3E $3E $3E $44 $44 ; colore prima riga player 0 end player1color: $1E ; colore ultima riga player1 $1E $1E $60 $60 $60 $1E $1E ; colore prima riga player1 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ; riga 0 playfield X.....X........................X X.....X........................X X.....X.....................X..X X...........................X..X X........................XXXX..X X............................... X............................... XXXXXXXXXXXX.....XXXXXXXXXXXXXXX X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ; riga 10 playfield end pfcolors: $08 ; colore riga 0 playfield $0C ; colore riga 1 playfield $08 ; ... $0A $0A $0C $08 $0A $0A $0A $D4 ; colore riga 10 playfield end player0x = 30 player0y = 64 player1x = 50 player1y = 64 main_loop COLUPF = $08 ; colore riga 0 playfield drawscreen goto main_loop ------------------------------------------------------- rem Platform Hero - Fisica con Virgola Fissa set romsize 2k include fixed_point_math.asm dim hero_x_fixed = a.b ; Posizione X a virgola fissa dim hero_y_fixed = c.d ; Posizione Y a virgola fissa dim y_velocity = e.f ; Velocità Y a virgola fissa dim on_ground = g ; 1 = a terra, 0 = in aria rem --- Inizializzazione --- hero_x_fixed = 80 hero_y_fixed = 64 y_velocity = 0.0 player0: %0010100 %0010100 %0010100 %1001001 %0111110 %0001000 %0011100 %0011100 end playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X.....X........................X X.....X........................X X.....X........................X X..............................X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ................................ ................................ end COLUP0 = $1E COLUBK = $86 COLUPF = $1E main_loop gosub handle_input gosub handle_physics gosub move_hero drawscreen goto main_loop rem ========= SUBROUTINES ========= handle_input rem Movimento orizzontale if joy0left && hero_x_fixed > 16 then hero_x_fixed = hero_x_fixed - 1 if joy0right && hero_x_fixed < 134 then hero_x_fixed = hero_x_fixed + 1 rem Salto: si può saltare solo se si è a terra if joy0fire && on_ground then y_velocity = -4 ; impulso iniziale verso l'alto return handle_physics rem 1. Applica la gravità (tira sempre verso il basso) y_velocity = y_velocity + 0.3 rem 2. Applica il movimento verticale (velocità e posizione) hero_y_fixed = hero_y_fixed + y_velocity rem 3. Controlla se il giocatore è atterrato if hero_y_fixed < 64 then on_ground = 0 ; In aria if hero_y_fixed >= 64 then hero_y_fixed = 64 : y_velocity = 0.0 : on_ground = 1 ; Impedisce di sprofondare, ferma la caduta return move_hero player0x = hero_x_fixed ; Assegna SOLO la parte intera alla posizione visibile player0y = hero_y_fixed return ------------------------------------------------------- set romsize 2k score = 0 main_loop scorecolor = $1E ; Colore giallo per il punteggio if joy0fire then score = score + 100 drawscreen goto main_loop ------------------------------------------------------- rem HUD Completo set romsize 2k const pfscore = 1 ; attiva barre laterali dim lives_bar = a dim health_bar = b dim retainleft = c dim retainright = d rem --- Inizializzazione --- lives_bar = %00010101 ; 3 vite (i bit 0, 2, 4 sono accesi) health_bar = %11111111 ; Salute piena (tutti i bit accesi) main_loop rem --- Logica di Gioco (Simulata) --- rem Se premi sinistra, perdi salute if !joy0left then retainleft = 0 if joy0left && retainleft = 0 then health_bar = health_bar / 2 : retainleft = 1 rem Se premi destra, perdi una vita if !joy0right then retainright = 0 if joy0right && retainright = 0 then lives_bar = lives_bar / 4 : retainright = 1 rem Se premi fire ripristina valori iniziali if joy0fire then lives_bar = %00010101 : health_bar = %11111111 : score = score + 1 rem --- Disegno HUD --- scorecolor = $1E ; colore giallo pfscorecolor = $86 ; colore blu pfscore1 = lives_bar pfscore2 = health_bar drawscreen goto main_loop ------------------------------------------------------- rem Ciclo Colori con Array data set romsize 2k set smartbranching on dim color_index = a main_loop if joy0fire then color_index = color_index + 1 rem Se l'indice supera la dimensione dell'array, lo azzera if color_index > 6 then color_index = 0 rem Leggi il colore dall'array e assegnalo allo sfondo COLUBK = palette_colors[color_index] drawscreen goto main_loop rem --- Definisci la tua tavolozza di colori in un array data --- data palette_colors $1E, $48, $86, $9C, $D4, $EA, $34 end ------------------------------------------------------- rem Motore Musicale con sdata set romsize 2k dim music_note_duration = a dim mus1 = b dim mus2 = c dim mus3 = d rem --- Inizializzazione --- gosub music_setup main_loop gosub music_play drawscreen goto main_loop music_play music_note_duration = music_note_duration - 1 if music_note_duration > 0 then return ; Se la nota non è finita, esci rem --- La nota e' finita, leggi la prossima dalla tabella --- rem Formato dati: Volume, Timbro, Frequenza, Durata mus1 = sread(music_data) ; Leggi il Volume rem Se il volume è 255, la canzone è finita. Riavvolgi. if mus1 = 255 then gosub music_setup : return mus2 = sread(music_data) ; Leggi il Timbro mus3 = sread(music_data) ; Leggi la Frequenza music_note_duration = sread(music_data) ; Leggi la Durata rem Imposta i registri audio per suonare la nuova nota AUDV0 = mus1 AUDC0 = mus2 AUDF0 = mus3 return music_setup rem --- TABELLA DATI MUSICALE --- rem Scegli la variabile x come puntatore alla tabella musicale rem Vol, Timbro, Freq, Durata sdata music_data = x 12, 4, 28, 15 ; Do 12, 4, 25, 15 ; Re 12, 4, 22, 15 ; Mi 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 28, 15 ; Do 12, 4, 25, 15 ; Re 12, 4, 22, 15 ; Mi 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 22, 15 ; Mi 12, 4, 21, 15 ; Fa 12, 4, 18, 30 ; Sol (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 22, 15 ; Mi 12, 4, 21, 15 ; Fa 12, 4, 18, 30 ; Sol (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 18, 15 ; Sol 12, 4, 16, 15 ; La 12, 4, 18, 15 ; Sol 12, 4, 21, 15 ; Fa 12, 4, 22, 15 ; Mi 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 18, 15 ; Sol 12, 4, 16, 15 ; La 12, 4, 18, 15 ; Sol 12, 4, 21, 15 ; Fa 12, 4, 22, 15 ; Mi 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 28, 15 ; Do 12, 4, 30, 15 ; Sol (basso) 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 12, 4, 28, 15 ; Do 12, 4, 30, 15 ; Sol (basso) 12, 4, 28, 30 ; Do (lunga) 0, 0, 0, 15 ; Pausa 255 ; Marcatore di fine canzone end music_note_duration = 1 ; Inizia subito la prima nota return -------------------------------------------------------