Utilizzare numeri binari per verificare condizioni

Tutorial, videotutorials ed esempi creati da noi
Rispondi
Avatar utente
Vallo92
GMI Advanced
Messaggi: 1508
Iscritto il: 15/07/2011, 20:26
Specialità: Grafico
Uso: GM:Studio 2
Contatta:

Utilizzare numeri binari per verificare condizioni

Messaggio da Vallo92 »

Visto che ho un po' di tempo libero ho deciso di scrivere questa piccola guida per mostrarvi un semplice e utile metodo per verificare semplici condizioni (true o false) utilizzando numeri binari.
Nello specifico, utilizzeremo numeri binari per assegnare a oggetti diverse, image_index di un singolo sprite.

Prima di iniziare vorrei dare la definizione di numero binario a chi non sa di cosa stiamo parlando:
Il sistema numerico binario, o sistema in base 2, deve il suo nome al fatto che vengono utilizzate solo e soltanto due cifre: 0 e 1. Proprio come nel caso di quello che usiamo tutti i giorni, il sistema di numerazione binario è posizionale, cioè ha importanza la posizione assunta da ogni singola cifra all'interno di un numero.
In questa guida creeremo degli oggetti "personaggio" a cui assegneremo degli sprite "freccia" che indicheranno le direzioni in cui possono muoversi (ne sceglieremo un numero a piacere su 8 direzioni totali: est, nord-est, nord, nord-ovest, ovest, sud-ovest, sud, sud-est).

Iniziamo subito creando due nuovi sprite:
- Uno sprite sPersonaggio rappresentante il nostro personaggio:
Immagine
-Uno sprite sFrecce rappresentante le 8 frecce direzionali (8 immagini totali):
ATTENZIONE Le frecce direzionali devono rispettare il seguente ordine: est, nord-est, nord, nord-ovest, ovest, sud-ovest, sud, sud-est.
Quindi: est > image_index 0, nord-est > image_index 1, etc.
Immagine

Adesso creiamo un nuovo oggetto, chiamiamolo oPersonaggio, e assegniamogli lo sprite sPersonaggio.

oPersonaggio
Create:

Codice: Seleziona tutto

direzioni = 1;
Nell'evento Create dell'oggetto oPersonaggio creiamo una nuova variabile chiamata "direzioni" e salviamo al suo interno un numero.
Ma che significato ha quel numero? Bene, adesso entreremo nel vero fulcro di questo sistema, quindi spremete le vostre meningi e cercate di capire questo funzionamento. Una volta capito questo passaggio, avrete capito l'intero sistema.
Il numero decimale 1, convertito in binario è scritto 00000001. Se contate gli 0 e gli 1 che compongono il numero binario vi accorgerete che in totale sono 8, proprio quante le possibili direzioni totali che vogliamo disegnare sul nostro personaggio tramite le varie image_index del nostro sprite sFrecce. Con questo sistema andremo ad assegnare ad ogni personaggio un numero intero, che convertito in binario, restituisce una serie di 8 numeri (0 e 1) che possiamo sfruttare per capire se in una direziona il personaggio ha una freccia (1, quindi true) o non ha una freccia (0, quindi false). In pratica inizieremo a leggere da destra il numero binario convertito dal numero decimale della variabile direzioni, e seguendo sempre l'ordine "est, nord-est, nord, nord-ovest, ovest, sud-ovest, sud, sud-est" sapremo se esiste una freccia in una determinata direzione.
Esempio:
00000001 indica che esiste sono la freccia rivolta verso destra. Leggendo il numero binario partendo da destra vedremo che è true (1, quindi esiste) sono la freccia est visto che leggiamo le direzioni sempre nell'ordine "est, nord-est, nord, nord-ovest, ovest, sud-ovest, sud, sud-est".
01000100 indica che sono presenti solo le frecce che indicano verso nord e sud.

Codice: Seleziona tutto

   0      1       0        0        0        1       0       0
sud-est  sud  sud-ovest  ovest  nord-ovest  nord  nord-est  est
Come facciamo però a convertire il nostro numero binario in numerazione decimale per immagazzinarlo all'interno della nostra variabile direzioni?
Esempio:
Se vogliamo scrivere nella numerazione decimale il numero binario 10101010. Avremo:
[latex]1 * 2^{7} + 0 * 2^{6} + 1 * 2^{5} + 0 * 2^{4}+ 1 * 2^{3} +

+ 0 * 2^{2} + 1 * 2^{3} + 0 * 2^{2} + 1 * 2^{1} + 0 * 2^{0}[/latex]
==
[latex]1 * 128 + 0 * 64 + 1 * 32+ 0 * 16+ 1 * 8 + 0 * 4 + 1 * 2 + 0 * 1[/latex]
==
[latex]128 + 0 + 32 + 0 + 8 + 0 + 2 + 0 = 170[/latex]
Quindi 10101010 binario è uguale a 170 decimale.
Per chi non ha molto chiaro il metodo può semplificarsi la vita cercando sella rete un convertitore binario/decimale che fa il lavoro sporco al posto vostro.

Bene, chiusa questa spiegazione (spero di essere stato abbastanza chiaro) torniamo al nostro oPersonaggio a cui avevamo appena assegnato una variabile direzioni contenente il valore 1.
Adesso sappiamo che il valore uno convertito in binario è scritto 00000001, e che noi utilizzeremo ogni singola cifra di tale numero per capire se disegnare una freccia in una determinata direzione o no. Ma come facciamo a fare questo?

Creiamo due nuovi script e chiamiamoli sDisegnoFreccia e sFrecciaEsistente:
sDisegnoFreccia

Codice: Seleziona tutto

var i;

//Ciclo le 8 direzioni
for(i=0; i<8; i++) {
   //Se la freccia esiste disegno lo lo sprite con image_index corretta. L'image index va da destra (image_index =0) e si muove verso sinistra in senso antiorario)
   if(sFrecciaEsistente(direzioni,i)) {
      draw_sprite(sFrecce,i,0,0);
   }
}
sFrecciaEsistente

Codice: Seleziona tutto

//Argument: direzioni, freccia

//Controllo se è presente una freccia nella posizione corrente (posizione nel numero binario). Se esiste il risultato è 1, quindi vero.
return (argument0 >> argument1) & 1;
Il funzionamento di sDisegnoFreccia è molto semplice: tramite un ciclo for andiamo a ciclare tutte le 8 direzioni possibili (quindi tutti e 8 i numeri che compongono il nostro numero binario), e se tramite lo script sFrecciaEsistente ci risulta che una freccia esiste, la disegnamo subito nella direzione corretta.

Il funzionamento di sFrecciaEsistente invece è leggermente più complicato, e per illustrarlo bisogna comprendere il funzionamento di due nuovi "simboli": gli operatori bitwise "&" e ">>".
- & (o anche "AND") restituisce questi valori:

Codice: Seleziona tutto

1 & 1 = 1
0 & 1 = 0
1 & 0 = 0
0 & 0 = 0
Quindi il risultato è 1 se i due operandi valgono 1. Altrimenti 0.
- Gli shift ">>" e "<<" equivalgono rispettivamente a divisione per multiplo di 2 e moltiplicazione per multiplo di 2.
Utilizzeremo gli shif per "shiftare" (ovvero far scorrere) i vari bit del numero binario verso una determinata direzione.
Esempio:

Codice: Seleziona tutto

1 << 2 = 00000100
1 >> 1 = 00000000
74 << 2 = 00101000
Andiamo quindi ad analizzare il nostro script sFrecciaEsistente:
lo script restituisce 1 o 0 (quindi vero o falso) in base al valore del bit all'estrema destra.
Prendiamo come esempio il nostro numero binario 00000001. il ciclo for di sDisegnoFreccia si avvia e con i=0 avvia il primo controllo di sFrecciaEsistente:

Codice: Seleziona tutto

return (1 >> 0) & 1;
//Quindi:
return (00000001 >> 0) & 1;
//In questo caso shiftiamo di 0 posizioni i vari bit del nostro numero binario verso destra. In questo caso l'1 rimane al suo posto.
//Quindi:
return (1) & 1;
//Lo script restituisce 1, cioè vero. Nella prima direzione (est) è presente la freccia, e quindi va disegnata.
Successivamente con i=1:

Codice: Seleziona tutto

return (1 >> 1) & 1;
//Quindi:
return (00000001 >> 1) & 1;
//In questo caso shiftiamo di 0 posizioni i vari bit del nostro numero binario verso destra. In questo caso l'1 rimane al suo posto.
//Quindi:
return (0) & 1;
//Lo script restituisce 0, cioè falso. Nella seconda direzione (nord-est) non è presente la freccia, e quindi non va disegnata.
E così via fino alla fine del ciclo delle 8 direzioni.

Andiamo quindi ad inserire il nostro script sDisegnoFreccia all'interno dell'evento Draw del nostro oggettooPersonaggio:
Draw:

Codice: Seleziona tutto

draw_self();
sDisegnoFreccia();
Ricapitolando:
oPersonaggio
Create:

Codice: Seleziona tutto

direzioni = 1;
Draw:

Codice: Seleziona tutto

draw_self();
sDisegnoFreccia();
sDisegnoFreccia

Codice: Seleziona tutto

var i;

for(i=0; i<8; i++) {
   if(sFrecciaEsistente(direzioni,i)) {
      draw_sprite(sFrecce,i,0,0);
   }
}
sFrecciaEsistente

Codice: Seleziona tutto

//Argument: direzioni, freccia

return (argument0 >> argument1) & 1;
Risultato:
Immagine

Vi basterà assegnare valori decimali alla variabile direzioni per poter disegnare sullo sprite del personaggio combinazioni di frecce differenti.
-Questi occhiali da sole le stanno benissimo. Vuole provarli con le lenti più scure?
- Si vede che le sto guardando le tette?
- Si
- Allora si

Avatar utente
Scario
Moderatore
Messaggi: 2707
Iscritto il: 26/05/2003, 20:29
Specialità: Tergiversare
Uso: GM:Studio 2
Contatta:

Re: Utilizzare numeri binari per verificare condizioni

Messaggio da Scario »

Ciao Vallo, ho appena letto il tuo tutorial (notando che purtroppo al momento il tag [math] del forum non funziona :( ). Una cosa non mi è chiara: perchè usare questo sistema invece del classico basato sulle direction? Per avere un cambio di direzione più veloce a livello di codice potendo usare lo shift?
Immagine

Avatar utente
Vallo92
GMI Advanced
Messaggi: 1508
Iscritto il: 15/07/2011, 20:26
Specialità: Grafico
Uso: GM:Studio 2
Contatta:

Re: Utilizzare numeri binari per verificare condizioni

Messaggio da Vallo92 »

Ho scritto questo tutorial basandomi su un sistema di disegno di sprite. Per muovere un oggetto non penso sia proprio il caso di usare questo sistema, visto che esistano le direction come hai detto tu.
-Questi occhiali da sole le stanno benissimo. Vuole provarli con le lenti più scure?
- Si vede che le sto guardando le tette?
- Si
- Allora si

Avatar utente
Scario
Moderatore
Messaggi: 2707
Iscritto il: 26/05/2003, 20:29
Specialità: Tergiversare
Uso: GM:Studio 2
Contatta:

Re: Utilizzare numeri binari per verificare condizioni

Messaggio da Scario »

Proponilo a Tizzio come Articolo ;)
Immagine

Rispondi

Chi c’è in linea

Visitano il forum: Nessuno e 8 ospiti