import java.awt.*; import java.applet.Applet; public class otto extends Applet implements Runnable { /* Dimensioni previste dell'applet */ private final int MAXX = 240; private final int MAXY = 240; /* Dimensioni della pallina */ private final int DIMX = 24; private final int DIMY = 24; private final int STEP = 10; /* Singolo movimento in pixel pallina verde*/ private final int RSTEP = 20; /* Singolo movimento in pixel pallina rossa*/ /* Costanti per la direzione del movimento */ private final int E = 0; private final int S = 1; private final int N = 2; private final int W = 3; /* Coordinate correnti della pallina verde */ private int x = MAXX / 3; private int y = 0; /* Variabile di stato: direzione corrente pallina verde */ private int dir = E; /* Coordinate correnti della pallina rossa */ private int xr = 0; private int yr = MAXY / 2; /* Variabile di stato: direzione corrente pallina rossa */ private int dirr = E; /* Array delle velocita' delle due palline */ private int speed [] = { STEP, RSTEP}; private Image dot = null; /* La pallina verde */ private Image rdot = null; /* La pallina rossa */ private volatile boolean sem1 = false; /* Semaforo di sinistra */ private volatile boolean sem2 = false; /* Semaforo di desrtra */ Thread avanza = null; /* Thread della pallina verde */ Thread ravanza = null; /* Thread della pallina rossa */ /* Init deve solamente lanciare il caricamento delle palline */ public void init () { dot = getImage(getCodeBase(), "lista.gif"); rdot = getImage(getCodeBase(), "listarossa.gif"); } /* Deve far partire l'animazione */ public void start() { /* Thread della pallina verde */ if (avanza == null) { // Se il thread non esiste ancora avanza = new Thread(this, "lista"); // Lo crea avanza.start(); // E lo fa partire } /* Thread della pallina rossa */ if (ravanza == null) { // Se il thread non esiste ancora ravanza = new Thread(this, "listarossa"); // Lo crea ravanza.start(); // E lo fa partire } } /* Movimento pallina verde */ private synchronized void ballMove () { switch (dir) { // A seconda dllo stato (la direzione corrente) case E : // Verso Est x += STEP; // Aumenta la X if (x >= (2 * MAXX) / 3) { // Se arriva al bordo destro dir = S; // Cambia direzione (va a Sud) } break; case S : // Verso Sud y += STEP; // Aumenta la Y /* Gestione dell'incorcio destro e del semaforo destro */ if (y >= (MAXY / 2) - DIMY && y < (MAXY / 2) - DIMY + STEP) { // Entra nella zona di scontro if (sem2) { // Se il semaforo destro e' rosso try { wait (); // (attende sull'applett) Attende il verde } catch (Exception e) { } } sem2 = true; // Accende il semaforo destro } else if (y >= (MAXY / 2) + DIMY && y < (MAXY / 2) + DIMY + STEP) { // Esce dalla zona di scontro sem2 = false; // Spegne il semaforo destro notifyAll (); // Sblocca i thread in attesa su quel semaforo } if (y >= (2 * MAXY) / 3) { // Se arriva al bordo inferiore dir = W; // Cambia direzione (va a Ovest) } break; case W : // Verso Ovest x -= STEP; // Cala la X if (x <= MAXX / 3) { // Se arriva al bordo sinistro dir = N; // Cambia direzione (va a Nord) } break; case N : // Verso Nord y -= STEP; // Cala la Y /* Gestione dell'incorcio sinistro e del semaforo sinistro */ if (y >= (MAXY / 2) + DIMY && y < (MAXY / 2) + DIMY + STEP) { // Entra nella zona di scontro if (sem1) { // Se il semaforo sinistro e' rosso try { wait (); // (attende sull'applett) Attende il verde } catch (Exception e) { } } sem1 = true; // Accende il semaforo sinistro } else if (y >= (MAXY / 2) - DIMY && y < (MAXY / 2) - DIMY + STEP) { // Esce dalla zona di scontro sem1 = false; // Spegne il semaforo sinistro notifyAll (); // Sblocca i thread in attesa su quel semaforo } if (y <= 0) { // Se arriva al bordo superiore dir = E; // Cambia direzione (va di nuovo a Est) } break; }; } /* Movimento pallina verde */ private synchronized void rballMove () { switch (dirr) { case E : // Verso Est xr += RSTEP; // Aumenta la X /* Gestione dell'incorcio sinistro e del semaforo sinistro */ if (xr >= (MAXX / 3) - DIMX && xr < (MAXX / 3) - DIMX + RSTEP) { // Entra nella zona di scontro if (sem1) { // Se il semaforo sinistro e' rosso try { wait (); // (attende sull'applett) Attende il verde } catch (Exception e) { } } sem1 = true; // Accende il semaforo sinistro } else if (xr >= (MAXX / 3) + DIMX && xr < (MAXX / 3) + DIMX + RSTEP) { // Esce dalla zona di scontro sem1 = false; // Spegne il semaforo sinistro notifyAll (); // Sblocca i thread in attesa su quel semaforo } /* Gestione dell'incorcio destro e del semaforo destro */ if (xr >= (2 * MAXX / 3) - DIMX && xr < (2 * MAXX / 3) - DIMX + RSTEP) { // Entra nella zona di scontro if (sem2) { // Se il semaforo destro e' rosso try { wait (); // (attende sull'applett) Attende il verde } catch (Exception e) { } } sem2 = true; // Accende il semaforo destro } else if (xr >= (2 * MAXX / 3) + DIMX && xr < (2 * MAXX / 3) + DIMX + RSTEP) { // Esce dalla zona di scontro sem2 = false; // Spegne il semaforo destro notifyAll (); // Sblocca i thread in attesa su quel semaforo } if (xr >= MAXX) { // Se arriva al bordo inferiore dirr = S; // Cambia direzione (va a Sud) } break; case S : // Verso Sud yr += RSTEP; // Aumenta la Y if (yr >= MAXY) { // Se arriva al bordo inferiore dirr = W; // Cambia direzione (va a Ovest) } break; case W : // Verso Ovest xr -= RSTEP; // Cala la X if (xr <= 0) { // Se arriva al bordo sinistro dirr = N; // Cambia direzione (va a Nord) } break; case N : // Verso Nord yr -= RSTEP; // Cala la Y if (yr <= MAXY / 2) { // Se arriva al bordo superiore dirr = E; // Cambia direzione (va di nuovo a Est) } break; }; } /* Metodo che esegue il 'lavoro duro' - azione */ public void run() { // Questo metodo viene invocato per ogni thread dell'Applet, quindi deve // eseguire il lavoro solo nel caso il thread sia quello dell'animazione, // uno o l'altro if (Thread.currentThread() == avanza) { // Thread pallina verde // Il loop termina quando l'attributo avanza viene messo a null in stop() while (avanza!= null) { ballMove (); // Movimento pallina verde - gestisce semaforo repaint(); // Ridisegna il cmapo try { Thread.sleep(100); // Attende 100 mS } catch (InterruptedException e){ // Nessuna azione } } } else if (Thread.currentThread() == ravanza) { // Il loop termina quando l'attributo ravanza viene messo a null in stop() while (ravanza!= null) { rballMove (); // Movimento pallina rossa - gestisce semaforo repaint(); // Ridisegna il cmapo try { Thread.sleep(100); // Attende 100 mS } catch (InterruptedException e){ // Nessuna azione } } } } /* Se usciamo dalla pagina, elimina il thread */ public void stop() { avanza = null; // se 'avanza' diventa 'null', il metodo 'run' (istanza pallina verde) termina ravanza = null; // se 'avanza' diventa 'null', il metodo 'run' (istanza pallina rossa) termina } /* Funzione di disegno che semplicemente disegna le palline alle coordinate fissate ed i semafori */ synchronized public void paint(Graphics g) { g.drawImage (dot, x, y, this); // Pallina verde g.drawImage (rdot, xr, yr, this); // Pallina rossa g.setColor ((sem1) ? Color.red : Color.green); // Colore semaforo sinistro g.fillRect (MAXX/3 - 20, MAXY / 2 - 20 , 10 , 10); // Semaforo sinistro g.setColor ((sem2) ? Color.red : Color.green); // Colore semaforo destro g.fillRect (2*MAXX/3 + 10 + DIMX, MAXY / 2 - 20 , 10 , 10);// Semaforo destro } }