Vogliamo svilluppare una semplice applicazione nella quale un sfera (MovingBall) si muove all'interno di un rettangolo e rimbalza quando raggiunge una parete del rettangolo.
Si può poi estendere l'esempio ad una array di MovingBalls indipendenti.
Il penultimo metodo, invocato a seguito di utilizzo di mouse, può essere usato per 'raccogliere' tutte le sfere prima di rilasciarle per movimenti random indipendenti.


import java.awt.*;


/*
 * Una sfera, oggetto di tipo MovingBall, contiene le informazioni
 * colore, raggio, posizione, velocità (speed), e direzione di movimento.
 * La sfera si può muovere solo in un rettangolo. La sfera si può ‘disegnare’
 * e si muove quando così ordinato.
 */

public class MovingBall  {
 

   private double x,y;      // posizione corrente della sfera ball.

   private double xmin, xmax;  // Limiti orizzontali, con xmin <= x <= xmax.
                              
   private double ymin, ymax;  // Limiti verticali, con ymin <= y <= ymax.
  
   private double dx,dy;    // Rappresenta la velocità.  Quando travel()  
                            // viene invocato, la sfera si sposta di
                            // dx pixels in orizontale e dy in verticale
  
   private Color color;     // colore della sfera

   private double radius;   // raggio della sfera


  
/*
    * Il costruttore crea una sfera che si può muovere entro limiti specificati,
    * left <= x <= right e top <= y <= bottom.   
    * La sfera è inizialmente posizionata al centro del rettangolo.   
    * La velocità è casuale tra 4 e 12 e direzione casuale.  Il raggio è 5
    * ed il colore rosso.
   
*/
   public MovingBall(double left, double right, double top, double bottom) {
      xmin = left;
      xmax = right;
      ymin = top;
      ymax = bottom;
      x = (xmin + xmax) / 2;
      y = (ymin + ymax) / 2;
      radius = 5;
      color = Color.red;
      double angle = 2 * Math.PI * Math.random();  // direzione Random.
      double speed = 4 + 8*Math.random();          // velocità Random.
      dx = Math.cos(angle) * speed;
      dy = Math.sin(angle) * speed;
   }
  

   /**
    * Il seguente metodo disegna la sfera nel contesto graphico g.   
    * Il colore di disegno in g è cambiato al ‘color’ della sfera.
   
*
    */
   public void draw(Graphics g) {
      g.setColor(color);
      g.fillOval( (int)(x-radius), (int)(y-radius), (int)(2*radius), (int)(2*radius) );
   }
  

   /*
    * Due metodi, uno generico per muovere la sfera per una unità di tempo.   
    * Notare: la sfera non si muove se una delle dimensioni del rettangolo
    * è inferiore al diametro della sfera.
   
*/
   public void travel() {
      travel(1.0);
   }
  
  
   /**
    * Il metodo successivo, usato dal precedente, specifica il numero di
    * unità di tempo.  
   
*/
   public void travel(double time) {
         
      /* non succeed nulla se il rettangolo è troppo piccolo. */
         
      if (xmax - xmin < 2*radius || ymax - ymin < 2*radius)
         return;

      /* Poi, se la sfera non è più nel rettangolo, si riposiziona
         (questo può succedere solo se il rettangolo è stato modificato
         chiamando il metodo setLimits(), o se la posizione della sfera  
         è cambiata a seguito dell’invocazione del metodo setLocation() )
     
*/
     
      if (x-radius < xmin)
         
x = xmin + radius;
     
else if (x+radius > xmax)
         x = xmax - radius;
      if (y - radius < ymin)
         y = ymin + radius;
      else if (y + radius > ymax)
         y = ymax - radius;
        
      /* calcola ‘per ora’ la nuova posizione, forse fuori del rettangolo */
        
     
double newx = x + dx*time;
      double newy = y + dy*time;
     
      /* se la nuova posizione è al di là di uno dei lati del rettangolo,
         "rifletti" il nuovo punto attraverso il lato del rettangolo */
     
     
if (newy < ymin + radius) {
         newy = 2*(ymin+radius) - newy;
         dy = Math.abs(dy);
      }
      else if (newy > ymax - radius) {
         newy = 2*(ymax-radius) - newy;
         dy = -Math.abs(dy);
      }
      if (newx < xmin + radius) {
         newx = 2*(xmin+radius) - newx;
         dx = Math.abs(dx);
      }
      else if (newx > xmax - radius) {
         newx = 2*(xmax-radius) - newx;
         dx = -Math.abs(dx);
      }
     
      /* ora abbiamo la nuova posizione della sfera */
     
     
x = newx;
      y = newy;
     
   } // end travel()
  
  
   /**
    * possiamo stabilire il colore della sfera.
   
*/
   public void setColor(Color c) {
      if (c != null)
         color = c;
   }
  

   /**
    * possiamo fissare il raggio della sfera (ma il diametro deve   
    * essere almeno di 1 pixel).
   
*/
   public void setRadius(int r) {
      radius = r;
      if (radius < 0.5)
         radius = 0.5;
   }
  

   /**
    * possiamo scegliere i limiti orizzontale e verticale per il movimento.
   
*/
   public void setLimits(double left, double right, double top, double bottom) {
      xmin = left;
      xmax = right;
      ymin = top;
      ymax = bottom;
   }
  

   /**
    * possiamo fissare la posizione della sfera.
   
*/
   public void setLocation(double x, double y) {
      this.x = x;
      this.y = y;
   }
  

   /*
    * con il seguente metodo, possiamo scegliere la velocità della sfera,
    * che deve essere positiva.   
   
*/
   public void setSpeed(double speed) {
      if (speed > 0) {
          double currentSpeed = Math.sqrt(dx*dx + dy*dy);
          dx = dx * speed / currentSpeed;
          dy = dy * speed / currentSpeed;
      }
   }
  

   /**
    * possiamo modificare la direzione di movimento della sfera per farla
    * dirigere verso il punto (a,b).  Se la sfera è già in quel punto, il
    * metodo non è definito, e non si fa nulle.
   
*/
   public void headTowards(int a, int b) {
      double vx = a - x;
      double vy = b - y;
      double dist = Math.sqrt(vx*vx + vy*vy);
      if (dist > 0) {
         double speed = Math.sqrt(dx*dx + dy*dy);
         dx = vx / dist * speed;
         dy = vy / dist * speed;
      }
   }
  

   /**
    * possiamo scegliere velocità e direzione del movimento.
    * uno tra dx e dy deve essere non-zero (o la sfera non si muove).
   
*/
   public void setVelocity(double dx, double dy) {
      if (dx != 0 || dy != 0) {
         this.dx = dx;
         this.dy = dy;
      }
   }
  

}  // fine class MovingBall