From 0e75e2f631e0cc025248913d426d650fcb722eab Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 19 Jan 2016 09:27:17 +0100 Subject: EiP 10.1 import --- ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/Ball.java | 79 ++++ .../10/1/de/lmu/ifi/tcs/GraphicsWindow.java | 421 +++++++++++++++++++++ .../10/1/de/lmu/ifi/tcs/HuepfendeBaelle.java | 129 +++++++ 3 files changed, 629 insertions(+) create mode 100644 ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/Ball.java create mode 100644 ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/GraphicsWindow.java create mode 100644 ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/HuepfendeBaelle.java (limited to 'ws2015/eip/blaetter/10/1/de/lmu') diff --git a/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/Ball.java b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/Ball.java new file mode 100644 index 0000000..83628a9 --- /dev/null +++ b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/Ball.java @@ -0,0 +1,79 @@ +package de.lmu.ifi.tcs; + +import java.awt.Color; +import java.awt.Point; + + +public class Ball { + + private Point randpunkt; + private double pos_x; + private double pos_y; + private double dx; + private double dy; + private long letztesupdate; + private Color farbe = Color.BLACK; + + public Ball(Point randpunkt, Point startpunkt, double dx, double dy, Color farbe) { + this.randpunkt = randpunkt; + this.pos_x = startpunkt.getX(); + this.pos_y = startpunkt.getY(); + this.dx = dx; + this.dy = dy; + this.letztesupdate = System.currentTimeMillis(); + this.farbe = farbe; + } + + public Ball(Point randpunkt, Point startpunkt, double dx, double dy) { + this(randpunkt, startpunkt, dx, dy, Color.BLACK); + } + + /** + * Aktualisiert die Position des Balls gemäß der vestrichenen Zeit. + */ + public void updatePosition() { + long aktuellezeit = System.currentTimeMillis(); + long verstrichen = aktuellezeit - letztesupdate; + pos_x += dx * verstrichen / 1000; + pos_y += dy * verstrichen / 1000; + letztesupdate = aktuellezeit; + if (pos_x<0 || pos_x>randpunkt.x) { + dx *= -1; + pos_x = (2*randpunkt.x - pos_x) % randpunkt.x; + } + if (pos_y<0 || pos_y>randpunkt.y) { + dy *= -1; + pos_y = (2*randpunkt.y - pos_y) % randpunkt.y; + } + } + + /** + * @return letzte Position des Balles + */ + public Point holePosition() { + return new Point((int) Math.round(pos_x), (int) Math.round(pos_y)); + } + + /** + * @return aktuelle Farbe des Balls + */ + public Color getFarbe() { + return farbe; + } + + /** + * Wechselt die Farbe des Balls + */ + public void wechsleFarbe() { + if (this.farbe.equals(Color.RED)) { + this.farbe = Color.GREEN; + } else if (this.farbe.equals(Color.GREEN)) { + this.farbe = Color.BLUE; + } else if (this.farbe.equals(Color.BLUE)) { + this.farbe = Color.ORANGE; + } else { + this.farbe = Color.RED; + } + + } +} diff --git a/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/GraphicsWindow.java b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/GraphicsWindow.java new file mode 100644 index 0000000..925005a --- /dev/null +++ b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/GraphicsWindow.java @@ -0,0 +1,421 @@ +package de.lmu.ifi.tcs; + +import java.awt.*; +import java.util.ArrayList; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.Timer; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.MouseEvent; +import java.awt.geom.RectangularShape; +import java.awt.geom.GeneralPath; + +/** + Eine Klasse zu pädagogischen Zwecken. + Erlaubt die Eingabe von Punktkoordinaten + mittels Mausklicks, das Zeichnen einfacher + 2D Objekte (java.awt.Shape), sowie die + Ausgabe von Texten in einer Statuszeile. + @version 3.043 + @author Martin Hofmann und die EiP-Teams verschiedener Jahre + */ + +public class GraphicsWindow { + + private int width; + private int height; + private JFrame dasFenster; + private static int fensterZahl; + private static int fensterNr; + private Label label; + private GraphicsWindowPanel panel; + private Point mousePos; + private Color activeColor = Color.BLACK; + final private Color backColor = Color.WHITE; + MyMouseAdapter mouseListener; + + /** + Erzeugt ein Fenster der Größe 640 auf 480 mit Textausgabe, Mauseingabe und Grafikausgabe. + */ + public GraphicsWindow() { + this(640, 480); + } + + /** + Erzeugt ein Fenster in vorgegebener Größe mit Textausgabe, Mauseingabe und Grafikausgabe. + @param width Breite des Fensters + @param height Höhe des Fensters + */ + public GraphicsWindow(int width, int height) { + this.width = width; + this.height = height; + dasFenster = new JFrame(); + dasFenster.setTitle("Grafikfenster " + ++fensterNr); + fensterZahl++; + dasFenster.setLocationByPlatform(true); + dasFenster.setSize(width,height+50); + dasFenster.getContentPane().setPreferredSize(new Dimension(width, height+50)); + dasFenster.pack(); + dasFenster.addWindowListener(new WindowAdapter(){ + public void windowClosing(WindowEvent e) { + dasFenster.dispose(); // nicht gleich alle Fenster abschiessen + if (--fensterZahl<1) System.exit(0); + } + }); + + label = new Label("Statuszeile..."); + label.setFont(new Font("Helvetica", Font.PLAIN, 12)); + dasFenster.getContentPane().add(label,"North" ); + panel = new GraphicsWindowPanel(); + //panel.setBackground(Color.cyan); + panel.addCommand(new SetColor(activeColor)); + dasFenster.getContentPane().add(panel,"Center"); + mousePos = new Point(); + mouseListener = new MyMouseAdapter(); + panel.addMouseListener(mouseListener); + clear(); + dasFenster.setVisible(true); + } + + /** + Gibt eine Zeichenkette oben im Fenster aus. + @param text diese Zeichenkette + */ + public void setText(String text) { + label.setText(text); + } + /** + Liest den oben im Fenster angezeigten Text aus. + @return den Text + */ + public String getText() { + return label.getText(); + } + /** + Wartet auf einen Mausklick. Die Methode blockiert das + aufrufende Programm solange bis der Mausklick erfolgt ist. + @return die Koordinaten des angeklickten Punkts + */ + + public Point mouseClick() { + try{ + synchronized(mouseListener){mouseListener.wait();} + } + catch(InterruptedException e){ + e.printStackTrace(); + } + return mousePos; + } + + class MyMouseAdapter extends MouseAdapter { + + /** + Beendet das Warten auf den Mausklick und verwertet die Koordinaten. + Diese Methode ist nicht für den Anwender bestimmt. + */ + + synchronized public void mouseClicked(MouseEvent e){ + mousePos = e.getPoint(); + notifyAll(); + } + } + + + /** + Schaltet die Zeichenfarbe auf die Hintergrundfarbe um. Dies ist + das Mittel, um gezeichnete Linien wieder zu löschen. + */ + public void switchToBackgroundColor(){ + activeColor = backColor; + panel.addCommand(new SwitchToBackgroundColor(activeColor)); + panel.repaint(); + } + + /** + Schaltet die Zeichenfarbe auf Schwarz um. + */ + public void switchToForegroundColor(){ + activeColor = Color.BLACK; + panel.addCommand(new SetColor(activeColor)); + panel.repaint(); + } + + + /** Liefert die aktuelle Zeichenfarbe. + @return die aktuelle Zeichenfarbe des GraphicsWindow. */ + public Color getColor() { + // return panel.getGraphics().getColor(); // getGraphics() has unpleasant side-effects. :( + /* Fixed by adding another instance variable activeColor for now. */ + return activeColor; + } + + /** + Zeichnet eine Linie in der aktuellen Zeichenfarbe. + @param x Anfangspunkt + @param y Endpunkt + */ + public void drawLine(Point x, Point y){ + // Odering points reduces the amount of graphical artifacts in rendering the same object in different ways + Point x1 = x; + Point y1 = y; + if ((x.x > y.x) || ((x.x == y.x) && (x.y > y.y))) { + x1 = y; + y1 = x; + } + panel.addCommand(new DrawLine(x1,y1)); + panel.repaint(); + } + + /** + Zeichnet einen Punkt in der aktuellen Zeichenfarbe. + @param p Punkt + */ + public void drawPoint(Point p){ + drawLine(p, p); + } + + /** + Zeichnet einen Punkt in der aktuellen Zeichenfarbe. + @param p Punkt + */ + public void drawStringAt(String s, Point p){ + Command c = new DrawString(s,p); + panel.addCommand(c); + panel.repaint(); + } + + /** + * Zeichnet ein Polygon, gegeben durch ein geordnetes Array von Punkten + * @param poly Array von Punkten, welche 2D Polygon beschreiben. + */ + public void drawPoly(Point[] poly) { + Point previous = poly[poly.length-1]; + for (Point next : poly) { + drawLine(previous,next); + previous = next; + } + } + + /** + * Zeichnet und füllt ein Polygon, gegeben durch ein geornetes Array von Punkten + * @param poly Array von Punkten, welche 2D Polygon beschreiben. + */ + public void fillPoly(Point[] poly) { + int[] xpoints = new int[poly.length]; + int[] ypoints = new int[poly.length]; + for (int i = 0; i cl = new ArrayList(); + + public void paintComponent(Graphics g) + { + super.paintComponent(g); + Graphics2D g2D = (Graphics2D)g; + + ArrayList cl = this.cl; // Kopie wegen Nebenläufigkeit von Swing + int size = cl.size(); + for (int i=0; i(); +// } +// }); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (InvocationTargetException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + } +} + + +abstract class Command //implements Serializable +{ + abstract void execute(Graphics2D g2D); + + /** Clone a shape. This method is needed because Shape + * does not define clone(), although many shape classes do. + * Kopiert aus jsky-2.6 auf ftp.eso.org */ + static Shape cloneShape(Shape s) { + // FIXME Add more specific shapes + if (s instanceof RectangularShape) { + return (RectangularShape) ((RectangularShape) s).clone(); + } else { + return new GeneralPath(s); + } + } + +} + +class DrawLine extends Command { + Point von; + Point bis; + DrawLine(Point von, Point bis) { + /* Clonen der Punkte essentiell um Aliasingeffekte beim Redraw zu verhindern */ + this.von = new Point(von); + this.bis = new Point(bis); + } + void execute(Graphics2D g2D) + { + g2D.drawLine(this.von.x,this.von.y,this.bis.x,this.bis.y); + } +} + +class SwitchToForegroundColor extends Command { + SwitchToForegroundColor() {} + void execute(Graphics2D g2D) { + g2D.setColor(Color.black); + } +} + +class SwitchToBackgroundColor extends Command { + Color backcolor; + SwitchToBackgroundColor(Color backcolor) {this.backcolor = backcolor;} + void execute(Graphics2D g2D) { + g2D.setColor(backcolor); + } +} + +class SetColor extends Command { + Color color; + SetColor(Color color) {this.color = color;} + void execute(Graphics2D g2D) { + g2D.setColor(this.color); + } +} + + +class Draw extends Command { + Shape shape; + Draw(Shape shape) {this.shape = cloneShape(shape);} + void execute(Graphics2D g2D) { + g2D.draw(this.shape); + } +} + +class Fill extends Command { + Shape shape; + Fill(Shape shape) {this.shape = cloneShape(shape);} + void execute(Graphics2D g2D) { + g2D.fill(this.shape); + } +} + +class DrawString extends Command { + String string; + Point position; + DrawString(String string, Point position) {this.string = string; this.position = position;} + @Override + void execute(Graphics2D g2D) { + g2D.drawString(string, position.x, position.y); + } +} + + + + + + + + + diff --git a/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/HuepfendeBaelle.java b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/HuepfendeBaelle.java new file mode 100644 index 0000000..f6e1eef --- /dev/null +++ b/ws2015/eip/blaetter/10/1/de/lmu/ifi/tcs/HuepfendeBaelle.java @@ -0,0 +1,129 @@ +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; + + +public class HuepfendeBaelle { + + 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; + /** + * @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); + + + //while( true ) { + for (Ball ball : baelle) { + ball.updatePosition(); + } + hb.zeichneAlleBaelle(); + //} + + // 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 +")"); + b = new Ball(randpunkt, click, (zufall.nextDouble()-0.5)*200, (zufall.nextDouble()-0.5)*200); + hb.plusBall(b); + } + for (Ball ball : baelle) { + ball.updatePosition(); + } + hb.zeichneAlleBaelle(); + click = gw.mouseClick(); // Warten auf Mausklick + } + gw.setText("Auf Wiedersehen!"); + gw.sleep(8000); + + System.exit(0); + } + + /** + * @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); + } +} -- cgit v1.2.3