Ubung 9 - Knopper.Net

Werbung
Softwaretechnik für IM, WS2016/2017
http://knopper.net/bw/swt/
Übung 9
Java-Games
1. Schreiben Sie eine Java-Klasse FangDenBaum, die folgendes leisten soll:
(a) 100 jeweils ungefähr 60x60 Pixel große Fenster öffnen, in denen ein ähnliches
Weihnachsbäumchen wie das in Übung 6...8 programmierte befindet. Hierfür bietet
sich die Verwendung einer Hilfsklasse an. Sie können ggf. Weihnachtsbaum.java
und WeihnachtsbaumNode.java aus Übung 6ff wiederverwenden. Die Fenster sollten keine Rahmen haben (Tipp: setUndecorated(true)).
(b) Die Fenster sollen vor der Maus fliehen“, wenn diese dem Fensterinhalt zu na”
he kommt, d.h. sich von der Maus wegbewegen (Tipp: setLocation(x,y)).
Hierzu bietet es sich an, einen MouseMotionListener für das Hauptfenster
(Fenster-Fläche oder gesamter Desktop) oder jedes einzelne Fenster zu implementieren, der an beliebigen Positionen die Mausposition erfährt.
(c) Optional (um es spannender zu machen) können die Fenster sich auch ständig auf
dem Bildschirm bewegen, z.B. in einem Schwarm im Kreis laufen. Hierfür ist es
wahrscheinlich sinnvoll, eine Schleife zu programmieren, in der neben setLocation(x,y)
auch ein Konstrukt wie das folgende auftaucht, um für ein zufälliges Zeitintervall
zwischen 0 und 100 Millisekunden zu warten:
try { new Thread().sleep((int) (100.0 * Math.random())); }
catch(InterruptedException ie) {} // Ignorieren
(d) Wenn der Anwender es schafft, ein Fenster zu fangen (d.h. auf das Bäumchen in
diesem Fenster zu klicken), wird das Programm beendet und alle Fenster geschlossen.
Folgende Methoden und Variablen aus der awt-Library könnten außerdem hilfreich sein:
getToolkit().getScreenSize().width,
getToolkit().getScreenSize().height,
Math.random(), setResizable(false),
addMouseMotionListener(...),
getX() (Mausposition X), getY() (Mausposition Y).
1
2. Was müssen Sie tun, damit das Programm auch in einem Web-Browser lauffähig ist?
Lösung Live:
http://knopper.net/bw/swt/uebungen/uebung09-musterloesung/FangDenBaum.html
2
Weihnachtsbaum.java
//
//
//
//
//
//
Weihnachtsbaum.java
Ein Bäumchen als Fenster
Vorlage für weitere Aufgaben ab Übung 8
(C) Klaus Knopper 2010
Lizenz: GPL V2
import java.awt.*;
// Graphics, Frame etc.
import java.awt.event.*; // *Listener
// Ein Weihnachsbäumchen als Frame, damit können wir ein Fenster mit Inhalt
// einfach durch new Weihnachtsbaum() erscheinen lassen.
public class Weihnachtsbaum extends Frame
implements WindowListener,MouseListener,MouseMotionList
// Polygonzug für Baumkrone
private static final int[] bkx = {30,20,25,15,20,10,15,5,55,45,50,40,45,35,40,30};
private static final int[] bky = {22,32,32,42,42,52,52,62,62,52,52,42,42,32,32,22};
private static final Polygon bk = new Polygon(bkx,bky,16);
// Polygonzug für Stamm
private static final int[] bsx = {29,29,20,20,40,40,31,31};
private static final int[] bsy = {62,72,72,74,74,72,72,62};
private static final Polygon bs = new Polygon(bsx,bsy,8);
public Weihnachtsbaum(){ // Konstruktor ohne Parameter...
this(true);
// ruft Konstruktor MIT Parameter auf. [ Weihnachtsbaum(true) ]
}
// Konstruktor mit Parameter
// wird "rahmen" auf "false" gesetzt, dann bekommen wir ein Fenster ohne
// Titelleiste und Dekoration.
public Weihnachtsbaum(boolean rahmen){
if(rahmen == false) setUndecorated(true);
setSize(60,80); // Kleine Fenstergröße
setResizable(false);
// Fenster zufällig irgendwo auf dem Bildschirm
// positionieren.
// Die Bildschirmgröße ist
// Window.getToolkit().getScreenSize().{width,height}
int screenWidth = getToolkit().getScreenSize().width;
int screenHeight = getToolkit().getScreenSize().height;
setLocation((int)(Math.random()*(double)(screenWidth-60)),
(int)(Math.random()*(double)(screenHeight-80))); // Zufällige Position
setVisible(true);
// Fenster sichtbar machen.
paint(this.getGraphics()); // Reinzeichnen, Methode paint() siehe unten.
addMouseMotionListener(this); // Mausbewegungen (im Fenster) abhören
addMouseListener(this);
// Mausklicks (im Fenster) abhören
addWindowListener(this);
// Schließen-Button
}
// paint() sollte immer aufgerufen werden, wenn der Fensterinhalt
// durch Überdeckung oder Iconifizieren zerstört wurde, und wieder
3
// neu aufgebaut werden soll.
public void paint(Graphics g) {
// Polygonzug mit grüner Füllung (Baumkrone)
g.setColor(Color.green); g.fillPolygon(bk);
// Umrandung
g.setColor(Color.black); g.drawPolygon(bk);
// Polygonzug mit brauner Füllung (Stamm)
g.setColor(Color.red);
g.fillPolygon(bs);
g.setColor(Color.black); g.drawPolygon(bs);
}
// Klick auf "Schließen"-Button schließt das Fenster
public void windowClosing(WindowEvent e) { dispose(); }
// Mausklick ins Fenster schließt das Fenster ebenfalls.
public void mouseClicked(MouseEvent e) { dispose(); }
// Fenster wurde wiederhergestellt, Inhalt neu zeichnen.
public void windowDeiconified(WindowEvent e)
{
paint(this.getGraphics());
}
// Diese Events kommen aus WindowListener, MouseListener und MouseMotionListener, u
// werden erst mal ignoriert.
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
}
WeihnachtsbaumAnimiert.java (Erweiterung der Vorlage aus Übung 6)
// WeihnachtsbaumAnimiert.java
// Erweiterung mit Bewegungsfunktion und ohne Rahmen
import java.awt.*;
// Graphics, Frame etc.
import java.awt.event.*; // *Listener
public class WeihnachtsbaumAnimiert extends Weihnachtsbaum implements MouseMotionLi
// Wird von Konstruktor und moveAround() verwendet
int screenWidth = 0, screenHeight = 0;
// Konstruktor mit Parameter
// wird "rahmen" auf "false" gesetzt, dann bekommen wir ein Fenster ohne
// Titelleiste und Dekoration.
public WeihnachtsbaumAnimiert(boolean rahmen){
4
dispose(); // Zunächst Frame aus Basis-Konstruktor schließen
if(rahmen == false) setUndecorated(true); // Ohne Titelleiste
setSize(60,80);
// Kleine Fenstergröße
setResizable(false);
// Ohne "Größe ändern" Rahmen
setAlwaysOnTop(true);
// Immer vor allen anderen Fenstern
setVisible(true);
// Fenster sichtbar machen.
paint(this.getGraphics()); // Reinzeichnen, Methode paint() siehe unten.
addMouseMotionListener(this); // Mausbewegungen (im Fenster) abhören
addMouseListener(this);
// Mausklicks (im Fenster) abhören
addWindowListener(this);
// Schließen-Button
}
public WeihnachtsbaumAnimiert(){ // Konstruktor ohne Parameter...
this(true);
// ruft Konstruktor MIT Parameter auf. [ WeihnachtsbaumAnimiert(true
}
// MouseListener und MouseMotionListener
public void mouseEntered(MouseEvent e) { moveAway(); } // Ausweichen!!!
public void mouseMoved(MouseEvent e) { moveAway(); } // Ausweichen!!!
// Ausweich-Routine
public void moveAway(){
// Baum um 0-100 Pixel in eine zufällige Richtung bewegen
int shiftX = 100 - (int)(200.0*Math.random());
int shiftY = 100 - (int)(200.0*Math.random());
setLocation(getX()+shiftX,getY()+shiftY);
X = Y = 0; // Bewegungsrichtung neu setzen
}
// Bewegungs-Routine
int dirX = Math.random() < 0.5
int dirY = Math.random() < 0.5
int X = 0, Y = 0;
public void moveAround(){
if(X==0) X = getX();
if(Y==0) Y = getY();
X += (int)(10.0*Math.random())
Y += (int)(10.0*Math.random())
setLocation(X, Y);
if(X < 60)
else if(X > (screenWidth-60))
if(Y < 60)
else if(Y > (screenHeight-80))
}
? 1 : -1;
? 1 : -1;
* dirX;
* dirY;
dirX
dirX
dirY
dirY
=
=
=
=
1;
-1;
1;
-1;
// Mausklick ins Fenster beendet das Spiel.
public void mouseClicked(MouseEvent e) { FangDenBaum.ende=true; new Gewonnen(); }
}
FangDenBaum.java
// FangDenBaum.java, Hauptprogramm
import java.awt.*;
5
import java.awt.event.*;
import java.applet.*;
import java.util.ArrayList;
public class FangDenBaum extends Applet { // Läuft als Applet wie als Applikation.
// Baum-Liste
ArrayList<WeihnachtsbaumAnimiert> liste = new ArrayList<WeihnachtsbaumAnimiert>();
// Indikator für "Spielende"
public static boolean ende = false;
// Falls Standalone-Applikation
public static void main(String[] args) {
FangDenBaum game = new FangDenBaum();
game.init();
// Bäume auf den Bildschirm
game.start(); // Bäume animieren
}
// Falls Applet
public void init() {
// Wir merken uns alle Bäume in der ArrayList
// damit wir sie alle jederzeit wieder löschen und bewegen können.
for(int i=0; i<100; i++) {
liste.add(new WeihnachtsbaumAnimiert(false));
}
}
public void start() {
while(!ende) {
for(int i=0; i<liste.size(); i++){
liste.get(i).moveAround();
sleep(25);
}
}
// Spielende: Alle Weihnachtsbaum-Fenster schließen
for(int i=0; i<liste.size(); i++){
liste.get(i).setVisible(false);
liste.get(i).dispose();
}
}
public void sleep(int ms) {
try { new Thread().sleep((int) (ms * Math.random())); }
catch(InterruptedException ie) {} // Ignorieren
}
}
Gewonnen.java (Eine kleine Erweiterung der Aufgabenstellung)
import java.awt.*;
import java.awt.event.*;
6
public class Gewonnen extends Frame implements MouseListener,WindowListener {
public Gewonnen(){
setTitle("Geschafft");
Button button = new Button("Gewonnen!");
button.setFont(new Font("SansSerif", Font.BOLD, 100));
setSize(750,300);
add(button);
button.addMouseListener(this);
addWindowListener(this);
setVisible(true);
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {}
// Klick auf "Schließen"-Button beendet das Programm
public void windowClosing(WindowEvent e) { dispose(); System.exit(0); }
// Mausklick ins Fenster beendet das Programm ebenfalls.
public void mouseClicked(MouseEvent e) { dispose(); System.exit(0); }
// Diese Events werden ignoriert.
public void windowOpened(WindowEvent e) { }
public void windowClosed(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
7
Herunterladen