Organizazione
di un gioco
Come
detto prima il programmatore di videogiochi deve scrivere un codice efficiente.
Java fortunatamente è un linguaggio ad oggetti per cui possiamo
sfruttare al meglio questa caratteristica per realizzare i giochi in modo
funzionale.
Per
prima cosa dobbiamo introdurre il concetto di Sprite.
Sprite
: piccoli oggetti mobili che si trovano all’ interno dello scenario di
un videogame .
Dalla
definizione è evidente che i personaggi , gli spari del gioco sono
tutti degli spirte con caratteristiche diverse per ciasun tipo (esempio
Lo sprite del giocato sarà diverso da quello del nemico in quanto
avrà come proprietà un numero di vite ...) tutti
però avranno delle caratteristiche comuni come la posizione , la
dimensione e l’ immagine caratteristica.
Evidente
che all’ interno di un videogiocio ci sia una gerarchia di classi la cui
genitrice sarà la nostra classe Sprite generale da cui deriveremo
tutte le altre classi come riportato nello schema.
|
Figura
1: la classe Sprite genitrice delle altre classi . Notare come
dal generale si va al particolare (tecnica top-down) . Il concetto
è : IN UN GIOCO TUTTO E’ UNO SPRITE.
Preso
atto di cio andiamo ad implementare il tutto in Java .
import
java.awt.*;
public
class Sprite
{
private
Image i; //L’
immagine associata allo sprite
private int x; //La posizione fisica
dello sprite
private
int y;
private
int larghezza; //Le dimensioni dello sprite
private
int altezza;
/*
*
Costruttore dello Sprite
*
Gli passo l’ immagine dello sprite, la posizione e l’ altezza
*/
public
Sprite (Image i,int x,int y,int larghezza,int altezza)
{
this.x=x;
this.y=y;
this.i=i;
this.larghezza =larghezza;
this.altezza =altezza;
}
public
void setLarghezza(int i)
{
larghezza =i;
}
public
void setAltezza(int i)
{
altezza =i;
}
public
Image getImage() //Ritorna l’ immagine associata allo sprite
{
return i;
}
public
int getLarghezza()
{
return larghezza;
}
public
int getAltezza()
{
return altezza;
}
public
void setSize(int altezza,int larghezza)
{
this.larghezza =larghezza;
this.altezza =altezza;
}
...........
altri metodi set e get per le proprietà dell’ oggetto
}//~fine
classe sprite
Ora
ci manca un metodo importantissimo per terminare la classe : la collisione
tra sprite. Ipotiziamo un gioco tipo SpaceCommander dove una navicella
deve sparate a degli ufo , dobbiamo controllare che se i due oggetti si
scontrano la navicella e l’ ufo muore. Per fare cio abbiamo dobbiamo controllare
per ciascun vertice dello sprite se esso e all’ interno di un ‘ altro sprite.
In
questo esempio useremo 4 vertici perchè esso offre un risultato
abbastanza buono dato che usiamo delle immagini rettangolari .
Di
conseguenza lo sprite rettangolare risualta avere queste coordinate
(x,y)
(x+laghezza,y)
+-----------------------+
|
SPRITE |
+-----------------------+
(x,y+altezza)
(x+larghezza,y+altezza)
Preso
atto di ciò andiamo a costruirci le varie situazioni in vi sono
delle collisioni
|
Lo
sprite corrente (quello in esame) è entratto con l’ angolo superiore
sinistro nell’ altro sprite di conseguenza c’ è stata una collisione. |
|
Lo
Sprite Corrente è entrato in collisione con l’angolo superiore destro:
Collisione avvenuta
|
|
Collisione
con l’ angolo inferiore Sinistro
|
|
Collisione
con l’angolo inferiore destro |
Tabella
1:
schema riassuntivo delle varie collisioni possibili
Implementazione
in Java:
public
boolean isCollisione(Sprite s)
{
/*
* L’angolo superiore sinistro coppia (x,y) e conpreso nello sprite
*/
if (((this.x>= s.x) &&(this.x<=s.x+s.larghezza ))
&&
((this.y>= s.y) &&(this.y<=s.y+s.altezza ))) return true;
//angolo superiore destro
if (((x+larghezza>= s.x) &&(x+larghezza<=s.x+s.larghezza ))&&
((y>= s.y) &&(y<=s.y+s.altezza ))) return true;
//angolo inferiore sinistro
if (((x>= s.x) &&(x<=s.x+s.larghezza ))&&
((y+altezza>= s.y) &&(y+altezza<=s.y+s.altezza ))) return
true;
//angolo inferiore destro
if (((x+larghezza>= s.x) &&(x+larghezza<=s.x+s.larghezza ))&&
((y+altezza>= s.y) &&(y+altezza<=s.y+s.altezza ))) return
true;
/*se non si sono verificate le condizioni sopra allora significa che
*non c’è stata collisione e quindi ritorno false
*/
return false;
}
Ora
la nostra classe generale è terminata se successivamente avremo
bisogno di avere un ‘ oggetto all’ interno del nostro gioco più
specifico basterà estenderla.
L’
utilità di questa gerarchia risulta utile durante il controllo delle
collisioni : esterndiamo 2 classi da Sprite Giocatore e Nemico
class
Giocatore extends Sprite
{
private int vite;
private int energia;
........
}
class
Nemico extends Sprite
{
private
int tipo;// esempio 1 = mostro 2= alieno 3 =ufo ..
........
}
Istanziamo
ora 2 oggetti uno per Nemico e uno per Giocatore
Giocatore
g=new Giocatore (.....);
Nemicio
n = new Nemicio(.....);
ora
effettuiamo il controllo delle collisioni in questo modo :
g.isCollisione(n);
questa
istruzione risulta valida in quanto anche se n è di tipo Nemico
prima di tutto è un oggetto Sprite .
Il Doppio Buffer
Se
qualcuno ha già provato a fare qualcosa di grafico tipo un testo
scorrevole , avrà sicuramente notato che se scriviamo e cancelliamo
continuamente un testo esso lampeggia o come molti dicono “fa lo sfargallio”
questo perchè scrivere nella memoria video direttamente è
lento. La soluzione che nel tempo si è andata affermandosi è
il cosidetto Doppio Buffer o double buffering la filofia di questo metodo
è :
creiamo
in memoria un buffer video virtuale e apportiamo a questo tutto quello
vorremmo fare sulla memoria video e alla fine copiamo tutto il buffer nella
memoria .
In
Java la sua implementazione è molto facile (a differenza di altri
linguaggi di programmazione quali c/c++, pascal...)e permette di eliminare
totalmente lo sfarfallio .
-
Per prima
cosa creiamo un oggetto Image vuoto che sarà il nostro buffer virtuale
-
Creiamo
un oggetto di tipo Graphics che è l’ oggetto grafico del buffer
virtuale
-
Usiamo
l’ oggetto Graphics per disegnare cancellare nel buffer virtuale
-
Copiamo
l’ oggetto Image nella memoria video
import
java.awt.*;
import
java.applet.*;
class
Prova extens Applet
{
Image buffervirtuale;
Graphics b_graph;
public void init()
{
......
//creo un’ immagine vuota della grandezza di tutto l’ applet
buffervirtuale= createImage(this.getSize().width ,this.getSize().height);
// prendo l’ oggetto Graphics del buffer per porter apportare modifiche
// al buffer
b_graph=buffervirtuale.getGraphics();
b_graph.drawString(10,10,”ciao Mondo!”);
repaint(); //forzo l’ aggiornamento dell’ applet
}
public void paint(Graphics g)
{
update(g); //uso update perchè aggiorno tutto l’ applet
}
public void update(Graphics g)
{
//disegno tutto quello che c’ è nel buffervirtuale e così
elimino lo sfarfallio
g.drawImage(0,0,buffervirtuale);
}
}//~
Fine class Prova
Conclusione
È
possibile realizzare mediante Java videogiochi di qualsiasi tipo (o quasi
) implementando soluzioni e algoritmi sempre più efficienti dato
che il linguaggio offre queste opportunità ma l’ arma che non dobbiamo
trascurare è la nostra fantasia.
|