Implementierung
Grundstruktur
Die Funktionalität ließe sich unterschiedlich aufteilen. Am einfachsten ist es für uns hier allerdings, wenn sämtliche Funktionalität -mit Ausnahme der Initialisierung des Spiels- in der Frosch-Klasse enthalten ist.
Ein Frosch muss die eigene Kraft kennen. Beim Erzeugen eines Frosches soll dessen Startbild angegeben werden. Ein Frosch kann springen, essen und einen Storch treffen. Da wir das Spiel in Greenfoot implementieren, kann er auch eine act-Methode ausführen. Theoretisch könnte man die komplette Funktionalität in der act-Methode implementieren. Allerdings wäre diese dann schnell unübersichtlich, weswegen wir gesonderte Methoden zum springen, essen und Storch treffen implementieren wollen. Damit ergibt sich für den Anfang folgendes Klassendiagramm:
Aufgabe 1 - Vorlage öffnen
Lade die Vorlage herunter und erzeuge einen grünen und blauen Frosch. Die Dateinamen der passenden Bilder lauten "froschgruen.png" und "froschblau.png". Warum tritt nicht der gewünschte Effekt ein?
Dokumentation lesen
Zu den ersten Implementierungsschritten könnte z.B. gehören:
- Beim Erzeugen des Frosches soll das Startbild gesetzt werden.
- Der Frosch soll sich zufällig bewegen.
- Wenn der Frosch keine Kraft mehr hat, soll Greenfoot anhalten.
Vielleicht erinnerst Du Dich noch an einen Teil der Methoden, die Du dazu benötigst. Einige Methoden, die Du brauchen wirst, kennst Du allerdings noch gar nicht. Der effektivste Weg diese zu finden, ist meist, die Dokumentation der entsprechenden Klassen zu lesen.
Aufgabe 2 - Aufbau der Dokumentation
Öffne in Greenfoot unter dem Menüpunkt "Hilfe → Greenfoot Klassendokumentation" die Dokumentation der zu Greenfoot zugehörigen Klassen. Untersuche die Dokumentation und beschreibe möglichst genau wo man welche Informationen findet.
Aufgabe 3 - Methoden finden
Suche Methoden, welche die folgenden Aufgaben lösen. Notiere Dir dazu die Klasse, in der eine Methode steht, ob es sich um eine Klassenmethode handelt und wie die Signatur der Methode lautet.
- Das Bild eines Actors soll gesetzt werden.
- Die x- und y-Position eines Actors soll abgefragt werden.
- Die Postion eines Actors soll gesetzt werden.
- Ein Actor soll in der Welt platziert werden.
- Die Breite der Welt soll abgefragt werden.
- Eine Zufallszahl soll erzeugt werden.
- Greenfoot soll anhalten.
Mit Hilfe der gerade gefundenen Methoden kannst Du nun einige Dinge implementieren:
Aufgabe 4 - Basifunktionalität
Ergänze im Programm folgende Funktionalität:
- Beim Erzeugen eines Frosches soll das Bild entsprechend dem übergebenen Parameter gesetzt werden.
- Beim Erzeugen der Welt sollen ein grüner und ein blauer Frosch zufällig auf der Welt erzeugt werden.
Aufgabe 5 - Springen
Der Frosch soll nun zufällig ein Feld weiterspringen. Dabei verringert sich seine Kraft um einen Punkt. Wenn er keine Kraft mehr hat, soll Greenfoot anhalten.
Für die Bewegung gibt es mehrere Lösungsstrategien. Verwende Deine eigene
oder diese hier: Es wird je eine Zufallszahl xDiff
bzw. yDiff
zwischen 0 und 2 für die x- und
y-Position bestimmt. Von dieser Zahl wird eins abgezogen, so dass
die Werte zwischen -1 und 1 liegen. Nun kann man die Position gemäß dem
folgenden Pseudocode verändern:
setzeNeuePosition(altesX + xDiff, altesY + yDiff)
Wiederholungen
Als nächsten müssen mehrere Fliegen und Störche auf der Welt platziert werden. Dabei können wir verschiedene Spielvarianten implementieren. Zuerst wollen wir davon ausgehen, dass der Computer eine Zufallszahl zwischen 0 und 5 "auswürfelt". Solange er eine Zahl kleiner als 5 würfelt, erzeugt er neue Fliegen. Analog könnte man für Störche vorgehen.
Wenn man mehrmals gleiche oder ähnliche Arbeiten in einer Schleife wiederholt ausführen möchte, nutzt man dazu Wiederholungen. Die oben dargestellte Idee ließe sich in Java mit Hilfe der while-Schleife formulieren:
while(Greenfoot.getRandomNumber(6) < 5)
{
int x = Greenfoot.getRandomNumber(getWidth());
int y = Greenfoot.getRandomNumber(getHeight());
addObject(new Storch(), x, y);
}
Aufgabe 6 - Fliegen würfeln
Erkläre den oben dargestellten Code Zeile für Zeile genau. Ergänze den Quellcode der Welt so, dass gemäß der oben dargestellten Idee Fliegen und Störche erzeugt werden.
Wiederholungen mit definierter Wiederholungszahl
Möchte man Anweisungen z.B. 10 mal wiederholen, lässt sich das mit Hilfe einer Zählvariablen realisieren:
int i = 0;
while(i < 10)
{
... Anweisungen ...
i = i + 1;
}
Aufgabe 7 - Fliegen fester Anzahl
Ändere den Code so ab, dass immer z.B. fünf Fliegen und drei Störche erzeugt werden.
Aufgabe 8 - Fliegen zufälliger Anzahl
Die Zahl der Wiederholungen muss nicht als feste Zahl vorgegeben sein, sondern kann z.B. zufällig oder durch Benutzereingaben dynamisch gesetzt werden. Ändere den Code so ab, dass z.B. zwischen vier bis acht Fliegen und zwei bis fünf Störche erzeugt werden.
Wenn Du die verschiedenen Varianten der Wiederholungen ausprobiert hast, kannst Du Dich für die Variante entscheiden, die Dir für das Spiel am besten gefällt.
Klassen und primitive Datentypen
Schön wäre es, wenn man auch optisch erkennt, wenn ein Frosch gestorben ist.
Dazu könnte dessen Bild z.B. halbtransparent dargestellt werden.
Wie Du in der Dokumentation sehen kannst, gibt es eine Methode
getImage()
in der Klasse Actor
, die das Bild eines
Actors vom Typ GreenfootImage
zurück gibt.
Dieses kann man sich nun in einer lokalen Variabeln speichern, um weitere Operation daran auszuführen. Welche dabei möglich sind, kannst Du in der Dokumentation nachlesen.
Die Transparenz eines Bildes lässt sich in Greenfoot damit nach folgendem Muster verändern:
if(kraft <= 0)
{
GreenfootImage img = getImage();
img.methodenaufruf(..) // Die Methode musst Du noch in der Dokumentation suchen
Greenfoot.stop();
}
Wenn man nur einmaligen Zugriff auf das Bild benötigt, kann man die Definition einer lokalen Variablen auch auslassen:
if(kraft <= 0)
{
getImage().methodenaufruf(..) // Die Methode musst Du noch in der Dokumentation suchen
Greenfoot.stop();
}
Aufgabe 9 - Transparenz
Ergänze die Froschklasse gemäß dem obigen Muster, um beim "Sterben" die Transparenz des Bildes zu verändern.
Beachte, dass Du durch getImage()
ein Objekt zurückgeliefert
bekommst, das Du Dir hier in einer Variablen gespeichert hast.
Da Objekte Methoden besitzen, kannst Du diese natürlich auch aufrufen.
Durch die Variable img
erhältst Du also Zugriff auf ein Objekt
einer Klasse.
Bei primitiven Datentypen wie int
oder boolean
funktioniert dies nicht. Ein Aufruf der folgenden Art funktioniert also
(in Java) nicht:
int x = getX();
x.tuWas(); // Kann unabhängig vom Methodennamen nicht funktionieren!
Kollisionserkennung in Greenfoot
In der Dokumentation der Actor-Klasse findest Du z.B. die folgende Methode zur Kollisionserkennung:
Die Signatur der Methode bedarf einiger Erläuterungen:
protected
ist ein Zugriffsmodifikator wie public
oder private
. Die genaue Bedeutung ist für uns hier nicht relevant.
(Wer es dennoch genau wissen will: protected
bedeutet, dass
man in Unterklassen auf die Methode zugreifen darf, in anderen Klassen aber nicht.)
Die Methode gibt true
oder false
zurück,
je nachdem ob ein Actor einer bestimmten Klasse berührt wird.
Als Parameter muss ein Objekt übergeben werden, das die Klasse repräsentiert.
Es handelt sich also nicht um die Klasse selbst, die übergeben wird, sondern
um ein Objekt mit Informationen über die Klasse. Dieses Objekt erhält man in Java
z.B. mit dem Ausdruck Fliege.class
Aufgabe 10 - Essen
Ergänze die Methode zum Essen folgendermaßen: Wenn eine Fliege berührt wird, dann soll die Kraft um 10 Punkte erhöht werden und die Fliege entfernt werden. Die Methode zum Entfernen eines berührten Objekts musst Du noch finden.
Aufgabe 11 - Treffe Storch
Zum Abschluss musst Du noch in der Methode
treffeStorch()
ergänzen, dass Greenfoot
bei Kollision mit einem Storch anhalten soll.
Wenn Du möchtest kannst Du auch dafür sorgen, dass das Bild des Frosches
analog dem Sterben durch Kraftlosigkeit transparent wird.
Glückwunsch: Dein Spiel ist fertig !
Wenn Du möchtest, kannst Du das Spiel noch mit Hilfe von for-Schleifen umschreiben und wie bei den Übungen beschrieben ergänzen.
Vertiefung: Zählschleifen
Um fünf mal eine Fliege auf die Welt zu setzen, hast Du Code in der folgenden Art geschrieben:
int i = 0;
while(i < 5)
{
addObject(new Fliege(), xPosition, yPosition);
i = i + 1;
}
Zählschleifen dieser Art kommen sehr häufig vor. Deshalb gibt es in den meisten Programmiersprachen auch for-Schleifen, die etwas kompakter als while-Schleifen sind:
for(int i = 0; i < 5; i = i+1)
{
addObject(new Fliege(), xPosition, yPosition);
}
In diesem Fall besteht der zu wiederholende Block nur aus einer Anweisung, so dass man sogar die geschweiften Klammern weglassen könnte:
for(int i = 0; i < 5; i = i+1)
addObject(new Fliege(), xPosition, yPosition);
Beachte, dass beide Schleifen gleich mächtig sind und sich nur in der Art der Darstellung unterscheiden.
Aufgabe 12 - for-Schleifen
Ersetze dort wo es Dir sinnvoll erscheint die Schleifen Deines Projektes durch for-Schleifen.