LEZIONE 20 – LA GRAFICA – GLI SPRITES (5°Parte)

da | Gen 25, 2024 | MSX BASIC | 0 commenti

Abbiamo creato il nostro sprite e lo abbiamo fatto muovere sullo schermo. Adesso vediamo come creare la collisione tra sprites. L’MSX ha un comando creato apposta per le collisioni. Questo funziona come un interruttore, ogni volta che due sprite si “toccano”, lascia tutto quello che sta facendo per andare in questa apposita subroutine. Innanzitutto, per fare sì che questa funzioni dobbiamo attivarla. Per fare questo dobbiamo mettere all’inizio del nostro programma di gioco il seguente comando: ON SPRITE GOSUB Numero di linea. Abbiamo preparato l’MSX alle collisioni, però non è ancora attivo. Per fare ciò dobbiamo dare un altro comando: SPRITE ON. Da questo momento in poi tutti gli sprites che entreranno
in collisione, verranno intercettati, cioè l’esecuzione del programma andrà nella subroutine che abbiamo creato con ON SPRITE GOSUB. Se vogliamo disattivare le collisioni basta cambiare il comando in SPRITE OFF. Ce n’è un altro: SPRITE STOP,
che sospende le collisioni, cioè li riconosce ma non va alla subroutine d’intercettamento. Per riattivare il tutto basta riportarlo in SPRITE ON. Farò un piccolo programma per essere più chiaro su tutto quello che ho detto. Ma prima voglio
parlare di altri 2 comandi fondamentali per i nostri giochi. Il primo è STICK, controlla lo stato dei tasti cursore o il joystick. Infatti, restituirà -1 se abbiamo premuto un tasto cursore o mosso la leva del joy. La suddetta funzione riconosce otto movimenti, anzi 9 se mettiamo quella di riposo. Faccio uno schizzo per rendere la spiegazione più semplice.


            8  1  2
             \ | /
          7 -  0  - 3
             / | \
            6  5  4

Possiamo mettere la funzione dentro una variabile. Se usiamo i tasti è Q=STICK(0), se usiamo il joystick in porta 1 è Q=STICK(1), la seconda porta sarà Q=STICK(2).
Quando viene premuto un tasto cursore o spostato la leva joystick il comando legge il movimento e lo restituisce alla variabile. La riga di programma potrebbe essere così:

100 Q=STICK(0)OR STICK(1):ON Q GOSUB 300,310,320,330,340,350,360,370

Nella prima parte della linea ho fatto in modo che la variabile Q sia uguale ai tasti cursore e al joystick. Nella seconda parte, sfruttando il comando ON GOSUB, l’esecuzione andrà al sottoprogramma stabilito. Se ad esempio abbiamo premuto il
cursore o la leva a destra, attiverà la terza routine, quella che si trova alla linea 320.
Il secondo comando è STRIG e ON STRIG, che serve per attivare la barra spazio o i pulsanti del joystick. Funziona come ON SPRITE, ma visto con quest’ultima, attivandola vale per tutte le collisioni, la STRIG deve essere attivata per ogni tasto. Le possibilità sono 5: 0 = Barra spazio, 1 = Primo pulsante Joystick 1, 2 = Primo pulsante del Joystick 2, 3 = Secondo pulsante del Joystick 1 ed infine 4 = Secondo pulsante del Joystick 2. Per attivare uno dei tasti o tutti insieme,
dobbiamo mettere il numero di linea nel comando ON STRIG. ON STRIG GOSUB 400,400.
Così facendo abbiamo predisposto il comando alla barra spazio e il primo tasto del joystick 1. Ma come la ON SPRITE, per renderli attivi dobbiamo aggiungere; STRIG(0)ON per la barra e STRIG(1)ON per il pulsante del Joy. Se vogliamo giocare con il primo pulsante dei due joystick, basta aggiungere un altro numero linea al comando ON STRIG e attivarlo con STRIG(3)ON. Visto che in mezzo c’è la posizione 2 che non è attiva ricordiamoci di lasciare uno spazio vuoto: ON STRIG GOSUB 400,400,,420. STRIG(X)STOP e STRIG(X)OFF, sospende e disattiva il comando, proprio come succede con SPRITE OFF/STOP.

Dopo aver spiegato come utilizzare i tasti per il movimento, procedo con il programma. Utilizzerò la navicella creata nella lezione precedente.

10 SCREEN 2,2: COLOR 15,1,1: CLS: OPEN “GRP:” AS#1: ON SPRITE GOSUB 200: ON STRIG GOSUB 400,400
20 S$=””: FOR I=0 TO 31: READ A$: S$=S$+CHR$(VAL(“&H”+A$)): NEXT I: SPRITE$(0)=S$: S$=””: FOR I=0 TO 7: READ A$: S$=S$+CHR$(VAL(“&H”+A$)):NEXT I: SPRITE$(1)=S$:L=1:P=0
30 FOR I=1 TO 100: PSET(RND(1)255,RND(1)191),11: NEXT I: FOR I=1 TO 5: CIRCLE(RND(1)240,RND(1)180),5,13: NEXT I: PRESET(0,0):PRINT#1,”SCORE”;P: PRESET(0,184):PRINT#1,”LEVEL”;L
40 V=0:F=0:X=0:Y=120:X1=240:Y1=120:R=0:SPRITE ON: STRIG(0)ON: STRIG(1)ON
50 Q=STICK(0)OR STICK(1): ON Q GOSUB 300,310,320,330,340,350,360,370
60 PUTSPRITE 0,(X,Y),15,0
70 GOSUB 100
80 IF F=1 THEN X2=X2+R:PUTSPRITE 2,(X2,Y2),14,1:IF X2<16 OR X2>232 THEN F=0:X2=0:Y2=0: PUTSPRITE 2,(X2,Y2),0
90 IF V=5*L THEN 150 ELSE 50
99 ‘ ** MOVIMENTO ASTRONAVE NEMICA **
100 IF X1>X THEN X1=X1-8 ELSE IF X1<=X THEN X1=X1+8
110 IF Y1>Y THEN Y1=Y1-8 ELSE IF Y1<=Y THEN Y1=Y1+8
120 PUTSPRITE 1,(X1,Y1),6,0: RETURN
149 ‘ ** PASSAGGIO LIVELLO **
150 SPRITE OFF: STRIG(0)OFF: STRIG(1)OFF
160 PRESET(40,120):PRINT #1,”YOU WIN! LEVEL PASSED!”:FOR I=0 TO 2: PUTSPRITE I,,0: NEXT
170 L=L+1:X2=0:Y2=0:FOR I=0TO 3000: NEXT: CLS:GOTO 30
199 ‘ ** COLLISIONI **
200 SPRITE OFF
210 IF X1+16>=X AND X1<=X+16 AND Y1+16>=Y AND Y1<=Y+16 THEN FOR I=0 TO 2: PUTSPRITE I,,0:NEXT I:PRESET(40,120): PRINT #1,”YOU LOSE. TRY AGAIN!!!”: FOR I=0 TO 3000:NEXT I: RUN
220 IF X2+8>=X1 AND X2<=X1+16 AND Y2+8>=Y AND Y2<=Y1+16 THEN X2=0:Y2=0: PUTSPRITE 1,(X1,Y1),0: PUTSPRITE 2,(X2,Y2),0: P=P+100: V=V+1: LINE(41,0)-(88,7) ,1,BF: PRESET(41,0):PRINT#1,P: F=0:X1=240:Y1=120:GOSUB 120
30 SPRITE ON: RETURN
299 ‘ ** MOVIMENTO DELLA NOSTRA NAVICELLA **
300 IF Y<8 THEN RETURN ELSE Y=Y-8: RETURN
310 IF Y<8 OR X>232 THEN RETURN ELSE Y=Y-8:X=X+8: RETURN
320 IF X>232 THEN RETURN ELSE X=X+8: RETURN
330 IF X>232 OR Y>168 THEN RETURN ELSE X=X+8:Y=Y+8: RETURN
340 IF Y>168 THEN RETURN ELSE Y=Y+8: RETURN
350 IF Y>168 OR X<8 THEN RETURN ELSE X=X-8:Y=Y+8: RETURN
360 IF X<8 THEN RETURN ELSE X=X-8: RETURN
370 IF X<8 OR Y<8 THEN RETURN ELSE X=X-8:Y=Y-8
380 RETURN
399 ‘ ** FUOCO DELLA NOSTRA NEVICELLA **
400 IF F=1 THEN RETURN ELSE F=1
410 IF X>X1 THEN R=-8:X2=X-8 ELSE IF X<X1 THEN R=8: X2=X+16
420 Y2=Y+4:PUTSPRITE 2,(X2,Y2),14,1: RETURN
999 ‘ *** Dati Astronave ***
1000 DATA 0F,1F,1C,18,18,18,7C,FF
1010 DATA BF,FF,6F,7D,3F,18,30,60
1020 DATA F0,F8,38,18,18,18,3E,FF
1030 DATA FD,FF,F6,BE,FC,18,0C,06
1040 ‘ ** DATI MISSILE NAVICELLA **
1050 DATA 3C,7F,FF,FF,FF,FF,7E,3C

E’ una battaglia tra due navicelle. Quella che guideremo è di colore bianco, dobbiamo lanciare i missili per distruggere la navicella nemica, che è di colore rosso e cercherà in tutti i modi di inseguirci e speronarci. Possiamo sparare solo
in orizzontale, questo lo fa automaticamente tramite programma, se il nemico è a destra sparerà a destra e viceversa. Movimenti con tasti cursore o Joystick, per sparare: barra spazio o pulsante joystick. Il gioco non avrà fine continuerà fin
quando non verrà distrutta la nostra navicella.
Questo gioco è un riassunto di tutto quello che ho spiegato. Sarò breve per riassumere alcune parti importanti del programma. Linea 10, dopo i soliti dati di inizializzazione, ho attivato le ruotine di intercettamento collisioni e tasti
fuoco. Linea 20, caricamento dei dati degli sprites, stavolta ho usato numeri esadecimali. Nella linea 30 ho creato un “misero” sfondo fatto di stelle e qualche pianeta usando il posizionamento casuale, tanto per mettere qualcosa. La 40
inizializza tutte le variabili che ci serviranno e attiva collisioni e tasti fuoco.
La 50 sarà processata solo se premeremo uno dei tasti di movimento. Le linee che vanno dalla 300 alla 370 sono i movimenti della nostra navicella, ho messo anche un blocco per non andare oltre i bordi dello schermo. La 70 manda il programma alla subroutine del movimento della nave nemica. La 80 controlla la variabile F, è un flag di controllo, per vedere se è stato premuto la barra spazio o il pulsante del joystick, se si varrà 1 ed eseguirà tutte le sue istruzioni. Questo avvinte perchè prima va alla routine del ON STRIG nella linea 400. In quest’ultima c’è un altro controllo che non fa eseguire la routine se il missile è ancora in movimento cioè se questa è ancora 1. Sarà riattivata solo se la F ritornerà 0. La 90 controlla se si è raggiunto il numero di colpi andati a segno contro il nemico. Se si,andrà alla 150 e ricomincerà un nuovo livello, aumentando il numero dei colpi contro il nemico altrimenti rimanderà alla riga 50 per un altro giro. Per finire, le
collisioni che vengono attivate alla linea 40. Quando 2 sprites si toccano l’esecuzione salterà alla linea 200, dove la prima cosa da fare e disattivarle (linea 200), altrimenti il continuo “tocco” farebbe rallentare l’esecuzione, per poi attivarle all’uscita della routine (linea 230). Se notate, alla linea 410, ho fatto partire il missile in modo che non tocchi la propria navicella, altrimenti sarebbe scattalo l’interruttore collisioni e visto che tra loro non c’è nessun controllo, sarebbe stato un rallentamento unico. Purtroppo, questo è il problema più grosso quando si usa ON SPRITE, che non puoi selezionare gli sprites da escludere, qualsiasi contatto tra loro crea la collisione. Finchè il gioco usa pochi sprites, come questo, il problema è risolvibile, ma quando sono tanti, è più conveniente non usarlo. Usare un controllo con i pixel è la soluzione ideale, proprio come ho fatto all’interno della ruotine collisioni ed esattamente alle linee 210 e 220. Potevo benissimo eliminare il tutto, cioè ON SPRITE, SPRITE ON e la routine completa e inserire solo le 2 linee dette dentro lo svolgimento del programma, ad esempio la 210 diventava 83 e la 220 la 86, non sarebbe cambiato niente. Ma con l’avvento del MSX2 hanno risolto in parte questo problema.

Per terminare questa lunga puntata, finisco con il dire che il gioco che ho creato è solo a scopo didattico e può essere implementato e soprattutto ottimizzato per renderlo ancora più veloce. Chi ha voglia e se la sente, potrebbe migliorarlo
aggiungendo altri sprites o magari creando uno sfondo più decente o provare a cambiare le dinamiche del gioco. Magari postando gli aggiornamenti effettuati.
Dai ragazzi fatemi vedere se queste mie spiegazioni hanno portato dei buoni frutti 🙂
Grazie a tutti, alla prossima.

0 commenti

Invia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

LEZIONE 26 – INTERVAL ON, RND ED ALTRI

LEZIONE 26 – INTERVAL ON, RND ED ALTRI

Buongiorno a tutti, In questa puntata parlerò di un interrupt importante, specialmente per i giochi, quando vogliamo far apparire un nemico all'improvviso o un oggetto utile, ma anche per creare un cronometro o un orologio e tante altre cose. Il COMANDO sfrutta il...

it_ITIT_IT