package de.lmu.ifi.tcs; import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.util.ArrayList; import java.util.Random; /* Änderungen: * - Runnable interface für HuepfendeBaelle * - Neue Konstante maxFramerate & update-frequenz limitiert auf maxFramerate updates/sekunde * - Auslagerung der update & zeichen-schleife in run() * - Aufrufen von run() in neuem thread * * Hinzugefügte Methoden: run * Veränderte Methoden: main */ public class HuepfendeBaelle implements Runnable { private ArrayList baelle; private GraphicsWindow gw; // Parameter private final static int max_x = 640; private final static int max_y = 480; private final static int ballgroesse = 20; private final static int knopfgroesse = 40; private final static int maxFramerate = 30; /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { Point randpunkt = new Point(max_x-ballgroesse,max_y-ballgroesse); ArrayList baelle = new ArrayList(); Ball b = new Ball(randpunkt, new Point(50,60), 100,90, Color.MAGENTA); baelle.add(b); b = new Ball(randpunkt, new Point(200,100), -5,20, Color.ORANGE); baelle.add(b); b = new Ball(randpunkt, new Point(323,243), 10,-30, Color.GREEN); baelle.add(b); b = new Ball(randpunkt, new Point(23,43), -199,-200); GraphicsWindow gw = new GraphicsWindow(max_x,max_y); gw.setText("Bälle anklicken; blaue Leiste zum Beenden anklicken."); HuepfendeBaelle hb = new HuepfendeBaelle(baelle, gw); Thread draw = new Thread(hb); draw.start(); // Vearbeitung der Mouse-clicks. Point click = gw.mouseClick(); Random zufall = new Random(); while (click.x >= 0 && click.x <= max_x && click.y >= knopfgroesse && click.y <= max_y) { if (hb.treffer(click)) { gw.setText("Treffer! ("+ click.x + "," + click.y +")"); } else { gw.setText("Daneben! ("+ click.x + "," + click.y +")"); synchronized (hb) { b = new Ball(randpunkt, click, (zufall.nextDouble()-0.5)*200, (zufall.nextDouble()-0.5)*200); hb.plusBall(b); } } click = gw.mouseClick(); } draw.interrupt(); // gw.setText("Auf Wiedersehen!"); // gw.sleep(8000); System.exit(0); } public void run() { try { while(! Thread.interrupted()) { synchronized (this) { for (Ball ball : baelle) { ball.updatePosition(); } zeichneAlleBaelle(); } Thread.sleep(1000/maxFramerate); } } catch (InterruptedException e) {}; } /** * @param baelle * @param gw */ public HuepfendeBaelle(ArrayList baelle, GraphicsWindow gw) { this.baelle = baelle; this.gw = gw; } /* Zeichnet alle Baelle ins GraphicsWindow ein */ public void zeichneAlleBaelle() { gw.clear(); zeichneEnde(); for (Ball ball : baelle) { gw.setColor(ball.getFarbe()); zeichneBallBei(ball.holePosition()); } } /* Zeichnet einen Ball bei einer speziellen Position */ public void zeichneBallBei(Point p) { Shape ball = new Ellipse2D.Double(p.getX(), p.getY(), ballgroesse, ballgroesse); gw.fill(ball); } /* Fügt einen weiteren Ball hinzu */ public void plusBall(Ball b) { this.baelle.add(b); } /* Prüft ab, ob sich an einer gegebenen Position ein Ball befindet * und wechselt ggf. dessen Farbe. */ public boolean treffer(Point schuss) { for (Ball ball : baelle) { Point bpos = ball.holePosition(); bpos.translate(ballgroesse/2, ballgroesse/2); if (schuss.distance(bpos) <= ballgroesse+5) { ball.wechsleFarbe(); return true; } } return false; } /* * Zeichnet einfach nur einen blauen Balken am oberen Fensterrand. */ public void zeichneEnde() { Rectangle ende = new Rectangle(0,0,max_x, knopfgroesse); gw.setColor(Color.BLUE); gw.fill(ende); } }