MokaByte Numero 40  - Aprile 2000
 
Programmare 
giochi in Java
di 
Filippo De Vecchi
Una breve descrizione sulla realizzazione di 
giochi usando il linguaggio JAVA

Creare un video games può essere considerata una ricerca di algoritmi sempre più elaborati ed efficienti  per rendere l’ esecuzione del programma fluida e veloce.  Oggi i video giochi non sono più progettati e realizzati da un singolo programmatore,come avveniva qualche tempo fa ,  ma bensì da un ‘ equipe questo per suddividere i compiti e quindi ciascun programmatore può dedicarsi pienamente nel settore assegnatogli.
Nonostante tutto, è sempre utile per chi incomincia a programmare giochi (e non ) scrivere da solo un programmata  per  farsi (come si dice in gergo ) “ le ossa ”.

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 .
 

  1. Per prima cosa creiamo un oggetto Image vuoto che sarà il nostro buffer virtuale  
  2. Creiamo un oggetto di tipo Graphics che è l’ oggetto grafico del buffer virtuale
  3. Usiamo l’ oggetto Graphics per disegnare cancellare nel buffer virtuale
  4. 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.
 
 

Chi volesse mettersi in contatto con la redazione può farlo scrivendo a mokainfo@mokabyte.it