esercizio 1
In questa applet é presente un bottone che comanda l'animazione permettendo di fermarla e di farla ripartire. L'uso di un solo bottone richiede di mantenere coerente il messaggio visualizzato sullo stesso e una gestione degli eventi che consideri lo stato.
É utile notare l'astrazione apportata nel concetto di canvas
animabile che estende una canvas
bufferizzata. Queste classi nascondono le usuali tecniche utilizzate per ottenere una animazione fluida. La classe BallCanvas deve implementare i metodi
doAnimation e
bufferedPaint senza occuparsi di altro.
Queste classi verranno usate in futuro per nascondere queste laboriose tecniche e per concentrare l'attenzione solo sulle classi in esame.
package corsoDrZito.lez4.es1;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class esercizio1 extends Applet
{
public esercizio1()
{
// allocate an array of bouncing balls
balls = new Ball[15];
// ACTHUNG!!! pass only an array reference without any single allocation still!!! Java Rulez! ^_^
bc = new BallCanvas(balls);
}
public void init()
{
// GUI
createGUI(this);
// now can allocate some balls
for (int i=0; i<balls.length; i++)
balls[i] = new Ball(bc.size());
setBackground(new Color(48,64,96));
}
void createGUI(Container c)
{
c.setLayout(new BorderLayout());
toggle = new Button();
toggle.addActionListener(new BL());
c.add(toggle, BorderLayout.SOUTH );
c.add(bc, BorderLayout.CENTER);
c.validate(); // to get a valid ball canvas size
}
public void start()
{
bc.setAnimation(true);
toggle.setLabel("stop");
}
public void stop()
{
bc.setAnimation(false);
toggle.setLabel("start");
}
// inner class for listeners
class BL implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String s = e.getActionCommand();
if (s.equals("start"))
{
bc.setAnimation(true);
((Button)e.getSource()).setLabel("stop");
}
else
if (s.equals("stop"))
{
bc.setAnimation(false);
((Button)e.getSource()).setLabel("start");
}
else
throw new IllegalStateException();
}
}
Ball[] balls;
BallCanvas bc;
Button toggle;
}
package corsoDrZito.lez4.es1;
import java.awt.*;
public class Ball
{
public Ball(Dimension d)
{
x = (int)(Math.random() * d.width);
y = (int)(Math.random() * d.height);
x_increment = 1 + (int)(Math.random() * 4.);
y_increment = 1 + (int)(Math.random() * 4.);
r = 28 - x_increment * y_increment;
bounds = d;
}
public void paint(Graphics g)
{
g.fillOval(x, y, r, r);
}
public void move()
{
if(x + r >= bounds.width ) x_increment = -Math.abs(x_increment);
else
if(x < 0) x_increment = Math.abs(x_increment);
if(y + r >= bounds.height) y_increment = -Math.abs(y_increment);
else
if(y < 0) y_increment = Math.abs(y_increment);
x += x_increment;
y += y_increment;
}
private int x, y, r, x_increment, y_increment;
private Dimension bounds;
}
package corsoDrZito.lez4.es1;
import java.awt.*;
import java.awt.image.*;
public class BallCanvas extends AnimateCanvas
{
public BallCanvas(Ball[] b)
{
super(10L);
if(b==null) throw new NullPointerException();
balls = b;
}
protected synchronized void doAnimation()
{
for (int i=0; i<balls.length; i++) balls[i].move();
}
protected synchronized void bufferedPaint(Graphics g)
{
for (int i=0; i<balls.length; i++) balls[i].paint(g);
}
Ball[] balls;
}
package corsoDrZito.lez4.es1;
import java.awt.*;
import java.awt.image.*;
public abstract class AnimateCanvas extends BufferedCanvas implements Runnable
{
public AnimateCanvas()
{
super();
animation = new Thread(this);
animation.start();
}
public AnimateCanvas(long waitTimeInMillis)
{
this();
this.waitTimeInMillis = waitTimeInMillis;
}
public void run()
{
animation.setPriority(Thread.MAX_PRIORITY);
do
{
if(animate)
{
doAnimation();
repaint();
}
try
{
Thread.currentThread();
Thread.sleep(waitTimeInMillis);
}
catch(InterruptedException ex) {}
} while(animation!=null);
}
protected abstract void doAnimation();
public void setAnimation(boolean state)
{
animate = state;
}
static int times;
boolean animate; // don't animate before explicit setAnimation(true) method invocation!
long waitTimeInMillis = 20L;
Thread animation;
}
package corsoDrZito.lez4.es1;
import java.awt.*;
import java.awt.image.*;
public abstract class BufferedCanvas extends Canvas
{
public BufferedCanvas()
{
super();
}
public synchronized void update(Graphics g)
{
paint(g);
}
public synchronized void paint(Graphics g)
{
d = size();
if (image==null)
{
image = createImage(d.width, d.height);
bg = image.getGraphics();
}
bg.clearRect(0, 0, d.width, d.height);
bufferedPaint(bg);
g.drawImage(image, 0, 0, this);
}
public boolean isDoubleBuffered()
{
return true;
}
protected abstract void bufferedPaint(Graphics g);
Dimension d;
Graphics bg;
Image image;
}