SlideShare uma empresa Scribd logo
1 de 12
Baixar para ler offline
Università degli Studi di Trento
                              Facoltà di Scienze MM.FF.NN
                           Corso di Laurea Specialistica in Informatica
                                        A.A. 2007­2008

               Relazione del progetto del corso di “Principi di Computer Grafica”, 
                         Prof. Raffaele De Amicis, Prof. Giuseppe Conti

                                    Massimo Santini  matr.130531

1 Introduzione

1.1 JOGLnoid
L'applicazione descritta in questa relazione, denominata simpaticamente “JOGLnoid”, corrisponde 
ad un clone del celebre videogioco arcade “Arkanoid”. JOGLnoid, infatti, è un semplice gioco in cui 
l'obiettivo principale dell'utente è quello di abbattere un determinato numero di mattoncini, posti 
all'interno di una scena bidimensionale, tramite l'uso di una sfera e di una piccola barra di gioco. La 
barra serve infatti a far rimbalzare la sfera di gioco contro i mattoncini, evitando che quest'ultima 
cada nella porzione di schermo sottostante alla barra stessa, causando così la perdita della partita.
Il gioco è stato sviluppato tramite l'ausilio della libreria grafica OpenGL, e premette all'utente di 
giocare partite composte da un massimo di 10 livelli, interagendo con l'applicazione tramite l'uso 
della tastiera del computer.


2 Componenti principali della finestra principale dell'applicazione

2.1 La schermata di gioco 
La finestra di gioco principale, di dimensione 1200x900 pixels,  si compone sostazialmente di due 
parti principali: sul pannello di sinistra troviamo la scena di gioco renderizzata tramite OpenGL, 
mentre sul pannello di destra è disponibile un'interfaccia utente necessaria per gestire e controllare il 
gioco.




                                 Figura 1: La schermata principale di JOGLnoid
2.1.1 L'interfaccia di controllo del gioco
L'interfaccia utente sulla sinistra della schermata di gioco, permette sostazialmente di effettuare 
tutte   quelle   operazioni   necessarie   all'avvio   di   una   parti.   Infatti,   tramite   una   serie   di   pulsanti 
etichettati e di menu a tendina, è possibile avviare una nuova partita, selezionandone il livello dal 
quale si vuole iniziare, oppure chiuderne a sua volta una già iniziata od, infine, chiudere l'intera 
applicazione.




                                        Figura 2: L'interfaccia di controllo del gioco

Sono inoltre presenti degli indicatori, necessari per visualizzare il punteggio corrente della partita, il 
numero di vite rimaste ed ovviamente il livello corrente gioco durante la partita.

2.1.2 La scena di gioco
La scena di gioco è visualizzata sulla sinistra della finestra principale, all'interno di un pannello di 
dimensioni   600x400 pixels ed è renderizzata tramite l'utilizzo della liberia  Jogl  (binding Java di 
OpenGL). Nella porzione superiore della scena vengono rappresentati i mattoncini da abbattere, 
colorati in maniera casuale, mentre nella parte inferiore sono presenti la sfera e la barra di gioco, 
entrambe colorate con tonalità di grigio. Inoltre il colore di queste componenti presenta  sfumature 
(shading) del colore sui vertici.


3 Giocare a JOGLnoid

3.1 Gestione di una partita a JOGLnoid
Una   partita   a   JOGLnoid   consiste   consiste   di   10   livelli   di   gioco   ognuno   dei   quali   presenta 
caratteristiche differenti. Tuttavia, l'utente non è obbligato ad iniziare necessariamente dall livello 1. 
Vi è infatti la possibilità di scegliere il livello iniziale, selezionando la voce corretta nel menù a 
tendina relativo ai livelli di gioco. Se tale scelta non viene effettuata si avvia di “default” una partita 
dal   livello   1.   Lo   scopo   del   gioco,   come   detto   precedentemente,   è   quello   di   abbattere   tutti   i 
mattoncini presenti nella scena, in modo da superare il livello e passare al successivo.
Ogni   livello   presenta   un   numero   di   mattoncini   differenti.   In   particolare,   il   numero   totale   dei 
mattoncini corrisponde a 160, e ad ogni livello ne vengono disegnati esclusivamente un numero pari 
alla percentuale asseganta al livello in questione. Ciò significa che, ad esempio, se si vuole superare 
il primo livello sarà necessario abbattere un numero di mattoncini pari al 10% del totale (ovvero 16); 
il superamento del secondo invece necessiterà l'abbattimento del 20% del totale e cosi' via, fino al 
livello 10, il quale conterrà il 100% dei mattoncini, ovvero in numero pari al totale possibile (160).
L'abbattimento di un mattoncino comporta un bonus sul punteggio totale di 10 punti. 
Di seguito è mostrato il metodo init_grid(int n_lines, int level)appartenente alla 
classe GLRenderer, ovvero il metodo che si occupa di riempire la scena di gioco con il numero 
adeguato di mattoncini.

        /***
         * Inizializza la griglia da abbattere
         * @param n_lines numero delle linee di mattoncini che compongono la scena 
         * da abbattere
         */
        private void init_grid(int n_lines, int level) {

                 box Box;
                 int num_mattoncini;
                 int num_mattoncini_left;
                 double index;

                 //il numero totale dei mattoncini da abbattere per livello
                 num_mattoncini = ((20*8)*(level*10)/100);

                 // numero box per linea
                 int numBxL = (int)(4.0f / 0.50f);

                 STACK_BOX.clear();

                 for (int i=1; i<=n_lines; i++) {
                       for (int j=1; j<=numBxL;j++) {
                             Box = new box((0.50f*j)­2.25f,((float)­i*(0.10f))+2.05f);
                             STACK_BOX.addElement(Box);
                             num_boxes++;
                       }
                 }

                 //calcolo il num di mattoncini da levare
                 num_mattoncini_left = 160 ­ num_mattoncini;

                 for (int k=0; k < num_mattoncini_left; k++) {
                       index =(double) Math.random() * (STACK_BOX.size()­1);
                       index = Math.round(index);
                       STACK_BOX.removeElementAt((int)index);
                       num_boxes = num_boxes ­ 1;
                 }

        }



È inoltre possibile che un mattoncino abbattuto contenga una specie di sorpresa, ovvero ciò che nel 
gioco   originale   è   chiamato   “power­up”.   Questi  power­up,  non   sono   altro   che   degli   oggetti   che 
precipitano verso il settore inferiore dell'area di gioco e che vengono eliminati non appaena escono 
da quest'ultima. Se uno di questi oggetto viene intercettato tramite la sbarra di gioco, allora il gioco 
subisce   alcune   variazioni   che   possono   rivelarsi   in   alcuni   casi   favorevoli   oppure   sfavorevoli 
all'utente. I power­up possono essere di cinque tipi diversi, a seconda del colore assegnatogli:

    ●   Rosso: Allarga le dimensioni della barra di gioco, facilitando l'intercettazione della sfera;
    ●   Verde: Restringe le dimensioni della barra di gioco, rendendo l'intercettazione della sfera 
               più difficile. Rallenta la velocità della sfera di gioco;
●   Blu: Aumenta la velocità della sfera;
    ●   Nero: Riempie nuovamente la scena di gioco con un numero di mattoncini pari a quelli  
               assegnati al livello corrente;
    ●   Viola: Trasforma la sfera di gioco in una “super­sfera”, in grado di abbattere i mattoncini 
               senza provocare collisioni;

Infine, l'abbattimento di tutti i mattoncini, consente il passaggio al livello successivo.
Ad ogni partita vengono assegnate un numero di vite pari a tre. Ovviamente, quando la sfera di 
gioco finisce nella zona sottostante la barra di gioco, la partita viene fermata e ciò comporta la 
perdita di una vita. L'esaurimento di tutte le vite disponibili comporta la fine della partita corrente.

3.2 L'interazione tramite la tastiera
Lo   strumento   principale   di   interazione   con   JOGLnoid   è   ovviamente   la   tastiera   del   computer. 
Sostanzialmente i tasti necessari al gioco possono essere divisi in due categorie: quelli relativi al 
controllo della barra di gioco e quelli relativi all'orientamento della telecamera virtuale.

3.2.1 Tasti per il controllo del gioco
I tasti utilizzati per muovere la barra di gioco sono esclusivamente due efanno parte del tastierino 
direzionale:

    ●   RIGHT_KEY (  ) : Sposta la barra verso destra;
    ●   LEFT_KEY   (  ) : Sposta la barra verso sinsitra;

A questi due tasti va inoltre aggiunta la barra spaziatrice, la quale permette di avviare la partita, 
ogni qualvolta questa viene fermata.

    ●   SPACEBAR  : Lancia la pallina;

3.2.2 Tasti per il controllo della telecamera virtuale
I tasti in questione permettono di muovere la telecamera virtuale in maniera da poter vedere il gioco 
da  punti di  vista differenti. Oltre a ciò, è possibile ruotare la scena di gioco in senso orario  e 
antioratio tramite l'utilizzo del mouse, ovvero tenendo premuto il tasto sinistro e trascinando verso 
destra o verso sinistra.
Tra i tasti di controllo della telecamera virtuale vi sono:
    ● D_KEY              : Ruota la telecamera verso destra;
    ● A_KEY              : Ruota la telecamera verso sinistra;
    ● S_KEY              : Sposta la telecamera indietro;
    ● W_KEY              : Sposta la telecamera in avanti;
    ● Q_KEY              : Sposta la telecamera in alto;
    ● E_KEY              : Sposta la telecamera in basso;
    ● PAG_UP             : Ruota la telecamera verso l'alto;
    ● PAG_DOWN : Ruota la telecamera verso il basso.




4 Le componenti principali di JOGLnoid

La struttua di JOGLnoid è sostanzialmente organizzata in packages (pacchetti). Ad ognuno di questi 
è assegnato un compito ben preciso ed ogni package contiene le classi necessarie per il suo scopo.
I package di maggiore interesse sono senz'altro gt.events, physics, math, game.components, texture, 
texture.loader, custom.events e render.
Di seguito verrà proposta una descrizione degli aspetti principali di tali pacchetti.

4.1 Il package gt.events
Il   package   gt.events   contiene   le   classi   statiche  GameStatus,  KeyNavigator  e 
MovementStatus. 
Le ultime due classi citate si occupano esclusivamente di gestire la mappatura dei controlli della 
tastiera.   Il   loro   scopo   è   quindi   unicamente   quello   di   interfacciare   la   tastiera   del   computer   con 
l'applicazione JOGLnoid.
La classe   GameStatus  riveste, invece, un ruolo maggiormente interessante, in quanto le sue 
variabli   statiche   si   occupano   di   memorizzare   lo   stato   corrente   del   gioco.   Tutto   ciò   è   utile   dal 
momento che, gestendo i vari eventi che accadono durante la partita, questa classe permette sempre 
di sapere qual'è lo stato corrente della partita che si sta giocando. Tra queste caratteristiche figurano, 
ad esempio, il numero di vite rimaste, il livello corrente, il punteggio corrente ecc... 
Di seguito viene mostrata l'implementazione di tale classe.

package gt.events;

/***
 * Classe GameStatus, costituisce un listener che permette ad ApplicationStarter
 * di conoscere lo stato del gioco in GLRenderer
 * @author Massimo Santini 130531
 *
 */
public class GameStatus {

         public static int num_lives = 3;
         public static int current_level = 1;
         public static int game_score = 0;
         public static boolean new_game = false;
         public static boolean reset = false;
         public static boolean game_is_working = true;
         public static boolean setLevelBoxes = false;
         public static boolean collision_wall_sound = false;
         public static boolean collision_box_sound = false;
         public static boolean collision_bar_sound = false;

}

4.2 I package texture e texture.loder
Questi due package contengono classi dedite esclusivamente alla gestione ed al caricamento delle 
texture del gioco. Per un maggiore approfondimento si rimanda al codice sorgente dell'applicazione.

4.3 Il package custom.events
JOGLnoid implementa un meccanismo di “design pattern” che permette alla classe  GLRenderer 
di generare un evento personalizzato ogni qual'volta accade qualcosa nella scena di gioco. Tale 
evento   è   implementato   dalla   classe  RenderEvent,   appartenente   a   questo   package,  e   viene 
intercettato   dalla   classe   che   gestisce   l'interfaccia   utente.   Tutto   ciò   permette   all'interfaccia   di 
controllo di essere sempre aggiornata sullo stato corrente del gioco, in maniera da poter poi settare i 
valori corretti nei suoi indicatori, come ad esempio il punteggio corrente oppure il numero delle vite 
rimaste. L'evento personalizzato   RenderEvent contiene alcune proprietà  quali, in particolare, 
punteggio  e  lives,   che   vengono   istanziate   al   momento   della   creazione   dell'oggetto   evento.   In 
particolare oggetti di questo tipo vengono creati ogni qualvolta accade nella scena di gioco qualcosa 
tipo l'abbattimento di un mattoncino, una collisione, un'intercettazione di un power­up, ecc...
Di seguito viene presentata l'implementazione della classe  RenderEvent.

package custom.events;
import java.util.EventObject;
public class RenderEvent extends EventObject {

         int punteggio;
         int lives;
         boolean wall_sound = false;
         boolean box_sound = false;
         boolean bar_sound = false;

      public RenderEvent(Object source, int points, int lives_left, boolean 
w_sound, boolean b_sound, boolean br_sound) {
            super(source);
            // TODO Auto­generated constructor stub
            punteggio = points;
            lives = lives_left;
            wall_sound = w_sound;
            box_sound = b_sound;
            bar_sound = br_sound; 
      }

         public int getPoints() {
               return punteggio;
         }

         public int getLivesLeft() {
               return lives;
         }

         public boolean getWall_sound() {
               return wall_sound;
         }
         public boolean getBox_sound() {
               return box_sound;
         }

         public boolean getBar_sound() {
               return bar_sound;
         }
}

4.4 Il package game.components
Il   package   game.components   include   tutte   quelle   classi   che   permettono   di   creare   le   varie 
componenti   grafiche   del   gioco,   quali   la   sfera,   la   barra   di   gioco,   i   power­up   e   i   mattoncini   da 
abbattere. Ognuna delle precedenti componenti è implementata rispettivamente dalle classi Ngon, 
bar, box e surprise.
In   particolare   ognuno   di   queste   classi   implementa   il   metodo  draw(GLAutoDrawable 
gLDrawable),il   quale   permette   di   disegnare   l'oggetto   in   questione   all'interno   della   scena   di 
gioco. Di particolare interesse è la classe che implementa la sfera di gioco, descritta nel paragrafo 
4.4.1. Infine è necessario sottolineare che ognuna delle componenti descritte fino ad ora presenta 
alcune   proprietà   particolari,   chiamate  bound_box[]:   queste   proprietà   permettono   di   definire 
quella regione relativa all'oggetto da disegnare, detta bounding box, la quale risulta necessaria per la 
gestione delle collisioni tra gli oggetti stessi. 

4.4.1 La classe Ngon
La   classe  Ngon  implementa   la   sfera   di   gioco.   Tale   sfera   viene   implementata   disegnando   una 
particolare primitiva geometrica, ovvero un poligono di dimensione n, che viene poi fatto ruotare di 
360°     lungo   l'asse  y.    In   questa   maniera   è   possibile   ottenere   un'approssimazione   di   una   sfera 
abbastanza precisa. Tale precisione dipende ovviamente dal numero di lati che possiede il poligono 
ed in questa applicazione si è scelto di utilizzare un decagono (poligono di 10 dimensioni). Nelle 
prossime righe è mostrata la procedura si occupa della creazione della sfera di gioco.

for (int j=0; j<=360.0f; j++) {
                  gl.glRotatef(j, 0.0f, 1.0f, 0.0f);
                  gl.glBegin(GL.GL_POLYGON);
                  for (int i=0; i<=size; i++) {
                        if (red) {
                              gl.glColor3f(1.0f, 0.0f, 0.0f);
                        }
                        else {
                              gl.glColor3f(0.6f,0.6f,0.6f);
                        }

gl.glVertex2d(radius*(Math.cos(angle_inc*i)),radius*(Math.sin(angle_inc*i)));
                  }
                  gl.glEnd();
                  j++;
            }      

4.5 Il package physics
Il package  physics  contiene un'unica classe, nominata  collision. Tale classe si occupa della 
gestione delle collisioni fra gli oggetti della scena. 
Una collisione viene rilevata sostanzialmente quando la bounding box   della sfera di gioco “entra” 
letteralmente nella bounding box dell'oggetto con cui sta per collidere.
In particolare, la classe collision implementa otto diversi metodi, ognuno dei quali è preposto 
ad individuare un particolare tipo di collisione. Questi metodi sono:

    ●   isCollidingWithSXWall(Ngon ball)
        Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione 
        sinistra dell'area di gioco;

    ●   isCollidingWithDXWall(Ngon ball)
        Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione 
        destra dell'area di gioco;

    ●   isCollidingWithUpperWall(Ngon ball)
        Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione 
        superiore dell'area di gioco;

    ●   isCollidingWithGameBar(Ngon ball, bar gameBar)
        Questo metodo si occupa di rilevare le collisioni della sfera con la barra di gioco;

    ●   isCollidingWithBoxRight(Ngon ball, box mattoncino)
        Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in 
        cui la sfera lo colpisca sul suo lato destro;

    ●   isCollidingWithBoxLeft(Ngon ball, box mattoncino)
        Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in 
        cui la sfera lo colpisca sul suo lato sinistro;

    ●   isCollidingWithBoxUp(Ngon ball, box mattoncino)
Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in 
         cui la sfera lo colpisca sul suo lato superiore;

    ●    isCollidingWithBoxDown(Ngon ball, box mattoncino)
         Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in 
         cui la sfera lo colpisca sul suo lato inferiore;

Ognuno   dei   metodi   visti   sopra   ritorna   un   valore   di   tipo   booleano   il   quale   determina,   in   caso 
affermativo, l'avvenuta collisione con l'oggetto in questione. 
Per quanto riguarda le collisioni della sfera con le delimitazioni dell'area di gioco, la condizione che 
determina l'avvenuta collisione è determinata da un controllo sulle coordinate della   bounding box 
della   sfera;   di   fatto,   non   appena   tali   coordinate   oltrepassano   i   valori   delle   coordinate   delle 
delimitazioni, viene rilevato un urto con una di quest'ultime e si procede ad inserire sullo stack la 
matrice di riflessione relativa al tipo di urto, in maniera da modificare adeguatamente la traiettoria 
della sfera durante il gioco. Le seguenti righe di codice, ad esempio, mostrano come viene gestita 
un'ipotetica collisione con la delimitazione superiore della scena di gioco.

      /***
       * Controlla se avviene una collisione con la delimitazione superiore
       * dell'area di gioco
       * @param ball pallina del gioco
       * @return true or false valore di ritorno (vero o falso)
       */
      public static boolean isCollidingWithUpperWall(Ngon ball) {
            // La sfera di gioco collide con la delimitazione superiore 
dell'area di gioco
            if (ball.bound_box[3] >= 2.0f) {
                  //System.out.println("collisione soffitto");
                  return(true);
                  }
            else {
                  return(false);
            }
      }

Le   collisioni   con   i   mattoncini   invece,   vengono   trattate   in   modo   simile,   anche   se   sono   stati 
introddotti alcuni controlli necessari, soprattutto per identificare con quale lato del mattoncino si sta 
collidendo. Sostanzialmente l'idea fondamentale consiste nel verificare quale dei lati della bounding 
box della sfera sta “letteralmente” entrando all'interno dell'area del mattoncino in questione. Una 
volta determinato quale lato della bounding box della sfera sta per collidere, si procede ad inserire 
sullo   stack   la   matrice   di   riflessione   associata   a   quel   particolare   tipo   di   urto,   modificando 
opportunamente la traiettoria della sfera.
Inoltre, viene introdotto un'ulteriore controllo che assicuri che la sfera stia per collidere con un 
particolare mattoncino e non con altri, posti nella scena di gioco, le cui coordinate delle bounding 
boxes potrebbero potenzialmente rendere valida la condizione di controllo sulla collisione. Questo 
impedisce che, ad esempio, nel caso di una collisione sul lato sinistro di un mattoncino, vengano 
eliminati tutti quei mattoncini che si trovano più a sinistra del mattoncino in questione. Di seguito è 
riportato un'esempio di gestione di un urto con il lato sinistro di un mattoncino del gioco.

         /***
          * Controlla se avviene una collisione con il lato sinistro di un 
          * mattoncino
          * @param ball pallina del gioco
          * @param mattoncino mattoncino su cui viene valutata la collisione
          * @return true or false valore di ritorno (vero o falso)
          */
public static boolean isCollidingWithBoxLeft(Ngon ball, box mattoncino) {

                  if (
                           (ball.bound_box[1]>=mattoncino.bound_box[0])&
                           (ball.bound_box[1]<mattoncino.bound_box[1])&


((ball.getY()<mattoncino.bound_box[3])&(ball.getY()>mattoncino.bound_box[2]))
                  )

                  {
                           System.out.println("isCollidingWithBoxLeft");
                           return(true);
                  }
                  else  {
                        return(false);
                  }
         }




4.6 Il package math
Il package  math  contiene due  classi che permettono l'utilizzo, dal punto di vista matematico di 
matrici numeriche. In particolare queste ultime servono per la gestione di tutte quelle matrici che 
permettono a JOGLnoid di muovere tutte le sue componenti grafiche. Fanno parte di questo package 
le classi matrix e matrixOperations. La prima classe implementa la struttura di una matrice 
numerica di dimensione 4x4, con in aggiunta alcuni metodi di servizio che, ad esempio, permettono 
di modificare valori in determinate posizioni della matrice oppure di trasformare quest'ultima in una 
matrice identità.
La classe  matrixOperations, invece, si occupa esclusivamente, di calcolare il prodotto fra due 
matrici.

4.7 Il package render
Quest'ultimo package costituisce il motore grafico vero e proprio di JOGLnoid. Infatti contiene la 
classe GLRenderer, il cui unico scopo è quello di disegnare gli oggetti nella scena di gioco.
La scena di gioco è disegnata all'interno di un frustum ottenuto da un volume di vista creato con 
un'angolo   di   apertura   di   45°,     dove   il  front   clipping   plane  e   il  far   clipping   plane  posti 
rispettivamente a distanza di 1 unità e 800 unità dall'origine del volume di vista.
Questa   classe   presenta   molteplici   aspetti   interessanti;   tra   questi   è   tuttavia   utile   soffermarsi   sul 
metodo display(GLAutoDrawable gLDrawable), nel quale vi risiedono tutte le istruzioni 
per il disegno degli oggetti nella scena. 
Per quanto riguarda il movimento della sfera, questo avviene scaricando utilizzando uno stack sul 
quale vengono caricate in maniera opportuna le matrici di traslazione o di riflessione. Il movimento 
è quindi dato da una serie di trasformazioni affini che permettono di disegnare la sfera nelle sue 
coordinate corrette. Infatti, ogni qual volta è necessario traslare la sfera, si procede all'inserimento 
sullo stack di una matrice di traslazione, con i relativi valori settati opportunamente. Analogamente 
un   urto   comporta   la   riflessione   della   traiettoria   della   sfera,   e   ciò   viene   effettuato   inserendovi 
un'apposita  matrice di riflessione. Ovviamente questi inserimenti sono condizionati dai risultati 
delle operazioni di rilevamento delle collisioni, le quali determinano la traiettoria che la sfera di 
gioco deve seguire.
Le righe di codice che seguono mostrano ad esempio, la fase di controllo di una possibile collisione 
della sfera con la delimitazione superiore di un mattoncino. In caso affermativo, la corrsipondente 
matrice di riflessione viene caricata sullo stack.
//      Check delle collisioni con i mattoncini
                     for (int j=0;j<STACK_BOX.size();j++) {
                           tmp_box = STACK_BOX.get(j);
                           xsorp = tmp_box.getX();
                           ysorp = tmp_box.getY();

                              if (collision.isCollidingWithBoxDown(ball, tmp_box)) {
                                    if (tmp_box.surprise == 1.0f) {
                                          creasorpresa(xsorp, ysorp);
                                    }
                                    YReflectionMatrix.setIdentity();
                                    YReflectionMatrix.setIndex(1, 1, ­1.0f);
                                    if (collision_srp) {
                                          STACK_MATRIX.addElement(YReflectionMatrix);
                                    }
                                    GameStatus.collision_box_sound = true;
                                    GameStatus.game_score = GameStatus.game_score + 10;
                                    fireRenderEvent();
                                    STACK_BOX.remove(j);
                              }

Al momento del disegno vero e proprio, tale stack viene scaricato e moltiplicando la matrice di 
trasformazione corrente con quella in cima allo stack, siamo in grado di ottenere la matrice che 
determinerà le coordinate in cui la sfera dovrà essere disegnata. Di seguito è mostrata la procedura 
che si occupa di tale attività.

      //svuoto lo stack e disegno la pallina
            for (int k=0; k<STACK_MATRIX.size(); k++) {
                  tmp = STACK_MATRIX.get(k);
                  currentMatrix = 
matrixOperations.multiplyMatrix(currentMatrix,tmp);
                  ball.setX(currentMatrix.getValue(0, 2));
                  ball.setY(currentMatrix.getValue(1, 2));
                  ball.draw(gLDrawable);
                  tmp.setIdentity();
            }

               if (game_started) {
                     STACK_MATRIX.clear();
               }

Inoltre una serie di  flag  booleane permette di controllare il flusso attraverso il codice durante il 
disegno dei frames, a seconda che ci si trovi in una situazione in cui il gioco è fermo o viceversa.
Un'altro aspetto interessante di questa classe è rappresentato dalle righe che seguono:

       /***
        * Permette il firing di eventi dalla classe GLRenderer
        *
        */
       protected synchronized void fireRenderEvent() {

            RenderEvent evt = new RenderEvent(this, GameStatus.game_score, 
GameStatus.num_lives, GameStatus.collision_wall_sound, 
GameStatus.collision_box_sound, GameStatus.collision_bar_sound);
            Object[] listeners = RenderEventListeners.getListenerList();
            // loop through each listener and pass on the event if needed
            int numListeners = listeners.length;
            for (int i = 0; i<numListeners; i+=2) 
            {
                  if (listeners[i] == RenderEventListener.class) 
                  {
// pass the event to the listeners event dispatch method
                        ((RenderEventListener)listeners[i
+1]).RenderEventReceived(evt);
                  }            
            }
      }

Le  righe  precedenti implementano il metodo  fireRenderEvent(), ovvero quella possibilità 
descritta   precedentemente,   che   permette   alla   classe  GLRenderer  di   creare   un   evento 
personalizzato ogni qualvolta qualcosa accade nella scena di gioco.
Un'altro   aspetto   interessante   è   rappresentato   dalla   gestione   dei   cosiddetti  power­up   ,descritti 
precedentemente. La loro intercettazione è ovviamente un'altro tipo di collisione che deve essere 
gestito. Di seguito è mostrata la parte di codice dedita a tale operazione.

//   controllo   eventuali   collisioni   con   la   barra   o   la   necessita'   di   eliminare 
sorprese
                     if (((tmp_sorpresa.bound_box[2] <= 
­1.80f)&(tmp_sorpresa.bound_box[3] >= ­1.90f)) 
                                  && ((tmp_sorpresa.getX() <= gameBar.bound_box[1])
                                                 &(tmp_sorpresa.getX() >= 
gameBar.bound_box[0]))) {

                                 System.out.println(tmp_sorpresa.surprise_type);
                                 switch ((int)tmp_sorpresa.surprise_type) {
                                 case 0:
                                       //ricreo tutti i mattoncini da abbattere
                                       init_grid(num_lines, GameStatus.current_level);
                                       collision_srp = true;
                                       gameBar.setDefaultWidth();
                                       ball_speed_Y =  0.07f;
                                       ball.setColorGray();
                                       GameStatus.game_score = GameStatus.game_score + 
20;
                                       break;
                                 case 1:
                                       //allargo la barra
                                       collision_srp = true;
                                       gameBar.setWidth(0.40f);
                                       ball_speed_Y = 0.07f;
                                       ball.setColorGray();
                                       GameStatus.game_score = GameStatus.game_score + 1;
                                       break;
                                 case 2:
                                       //aumento la velocita'
                                       collision_srp = true;
                                       gameBar.setDefaultWidth();
                                       ball_speed_Y =  0.09f;
                                       ball.setColorGray();
                                       GameStatus.game_score = GameStatus.game_score + 3;
                                       break;
                                 case 3:
                                       //restringo la barra
                                       collision_srp = true;
                                       gameBar.setWidth(0.15f);
                                       ball_speed_Y = 0.05f;
                                       ball.setColorGray();
                                       GameStatus.game_score = GameStatus.game_score + 10;
                                       break;
                                 case 4:
                                       collision_srp = false;
                                       gameBar.setDefaultWidth();
                                       ball_speed_Y = 0.07f;
                                       ball.setColorRed();
GameStatus.game_score = GameStatus.game_score + 5;
                                      break;
                              }
                              fireRenderEvent();
                              STACK_SURPRISE.removeElementAt(d);
                       }
                       tmp_sorpresa.draw(gLDrawable);
               }

La condizione descritta nel primo if  determina se la sorpresa in questione debba essere disegnata 
oppure no, mentre il membro alla destra dell'operatore condizionale && rileva un'eventuale 
collisione del power­up con la barra di gioco . In caso affermativo di procede alla valutazione del 
tipo di sorpresa che è stato intercettato, modificando di conseguenza i relativi parametri con i valori 
assegnati al  power­up.


5 Note tecniche sullo sviluppo dell'applicazione JOGLnoid

JOGLnoid  è stato sviluppando in  JAVA, utilizzando l'ambiente di sviluppo Eclipse, ed il binding 
OpenGL per JAVA, denominato Jogl. L'intera applicazione inoltre è stata creata su piattaforma i386, 
in ambiente GNU/Linux.

Mais conteúdo relacionado

Destaque

An integrated approach for designing and testing specific processors
An integrated approach for designing and testing specific processorsAn integrated approach for designing and testing specific processors
An integrated approach for designing and testing specific processorsVLSICS Design
 
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)ozlael ozlael
 
Deferred Rendering in Killzone 2
Deferred Rendering in Killzone 2Deferred Rendering in Killzone 2
Deferred Rendering in Killzone 2ozlael ozlael
 
Lect01 handout
Lect01 handoutLect01 handout
Lect01 handoutnomio0703
 
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...IDES Editor
 
Visual dictionary-902440435
Visual dictionary-902440435Visual dictionary-902440435
Visual dictionary-902440435902440435
 
ALIES presentation
ALIES presentationALIES presentation
ALIES presentationLourense Das
 
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...IOSR Journals
 
Counter mesaures aginst liquefaction induced settlemnt for ohl
Counter mesaures aginst liquefaction induced settlemnt for ohlCounter mesaures aginst liquefaction induced settlemnt for ohl
Counter mesaures aginst liquefaction induced settlemnt for ohlLahmeyer International, UAE
 
Presupuestos cronogramas de actividades
Presupuestos cronogramas de actividadesPresupuestos cronogramas de actividades
Presupuestos cronogramas de actividadesyeyis2945
 
Presentation Innovatys
Presentation InnovatysPresentation Innovatys
Presentation InnovatysTibet Demirel
 
Sunday School Lession 2009 06 21
Sunday  School  Lession 2009 06 21Sunday  School  Lession 2009 06 21
Sunday School Lession 2009 06 21fnuthalapaty
 
Trabajos dia infformatica
Trabajos dia infformaticaTrabajos dia infformatica
Trabajos dia infformaticaAnny Ortegon
 

Destaque (18)

An integrated approach for designing and testing specific processors
An integrated approach for designing and testing specific processorsAn integrated approach for designing and testing specific processors
An integrated approach for designing and testing specific processors
 
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)
Hable uncharted2(siggraph%202010%20 advanced%20realtime%20rendering%20course)
 
Inferred lighting
Inferred lightingInferred lighting
Inferred lighting
 
Deferred Rendering in Killzone 2
Deferred Rendering in Killzone 2Deferred Rendering in Killzone 2
Deferred Rendering in Killzone 2
 
Lect01 handout
Lect01 handoutLect01 handout
Lect01 handout
 
Jose fernando
Jose fernandoJose fernando
Jose fernando
 
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...
Hybrid Particle Swarm Optimization for Multi-objective Reactive Power Optimiz...
 
Visual dictionary-902440435
Visual dictionary-902440435Visual dictionary-902440435
Visual dictionary-902440435
 
Logfile
LogfileLogfile
Logfile
 
ALIES presentation
ALIES presentationALIES presentation
ALIES presentation
 
Xcp
XcpXcp
Xcp
 
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...
An Improved Phase Disposition Pulse Width Modulation (PDPWM) For a Modular Mu...
 
Counter mesaures aginst liquefaction induced settlemnt for ohl
Counter mesaures aginst liquefaction induced settlemnt for ohlCounter mesaures aginst liquefaction induced settlemnt for ohl
Counter mesaures aginst liquefaction induced settlemnt for ohl
 
Presupuestos cronogramas de actividades
Presupuestos cronogramas de actividadesPresupuestos cronogramas de actividades
Presupuestos cronogramas de actividades
 
Presentation Innovatys
Presentation InnovatysPresentation Innovatys
Presentation Innovatys
 
Sunday School Lession 2009 06 21
Sunday  School  Lession 2009 06 21Sunday  School  Lession 2009 06 21
Sunday School Lession 2009 06 21
 
Laura Beeth - Fairview Health Services
Laura Beeth - Fairview Health ServicesLaura Beeth - Fairview Health Services
Laura Beeth - Fairview Health Services
 
Trabajos dia infformatica
Trabajos dia infformaticaTrabajos dia infformatica
Trabajos dia infformatica
 

Mais de graphitech

A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationgraphitech
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationgraphitech
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationgraphitech
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationgraphitech
 
Rescue Mission
Rescue MissionRescue Mission
Rescue Missiongraphitech
 
Rescue Mission
Rescue MissionRescue Mission
Rescue Missiongraphitech
 
Mashup - Sustainability
Mashup - SustainabilityMashup - Sustainability
Mashup - Sustainabilitygraphitech
 
Mashup - Sustainability
Mashup - SustainabilityMashup - Sustainability
Mashup - Sustainabilitygraphitech
 
Multiple Screens
Multiple ScreensMultiple Screens
Multiple Screensgraphitech
 
Multiple Screens
Multiple ScreensMultiple Screens
Multiple Screensgraphitech
 
Graph Matching
Graph MatchingGraph Matching
Graph Matchinggraphitech
 
Shape Analysis
Shape AnalysisShape Analysis
Shape Analysisgraphitech
 
Human Interaction Library
Human Interaction LibraryHuman Interaction Library
Human Interaction Librarygraphitech
 
Human Interaction Library
Human Interaction LibraryHuman Interaction Library
Human Interaction Librarygraphitech
 
WebCams Mapping on Nasa World Wind
WebCams Mapping on Nasa World WindWebCams Mapping on Nasa World Wind
WebCams Mapping on Nasa World Windgraphitech
 
Street Builder
Street BuilderStreet Builder
Street Buildergraphitech
 
Street Builder
Street BuilderStreet Builder
Street Buildergraphitech
 
Live Video in World Wind
Live Video in World WindLive Video in World Wind
Live Video in World Windgraphitech
 
Live Video in World Wind
Live Video in World WindLive Video in World Wind
Live Video in World Windgraphitech
 
Terrain Modification
Terrain ModificationTerrain Modification
Terrain Modificationgraphitech
 

Mais de graphitech (20)

A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolation
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolation
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolation
 
A graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolationA graphic library and an application for simple curve manipolation
A graphic library and an application for simple curve manipolation
 
Rescue Mission
Rescue MissionRescue Mission
Rescue Mission
 
Rescue Mission
Rescue MissionRescue Mission
Rescue Mission
 
Mashup - Sustainability
Mashup - SustainabilityMashup - Sustainability
Mashup - Sustainability
 
Mashup - Sustainability
Mashup - SustainabilityMashup - Sustainability
Mashup - Sustainability
 
Multiple Screens
Multiple ScreensMultiple Screens
Multiple Screens
 
Multiple Screens
Multiple ScreensMultiple Screens
Multiple Screens
 
Graph Matching
Graph MatchingGraph Matching
Graph Matching
 
Shape Analysis
Shape AnalysisShape Analysis
Shape Analysis
 
Human Interaction Library
Human Interaction LibraryHuman Interaction Library
Human Interaction Library
 
Human Interaction Library
Human Interaction LibraryHuman Interaction Library
Human Interaction Library
 
WebCams Mapping on Nasa World Wind
WebCams Mapping on Nasa World WindWebCams Mapping on Nasa World Wind
WebCams Mapping on Nasa World Wind
 
Street Builder
Street BuilderStreet Builder
Street Builder
 
Street Builder
Street BuilderStreet Builder
Street Builder
 
Live Video in World Wind
Live Video in World WindLive Video in World Wind
Live Video in World Wind
 
Live Video in World Wind
Live Video in World WindLive Video in World Wind
Live Video in World Wind
 
Terrain Modification
Terrain ModificationTerrain Modification
Terrain Modification
 

Último

Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptx
Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptxLorenzo D'Emidio_Vita di Cristoforo Colombo.pptx
Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptxlorenzodemidio01
 
LE ALGHE.pptx ..........................
LE ALGHE.pptx ..........................LE ALGHE.pptx ..........................
LE ALGHE.pptx ..........................giorgiadeascaniis59
 
Tosone Christian_Steve Jobsaaaaaaaa.pptx
Tosone Christian_Steve Jobsaaaaaaaa.pptxTosone Christian_Steve Jobsaaaaaaaa.pptx
Tosone Christian_Steve Jobsaaaaaaaa.pptxlorenzodemidio01
 
case passive_GiorgiaDeAscaniis.pptx.....
case passive_GiorgiaDeAscaniis.pptx.....case passive_GiorgiaDeAscaniis.pptx.....
case passive_GiorgiaDeAscaniis.pptx.....giorgiadeascaniis59
 
Oppressi_oppressori.pptx................
Oppressi_oppressori.pptx................Oppressi_oppressori.pptx................
Oppressi_oppressori.pptx................giorgiadeascaniis59
 
Presentazioni Efficaci e lezioni di Educazione Civica
Presentazioni Efficaci e lezioni di Educazione CivicaPresentazioni Efficaci e lezioni di Educazione Civica
Presentazioni Efficaci e lezioni di Educazione CivicaSalvatore Cianciabella
 
Lorenzo D'Emidio_Vita e opere di Aristotele.pptx
Lorenzo D'Emidio_Vita e opere di Aristotele.pptxLorenzo D'Emidio_Vita e opere di Aristotele.pptx
Lorenzo D'Emidio_Vita e opere di Aristotele.pptxlorenzodemidio01
 
Descrizione Piccolo teorema di Talete.pptx
Descrizione Piccolo teorema di Talete.pptxDescrizione Piccolo teorema di Talete.pptx
Descrizione Piccolo teorema di Talete.pptxtecongo2007
 
Aristotele, vita e opere e fisica...pptx
Aristotele, vita e opere e fisica...pptxAristotele, vita e opere e fisica...pptx
Aristotele, vita e opere e fisica...pptxtecongo2007
 
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptx
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptxLorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptx
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptxlorenzodemidio01
 
Quadrilateri e isometrie studente di liceo
Quadrilateri e isometrie studente di liceoQuadrilateri e isometrie studente di liceo
Quadrilateri e isometrie studente di liceoyanmeng831
 
Scrittura seo e scrittura accessibile
Scrittura seo e scrittura accessibileScrittura seo e scrittura accessibile
Scrittura seo e scrittura accessibileNicola Rabbi
 
discorso generale sulla fisica e le discipline.pptx
discorso generale sulla fisica e le discipline.pptxdiscorso generale sulla fisica e le discipline.pptx
discorso generale sulla fisica e le discipline.pptxtecongo2007
 
Confronto tra Sparta e Atene classiche.ppt
Confronto tra Sparta e Atene classiche.pptConfronto tra Sparta e Atene classiche.ppt
Confronto tra Sparta e Atene classiche.pptcarlottagalassi
 
Lorenzo D'Emidio_Francesco Petrarca.pptx
Lorenzo D'Emidio_Francesco Petrarca.pptxLorenzo D'Emidio_Francesco Petrarca.pptx
Lorenzo D'Emidio_Francesco Petrarca.pptxlorenzodemidio01
 
Vuoi girare il mondo? educazione civica.
Vuoi girare il mondo? educazione civica.Vuoi girare il mondo? educazione civica.
Vuoi girare il mondo? educazione civica.camillaorlando17
 
descrizioni della antica civiltà dei sumeri.pptx
descrizioni della antica civiltà dei sumeri.pptxdescrizioni della antica civiltà dei sumeri.pptx
descrizioni della antica civiltà dei sumeri.pptxtecongo2007
 
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptx
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptxScienza Potere Puntoaaaaaaaaaaaaaaa.pptx
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptxlorenzodemidio01
 
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptx
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptxNicola pisano aaaaaaaaaaaaaaaaaa(1).pptx
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptxlorenzodemidio01
 

Último (19)

Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptx
Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptxLorenzo D'Emidio_Vita di Cristoforo Colombo.pptx
Lorenzo D'Emidio_Vita di Cristoforo Colombo.pptx
 
LE ALGHE.pptx ..........................
LE ALGHE.pptx ..........................LE ALGHE.pptx ..........................
LE ALGHE.pptx ..........................
 
Tosone Christian_Steve Jobsaaaaaaaa.pptx
Tosone Christian_Steve Jobsaaaaaaaa.pptxTosone Christian_Steve Jobsaaaaaaaa.pptx
Tosone Christian_Steve Jobsaaaaaaaa.pptx
 
case passive_GiorgiaDeAscaniis.pptx.....
case passive_GiorgiaDeAscaniis.pptx.....case passive_GiorgiaDeAscaniis.pptx.....
case passive_GiorgiaDeAscaniis.pptx.....
 
Oppressi_oppressori.pptx................
Oppressi_oppressori.pptx................Oppressi_oppressori.pptx................
Oppressi_oppressori.pptx................
 
Presentazioni Efficaci e lezioni di Educazione Civica
Presentazioni Efficaci e lezioni di Educazione CivicaPresentazioni Efficaci e lezioni di Educazione Civica
Presentazioni Efficaci e lezioni di Educazione Civica
 
Lorenzo D'Emidio_Vita e opere di Aristotele.pptx
Lorenzo D'Emidio_Vita e opere di Aristotele.pptxLorenzo D'Emidio_Vita e opere di Aristotele.pptx
Lorenzo D'Emidio_Vita e opere di Aristotele.pptx
 
Descrizione Piccolo teorema di Talete.pptx
Descrizione Piccolo teorema di Talete.pptxDescrizione Piccolo teorema di Talete.pptx
Descrizione Piccolo teorema di Talete.pptx
 
Aristotele, vita e opere e fisica...pptx
Aristotele, vita e opere e fisica...pptxAristotele, vita e opere e fisica...pptx
Aristotele, vita e opere e fisica...pptx
 
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptx
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptxLorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptx
Lorenzo D'Emidio- Lavoro sulla Bioarchittetura.pptx
 
Quadrilateri e isometrie studente di liceo
Quadrilateri e isometrie studente di liceoQuadrilateri e isometrie studente di liceo
Quadrilateri e isometrie studente di liceo
 
Scrittura seo e scrittura accessibile
Scrittura seo e scrittura accessibileScrittura seo e scrittura accessibile
Scrittura seo e scrittura accessibile
 
discorso generale sulla fisica e le discipline.pptx
discorso generale sulla fisica e le discipline.pptxdiscorso generale sulla fisica e le discipline.pptx
discorso generale sulla fisica e le discipline.pptx
 
Confronto tra Sparta e Atene classiche.ppt
Confronto tra Sparta e Atene classiche.pptConfronto tra Sparta e Atene classiche.ppt
Confronto tra Sparta e Atene classiche.ppt
 
Lorenzo D'Emidio_Francesco Petrarca.pptx
Lorenzo D'Emidio_Francesco Petrarca.pptxLorenzo D'Emidio_Francesco Petrarca.pptx
Lorenzo D'Emidio_Francesco Petrarca.pptx
 
Vuoi girare il mondo? educazione civica.
Vuoi girare il mondo? educazione civica.Vuoi girare il mondo? educazione civica.
Vuoi girare il mondo? educazione civica.
 
descrizioni della antica civiltà dei sumeri.pptx
descrizioni della antica civiltà dei sumeri.pptxdescrizioni della antica civiltà dei sumeri.pptx
descrizioni della antica civiltà dei sumeri.pptx
 
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptx
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptxScienza Potere Puntoaaaaaaaaaaaaaaa.pptx
Scienza Potere Puntoaaaaaaaaaaaaaaa.pptx
 
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptx
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptxNicola pisano aaaaaaaaaaaaaaaaaa(1).pptx
Nicola pisano aaaaaaaaaaaaaaaaaa(1).pptx
 

JOGLnoid

  • 1. Università degli Studi di Trento Facoltà di Scienze MM.FF.NN Corso di Laurea Specialistica in Informatica A.A. 2007­2008  Relazione del progetto del corso di “Principi di Computer Grafica”,  Prof. Raffaele De Amicis, Prof. Giuseppe Conti Massimo Santini  matr.130531 1 Introduzione 1.1 JOGLnoid L'applicazione descritta in questa relazione, denominata simpaticamente “JOGLnoid”, corrisponde  ad un clone del celebre videogioco arcade “Arkanoid”. JOGLnoid, infatti, è un semplice gioco in cui  l'obiettivo principale dell'utente è quello di abbattere un determinato numero di mattoncini, posti  all'interno di una scena bidimensionale, tramite l'uso di una sfera e di una piccola barra di gioco. La  barra serve infatti a far rimbalzare la sfera di gioco contro i mattoncini, evitando che quest'ultima  cada nella porzione di schermo sottostante alla barra stessa, causando così la perdita della partita. Il gioco è stato sviluppato tramite l'ausilio della libreria grafica OpenGL, e premette all'utente di  giocare partite composte da un massimo di 10 livelli, interagendo con l'applicazione tramite l'uso  della tastiera del computer. 2 Componenti principali della finestra principale dell'applicazione 2.1 La schermata di gioco  La finestra di gioco principale, di dimensione 1200x900 pixels,  si compone sostazialmente di due  parti principali: sul pannello di sinistra troviamo la scena di gioco renderizzata tramite OpenGL,  mentre sul pannello di destra è disponibile un'interfaccia utente necessaria per gestire e controllare il  gioco. Figura 1: La schermata principale di JOGLnoid
  • 2. 2.1.1 L'interfaccia di controllo del gioco L'interfaccia utente sulla sinistra della schermata di gioco, permette sostazialmente di effettuare  tutte   quelle   operazioni   necessarie   all'avvio   di   una   parti.   Infatti,   tramite   una   serie   di   pulsanti  etichettati e di menu a tendina, è possibile avviare una nuova partita, selezionandone il livello dal  quale si vuole iniziare, oppure chiuderne a sua volta una già iniziata od, infine, chiudere l'intera  applicazione. Figura 2: L'interfaccia di controllo del gioco Sono inoltre presenti degli indicatori, necessari per visualizzare il punteggio corrente della partita, il  numero di vite rimaste ed ovviamente il livello corrente gioco durante la partita. 2.1.2 La scena di gioco La scena di gioco è visualizzata sulla sinistra della finestra principale, all'interno di un pannello di  dimensioni   600x400 pixels ed è renderizzata tramite l'utilizzo della liberia  Jogl  (binding Java di  OpenGL). Nella porzione superiore della scena vengono rappresentati i mattoncini da abbattere,  colorati in maniera casuale, mentre nella parte inferiore sono presenti la sfera e la barra di gioco,  entrambe colorate con tonalità di grigio. Inoltre il colore di queste componenti presenta  sfumature  (shading) del colore sui vertici. 3 Giocare a JOGLnoid 3.1 Gestione di una partita a JOGLnoid Una   partita   a   JOGLnoid   consiste   consiste   di   10   livelli   di   gioco   ognuno   dei   quali   presenta  caratteristiche differenti. Tuttavia, l'utente non è obbligato ad iniziare necessariamente dall livello 1.  Vi è infatti la possibilità di scegliere il livello iniziale, selezionando la voce corretta nel menù a  tendina relativo ai livelli di gioco. Se tale scelta non viene effettuata si avvia di “default” una partita  dal   livello   1.   Lo   scopo   del   gioco,   come   detto   precedentemente,   è   quello   di   abbattere   tutti   i  mattoncini presenti nella scena, in modo da superare il livello e passare al successivo. Ogni   livello   presenta   un   numero   di   mattoncini   differenti.   In   particolare,   il   numero   totale   dei  mattoncini corrisponde a 160, e ad ogni livello ne vengono disegnati esclusivamente un numero pari  alla percentuale asseganta al livello in questione. Ciò significa che, ad esempio, se si vuole superare 
  • 3. il primo livello sarà necessario abbattere un numero di mattoncini pari al 10% del totale (ovvero 16);  il superamento del secondo invece necessiterà l'abbattimento del 20% del totale e cosi' via, fino al  livello 10, il quale conterrà il 100% dei mattoncini, ovvero in numero pari al totale possibile (160). L'abbattimento di un mattoncino comporta un bonus sul punteggio totale di 10 punti.  Di seguito è mostrato il metodo init_grid(int n_lines, int level)appartenente alla  classe GLRenderer, ovvero il metodo che si occupa di riempire la scena di gioco con il numero  adeguato di mattoncini. /***  * Inizializza la griglia da abbattere  * @param n_lines numero delle linee di mattoncini che compongono la scena   * da abbattere  */ private void init_grid(int n_lines, int level) { box Box; int num_mattoncini; int num_mattoncini_left; double index; //il numero totale dei mattoncini da abbattere per livello num_mattoncini = ((20*8)*(level*10)/100); // numero box per linea int numBxL = (int)(4.0f / 0.50f); STACK_BOX.clear(); for (int i=1; i<=n_lines; i++) { for (int j=1; j<=numBxL;j++) { Box = new box((0.50f*j)­2.25f,((float)­i*(0.10f))+2.05f); STACK_BOX.addElement(Box); num_boxes++; } } //calcolo il num di mattoncini da levare num_mattoncini_left = 160 ­ num_mattoncini; for (int k=0; k < num_mattoncini_left; k++) { index =(double) Math.random() * (STACK_BOX.size()­1); index = Math.round(index); STACK_BOX.removeElementAt((int)index); num_boxes = num_boxes ­ 1; } } È inoltre possibile che un mattoncino abbattuto contenga una specie di sorpresa, ovvero ciò che nel  gioco   originale   è   chiamato   “power­up”.   Questi  power­up,  non   sono   altro   che   degli   oggetti   che  precipitano verso il settore inferiore dell'area di gioco e che vengono eliminati non appaena escono  da quest'ultima. Se uno di questi oggetto viene intercettato tramite la sbarra di gioco, allora il gioco  subisce   alcune   variazioni   che   possono   rivelarsi   in   alcuni   casi   favorevoli   oppure   sfavorevoli  all'utente. I power­up possono essere di cinque tipi diversi, a seconda del colore assegnatogli: ● Rosso: Allarga le dimensioni della barra di gioco, facilitando l'intercettazione della sfera; ● Verde: Restringe le dimensioni della barra di gioco, rendendo l'intercettazione della sfera  più difficile. Rallenta la velocità della sfera di gioco;
  • 4. Blu: Aumenta la velocità della sfera; ● Nero: Riempie nuovamente la scena di gioco con un numero di mattoncini pari a quelli   assegnati al livello corrente; ● Viola: Trasforma la sfera di gioco in una “super­sfera”, in grado di abbattere i mattoncini  senza provocare collisioni; Infine, l'abbattimento di tutti i mattoncini, consente il passaggio al livello successivo. Ad ogni partita vengono assegnate un numero di vite pari a tre. Ovviamente, quando la sfera di  gioco finisce nella zona sottostante la barra di gioco, la partita viene fermata e ciò comporta la  perdita di una vita. L'esaurimento di tutte le vite disponibili comporta la fine della partita corrente. 3.2 L'interazione tramite la tastiera Lo   strumento   principale   di   interazione   con   JOGLnoid   è   ovviamente   la   tastiera   del   computer.  Sostanzialmente i tasti necessari al gioco possono essere divisi in due categorie: quelli relativi al  controllo della barra di gioco e quelli relativi all'orientamento della telecamera virtuale. 3.2.1 Tasti per il controllo del gioco I tasti utilizzati per muovere la barra di gioco sono esclusivamente due efanno parte del tastierino  direzionale: ● RIGHT_KEY (  ) : Sposta la barra verso destra; ● LEFT_KEY   (  ) : Sposta la barra verso sinsitra; A questi due tasti va inoltre aggiunta la barra spaziatrice, la quale permette di avviare la partita,  ogni qualvolta questa viene fermata. ● SPACEBAR  : Lancia la pallina; 3.2.2 Tasti per il controllo della telecamera virtuale I tasti in questione permettono di muovere la telecamera virtuale in maniera da poter vedere il gioco  da  punti di  vista differenti. Oltre a ciò, è possibile ruotare la scena di gioco in senso orario  e  antioratio tramite l'utilizzo del mouse, ovvero tenendo premuto il tasto sinistro e trascinando verso  destra o verso sinistra. Tra i tasti di controllo della telecamera virtuale vi sono: ● D_KEY  : Ruota la telecamera verso destra; ● A_KEY  : Ruota la telecamera verso sinistra; ● S_KEY  : Sposta la telecamera indietro; ● W_KEY : Sposta la telecamera in avanti; ● Q_KEY  : Sposta la telecamera in alto; ● E_KEY  : Sposta la telecamera in basso; ● PAG_UP  : Ruota la telecamera verso l'alto; ● PAG_DOWN : Ruota la telecamera verso il basso. 4 Le componenti principali di JOGLnoid La struttua di JOGLnoid è sostanzialmente organizzata in packages (pacchetti). Ad ognuno di questi  è assegnato un compito ben preciso ed ogni package contiene le classi necessarie per il suo scopo. I package di maggiore interesse sono senz'altro gt.events, physics, math, game.components, texture, 
  • 5. texture.loader, custom.events e render. Di seguito verrà proposta una descrizione degli aspetti principali di tali pacchetti. 4.1 Il package gt.events Il   package   gt.events   contiene   le   classi   statiche  GameStatus,  KeyNavigator  e  MovementStatus.  Le ultime due classi citate si occupano esclusivamente di gestire la mappatura dei controlli della  tastiera.   Il   loro   scopo   è   quindi   unicamente   quello   di   interfacciare   la   tastiera   del   computer   con  l'applicazione JOGLnoid. La classe   GameStatus  riveste, invece, un ruolo maggiormente interessante, in quanto le sue  variabli   statiche   si   occupano   di   memorizzare   lo   stato   corrente   del   gioco.   Tutto   ciò   è   utile   dal  momento che, gestendo i vari eventi che accadono durante la partita, questa classe permette sempre  di sapere qual'è lo stato corrente della partita che si sta giocando. Tra queste caratteristiche figurano,  ad esempio, il numero di vite rimaste, il livello corrente, il punteggio corrente ecc...  Di seguito viene mostrata l'implementazione di tale classe. package gt.events; /***  * Classe GameStatus, costituisce un listener che permette ad ApplicationStarter  * di conoscere lo stato del gioco in GLRenderer  * @author Massimo Santini 130531  *  */ public class GameStatus { public static int num_lives = 3; public static int current_level = 1; public static int game_score = 0; public static boolean new_game = false; public static boolean reset = false; public static boolean game_is_working = true; public static boolean setLevelBoxes = false; public static boolean collision_wall_sound = false; public static boolean collision_box_sound = false; public static boolean collision_bar_sound = false; } 4.2 I package texture e texture.loder Questi due package contengono classi dedite esclusivamente alla gestione ed al caricamento delle  texture del gioco. Per un maggiore approfondimento si rimanda al codice sorgente dell'applicazione. 4.3 Il package custom.events JOGLnoid implementa un meccanismo di “design pattern” che permette alla classe  GLRenderer  di generare un evento personalizzato ogni qual'volta accade qualcosa nella scena di gioco. Tale  evento   è   implementato   dalla   classe  RenderEvent,   appartenente   a   questo   package,  e   viene  intercettato   dalla   classe   che   gestisce   l'interfaccia   utente.   Tutto   ciò   permette   all'interfaccia   di  controllo di essere sempre aggiornata sullo stato corrente del gioco, in maniera da poter poi settare i  valori corretti nei suoi indicatori, come ad esempio il punteggio corrente oppure il numero delle vite  rimaste. L'evento personalizzato   RenderEvent contiene alcune proprietà  quali, in particolare,  punteggio  e  lives,   che   vengono   istanziate   al   momento   della   creazione   dell'oggetto   evento.   In  particolare oggetti di questo tipo vengono creati ogni qualvolta accade nella scena di gioco qualcosa  tipo l'abbattimento di un mattoncino, una collisione, un'intercettazione di un power­up, ecc...
  • 6. Di seguito viene presentata l'implementazione della classe  RenderEvent. package custom.events; import java.util.EventObject; public class RenderEvent extends EventObject { int punteggio; int lives; boolean wall_sound = false; boolean box_sound = false; boolean bar_sound = false; public RenderEvent(Object source, int points, int lives_left, boolean  w_sound, boolean b_sound, boolean br_sound) { super(source); // TODO Auto­generated constructor stub punteggio = points; lives = lives_left; wall_sound = w_sound; box_sound = b_sound; bar_sound = br_sound;  } public int getPoints() { return punteggio; } public int getLivesLeft() { return lives; } public boolean getWall_sound() { return wall_sound; } public boolean getBox_sound() { return box_sound; } public boolean getBar_sound() { return bar_sound; } } 4.4 Il package game.components Il   package   game.components   include   tutte   quelle   classi   che   permettono   di   creare   le   varie  componenti   grafiche   del   gioco,   quali   la   sfera,   la   barra   di   gioco,   i   power­up   e   i   mattoncini   da  abbattere. Ognuna delle precedenti componenti è implementata rispettivamente dalle classi Ngon,  bar, box e surprise. In   particolare   ognuno   di   queste   classi   implementa   il   metodo  draw(GLAutoDrawable  gLDrawable),il   quale   permette   di   disegnare   l'oggetto   in   questione   all'interno   della   scena   di  gioco. Di particolare interesse è la classe che implementa la sfera di gioco, descritta nel paragrafo  4.4.1. Infine è necessario sottolineare che ognuna delle componenti descritte fino ad ora presenta  alcune   proprietà   particolari,   chiamate  bound_box[]:   queste   proprietà   permettono   di   definire  quella regione relativa all'oggetto da disegnare, detta bounding box, la quale risulta necessaria per la  gestione delle collisioni tra gli oggetti stessi.  4.4.1 La classe Ngon La   classe  Ngon  implementa   la   sfera   di   gioco.   Tale   sfera   viene   implementata   disegnando   una  particolare primitiva geometrica, ovvero un poligono di dimensione n, che viene poi fatto ruotare di 
  • 7. 360°     lungo   l'asse  y.    In   questa   maniera   è   possibile   ottenere   un'approssimazione   di   una   sfera  abbastanza precisa. Tale precisione dipende ovviamente dal numero di lati che possiede il poligono  ed in questa applicazione si è scelto di utilizzare un decagono (poligono di 10 dimensioni). Nelle  prossime righe è mostrata la procedura si occupa della creazione della sfera di gioco. for (int j=0; j<=360.0f; j++) { gl.glRotatef(j, 0.0f, 1.0f, 0.0f); gl.glBegin(GL.GL_POLYGON); for (int i=0; i<=size; i++) { if (red) { gl.glColor3f(1.0f, 0.0f, 0.0f); } else { gl.glColor3f(0.6f,0.6f,0.6f); } gl.glVertex2d(radius*(Math.cos(angle_inc*i)),radius*(Math.sin(angle_inc*i))); } gl.glEnd(); j++; }   4.5 Il package physics Il package  physics  contiene un'unica classe, nominata  collision. Tale classe si occupa della  gestione delle collisioni fra gli oggetti della scena.  Una collisione viene rilevata sostanzialmente quando la bounding box   della sfera di gioco “entra”  letteralmente nella bounding box dell'oggetto con cui sta per collidere. In particolare, la classe collision implementa otto diversi metodi, ognuno dei quali è preposto  ad individuare un particolare tipo di collisione. Questi metodi sono: ● isCollidingWithSXWall(Ngon ball) Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione  sinistra dell'area di gioco; ● isCollidingWithDXWall(Ngon ball) Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione  destra dell'area di gioco; ● isCollidingWithUpperWall(Ngon ball) Questo metodo si occupa di rilevare eventuali collisioni della sfera con la delimitazione  superiore dell'area di gioco; ● isCollidingWithGameBar(Ngon ball, bar gameBar) Questo metodo si occupa di rilevare le collisioni della sfera con la barra di gioco; ● isCollidingWithBoxRight(Ngon ball, box mattoncino) Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in  cui la sfera lo colpisca sul suo lato destro; ● isCollidingWithBoxLeft(Ngon ball, box mattoncino) Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in  cui la sfera lo colpisca sul suo lato sinistro; ● isCollidingWithBoxUp(Ngon ball, box mattoncino)
  • 8. Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in  cui la sfera lo colpisca sul suo lato superiore; ● isCollidingWithBoxDown(Ngon ball, box mattoncino) Questo metodo si occupa di rilevare le collisioni della sfera con un mattoncino, nel caso in  cui la sfera lo colpisca sul suo lato inferiore; Ognuno   dei   metodi   visti   sopra   ritorna   un   valore   di   tipo   booleano   il   quale   determina,   in   caso  affermativo, l'avvenuta collisione con l'oggetto in questione.  Per quanto riguarda le collisioni della sfera con le delimitazioni dell'area di gioco, la condizione che  determina l'avvenuta collisione è determinata da un controllo sulle coordinate della   bounding box  della   sfera;   di   fatto,   non   appena   tali   coordinate   oltrepassano   i   valori   delle   coordinate   delle  delimitazioni, viene rilevato un urto con una di quest'ultime e si procede ad inserire sullo stack la  matrice di riflessione relativa al tipo di urto, in maniera da modificare adeguatamente la traiettoria  della sfera durante il gioco. Le seguenti righe di codice, ad esempio, mostrano come viene gestita  un'ipotetica collisione con la delimitazione superiore della scena di gioco. /***  * Controlla se avviene una collisione con la delimitazione superiore  * dell'area di gioco  * @param ball pallina del gioco  * @return true or false valore di ritorno (vero o falso)  */ public static boolean isCollidingWithUpperWall(Ngon ball) { // La sfera di gioco collide con la delimitazione superiore  dell'area di gioco if (ball.bound_box[3] >= 2.0f) { //System.out.println("collisione soffitto"); return(true); } else { return(false); } } Le   collisioni   con   i   mattoncini   invece,   vengono   trattate   in   modo   simile,   anche   se   sono   stati  introddotti alcuni controlli necessari, soprattutto per identificare con quale lato del mattoncino si sta  collidendo. Sostanzialmente l'idea fondamentale consiste nel verificare quale dei lati della bounding  box della sfera sta “letteralmente” entrando all'interno dell'area del mattoncino in questione. Una  volta determinato quale lato della bounding box della sfera sta per collidere, si procede ad inserire  sullo   stack   la   matrice   di   riflessione   associata   a   quel   particolare   tipo   di   urto,   modificando  opportunamente la traiettoria della sfera. Inoltre, viene introdotto un'ulteriore controllo che assicuri che la sfera stia per collidere con un  particolare mattoncino e non con altri, posti nella scena di gioco, le cui coordinate delle bounding  boxes potrebbero potenzialmente rendere valida la condizione di controllo sulla collisione. Questo  impedisce che, ad esempio, nel caso di una collisione sul lato sinistro di un mattoncino, vengano  eliminati tutti quei mattoncini che si trovano più a sinistra del mattoncino in questione. Di seguito è  riportato un'esempio di gestione di un urto con il lato sinistro di un mattoncino del gioco. /***  * Controlla se avviene una collisione con il lato sinistro di un   * mattoncino  * @param ball pallina del gioco  * @param mattoncino mattoncino su cui viene valutata la collisione  * @return true or false valore di ritorno (vero o falso)  */
  • 9. public static boolean isCollidingWithBoxLeft(Ngon ball, box mattoncino) { if ( (ball.bound_box[1]>=mattoncino.bound_box[0])& (ball.bound_box[1]<mattoncino.bound_box[1])& ((ball.getY()<mattoncino.bound_box[3])&(ball.getY()>mattoncino.bound_box[2])) ) { System.out.println("isCollidingWithBoxLeft"); return(true); } else  { return(false); } } 4.6 Il package math Il package  math  contiene due  classi che permettono l'utilizzo, dal punto di vista matematico di  matrici numeriche. In particolare queste ultime servono per la gestione di tutte quelle matrici che  permettono a JOGLnoid di muovere tutte le sue componenti grafiche. Fanno parte di questo package  le classi matrix e matrixOperations. La prima classe implementa la struttura di una matrice  numerica di dimensione 4x4, con in aggiunta alcuni metodi di servizio che, ad esempio, permettono  di modificare valori in determinate posizioni della matrice oppure di trasformare quest'ultima in una  matrice identità. La classe  matrixOperations, invece, si occupa esclusivamente, di calcolare il prodotto fra due  matrici. 4.7 Il package render Quest'ultimo package costituisce il motore grafico vero e proprio di JOGLnoid. Infatti contiene la  classe GLRenderer, il cui unico scopo è quello di disegnare gli oggetti nella scena di gioco. La scena di gioco è disegnata all'interno di un frustum ottenuto da un volume di vista creato con  un'angolo   di   apertura   di   45°,     dove   il  front   clipping   plane  e   il  far   clipping   plane  posti  rispettivamente a distanza di 1 unità e 800 unità dall'origine del volume di vista. Questa   classe   presenta   molteplici   aspetti   interessanti;   tra   questi   è   tuttavia   utile   soffermarsi   sul  metodo display(GLAutoDrawable gLDrawable), nel quale vi risiedono tutte le istruzioni  per il disegno degli oggetti nella scena.  Per quanto riguarda il movimento della sfera, questo avviene scaricando utilizzando uno stack sul  quale vengono caricate in maniera opportuna le matrici di traslazione o di riflessione. Il movimento  è quindi dato da una serie di trasformazioni affini che permettono di disegnare la sfera nelle sue  coordinate corrette. Infatti, ogni qual volta è necessario traslare la sfera, si procede all'inserimento  sullo stack di una matrice di traslazione, con i relativi valori settati opportunamente. Analogamente  un   urto   comporta   la   riflessione   della   traiettoria   della   sfera,   e   ciò   viene   effettuato   inserendovi  un'apposita  matrice di riflessione. Ovviamente questi inserimenti sono condizionati dai risultati  delle operazioni di rilevamento delle collisioni, le quali determinano la traiettoria che la sfera di  gioco deve seguire. Le righe di codice che seguono mostrano ad esempio, la fase di controllo di una possibile collisione  della sfera con la delimitazione superiore di un mattoncino. In caso affermativo, la corrsipondente  matrice di riflessione viene caricata sullo stack.
  • 10. // Check delle collisioni con i mattoncini for (int j=0;j<STACK_BOX.size();j++) { tmp_box = STACK_BOX.get(j); xsorp = tmp_box.getX(); ysorp = tmp_box.getY(); if (collision.isCollidingWithBoxDown(ball, tmp_box)) { if (tmp_box.surprise == 1.0f) { creasorpresa(xsorp, ysorp); } YReflectionMatrix.setIdentity(); YReflectionMatrix.setIndex(1, 1, ­1.0f); if (collision_srp) { STACK_MATRIX.addElement(YReflectionMatrix); } GameStatus.collision_box_sound = true; GameStatus.game_score = GameStatus.game_score + 10; fireRenderEvent(); STACK_BOX.remove(j); } Al momento del disegno vero e proprio, tale stack viene scaricato e moltiplicando la matrice di  trasformazione corrente con quella in cima allo stack, siamo in grado di ottenere la matrice che  determinerà le coordinate in cui la sfera dovrà essere disegnata. Di seguito è mostrata la procedura  che si occupa di tale attività. //svuoto lo stack e disegno la pallina for (int k=0; k<STACK_MATRIX.size(); k++) { tmp = STACK_MATRIX.get(k); currentMatrix =  matrixOperations.multiplyMatrix(currentMatrix,tmp); ball.setX(currentMatrix.getValue(0, 2)); ball.setY(currentMatrix.getValue(1, 2)); ball.draw(gLDrawable); tmp.setIdentity(); } if (game_started) { STACK_MATRIX.clear(); } Inoltre una serie di  flag  booleane permette di controllare il flusso attraverso il codice durante il  disegno dei frames, a seconda che ci si trovi in una situazione in cui il gioco è fermo o viceversa. Un'altro aspetto interessante di questa classe è rappresentato dalle righe che seguono: /***  * Permette il firing di eventi dalla classe GLRenderer  *  */ protected synchronized void fireRenderEvent() { RenderEvent evt = new RenderEvent(this, GameStatus.game_score,  GameStatus.num_lives, GameStatus.collision_wall_sound,  GameStatus.collision_box_sound, GameStatus.collision_bar_sound); Object[] listeners = RenderEventListeners.getListenerList(); // loop through each listener and pass on the event if needed int numListeners = listeners.length; for (int i = 0; i<numListeners; i+=2)  { if (listeners[i] == RenderEventListener.class)  {
  • 11. // pass the event to the listeners event dispatch method ((RenderEventListener)listeners[i +1]).RenderEventReceived(evt); }             } } Le  righe  precedenti implementano il metodo  fireRenderEvent(), ovvero quella possibilità  descritta   precedentemente,   che   permette   alla   classe  GLRenderer  di   creare   un   evento  personalizzato ogni qualvolta qualcosa accade nella scena di gioco. Un'altro   aspetto   interessante   è   rappresentato   dalla   gestione   dei   cosiddetti  power­up   ,descritti  precedentemente. La loro intercettazione è ovviamente un'altro tipo di collisione che deve essere  gestito. Di seguito è mostrata la parte di codice dedita a tale operazione. //   controllo   eventuali   collisioni   con   la   barra   o   la   necessita'   di   eliminare  sorprese if (((tmp_sorpresa.bound_box[2] <=  ­1.80f)&(tmp_sorpresa.bound_box[3] >= ­1.90f))  && ((tmp_sorpresa.getX() <= gameBar.bound_box[1]) &(tmp_sorpresa.getX() >=  gameBar.bound_box[0]))) { System.out.println(tmp_sorpresa.surprise_type); switch ((int)tmp_sorpresa.surprise_type) { case 0: //ricreo tutti i mattoncini da abbattere init_grid(num_lines, GameStatus.current_level); collision_srp = true; gameBar.setDefaultWidth(); ball_speed_Y =  0.07f; ball.setColorGray(); GameStatus.game_score = GameStatus.game_score +  20; break; case 1: //allargo la barra collision_srp = true; gameBar.setWidth(0.40f); ball_speed_Y = 0.07f; ball.setColorGray(); GameStatus.game_score = GameStatus.game_score + 1; break; case 2: //aumento la velocita' collision_srp = true; gameBar.setDefaultWidth(); ball_speed_Y =  0.09f; ball.setColorGray(); GameStatus.game_score = GameStatus.game_score + 3; break; case 3: //restringo la barra collision_srp = true; gameBar.setWidth(0.15f); ball_speed_Y = 0.05f; ball.setColorGray(); GameStatus.game_score = GameStatus.game_score + 10; break; case 4: collision_srp = false; gameBar.setDefaultWidth(); ball_speed_Y = 0.07f; ball.setColorRed();
  • 12. GameStatus.game_score = GameStatus.game_score + 5; break; } fireRenderEvent(); STACK_SURPRISE.removeElementAt(d); } tmp_sorpresa.draw(gLDrawable); } La condizione descritta nel primo if  determina se la sorpresa in questione debba essere disegnata  oppure no, mentre il membro alla destra dell'operatore condizionale && rileva un'eventuale  collisione del power­up con la barra di gioco . In caso affermativo di procede alla valutazione del  tipo di sorpresa che è stato intercettato, modificando di conseguenza i relativi parametri con i valori  assegnati al  power­up. 5 Note tecniche sullo sviluppo dell'applicazione JOGLnoid JOGLnoid  è stato sviluppando in  JAVA, utilizzando l'ambiente di sviluppo Eclipse, ed il binding  OpenGL per JAVA, denominato Jogl. L'intera applicazione inoltre è stata creata su piattaforma i386,  in ambiente GNU/Linux.