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