Greenfoot - Schnipsel

Worum geht es hier?

Hier findest Du einige kleine Codeschnipsel, die typische Programmiermuster demonstrieren. Für eine vollständige Übersicht der Möglichkeiten solltest Du Dir einmal die Greenfoot-API anschauen (API = Application Programming Interface), die Du im Greenfoot-Menü unter "Help→Greenfoot Class Documentation" findest.

Die Beispiele sind bewusst kurz gehalten und sollen nicht jedes Programmierkonzept, das dahinter steht, erläutern. Dafür hast Du ja noch Deinen Informatiklehrer. Der hilft Dir bestimmt bei Fragen, wenn Du ihn nett darum bittest :-)

Den meisten Beispielen liegt ein Greenfoot-Projekt mit Hunden und Katzen zu Grunde, das Du Dir auch herunterladen kannst.

Zufallszahlen

Zufallszahlen kann man wie in Java üblich erzeugen oder mit einer Hilfsfunktion in Greenfoot:

// Erzeuge eine Zufallszahl zwischen 0 und 4 und speichere sie.
int x = Greenfoot.getRandomNumber(5);

Damit könnte man z.B. in zufälligen Abständen ein neues Objekt in der Welt erzeugen:

if(Greenfoot.getRandomNumber(10) == 0)
   getWorld().addObject(new Cat(), 1, 1);

Mausklicks

Man kann sehr einfach feststellen, ob auf ein Objekt geklickt wurde. Dazu benutzt man die Methode Greenfoot.mouseClicked(...). Die Methode gibt true zurück, wenn auf das als Parameter übergebene Objekt geklickt wurde. Übergibt man null, spielt es keine Rolle wohin geklickt wurde. Der unten stehende Code demonstriert wie man innerhalb einer Actor-Klasse auf Mausklicks reagieren kann.

// true, wenn auf das Objekt selbst geklickt wurde.
if(Greenfoot.mouseClicked(this))
   // ...tu was ...

// true, wenn auf den Hintergrund der Welt geklickt wurde.
if(Greenfoot.mouseClicked(getWorld()))
   // ... tu was ...

// true, wenn auf den neu erzeugten Hund geklickt wurde.
Hund h = new Hund();
getWorld().addObject(h, 10, 20);
if(Greenfoot.mouseClicked(h))
   // ... tu was ...

Tastatur

Soll z.B. der Hund bellen, wenn die Taste "b" gedrückt wird, muss in seiner act-Methode stehen:

if(Greenfoot.isKeyDown("b"))
   bellen();

Leertaste und die Cursortasten werden über die Zeichenketten "space", "left", "up", ... angesprochen.

Greenfoot anhalten

Beim Spielende o.ä. lässt sich Greenfoot auch anhalten.

Greenfoot.stop();

Geschwindigkeit einstellen

Den Schieberegler zum Einstellen der Greenfoot-Geschwindigkeit kann man auch über einen Befehl verstellen. Besonders sinnvoll ist dies oft im Kontruktor der Welt. Gültige Werte sind ganze Zahlen zwischen 0 und 100.

public MyWorld()
{
   Greenfoot.setSpeed(50);
}

Kollisionen erkennen

Möchte ein Hund wissen, ob er auf eine Katze trifft, kann er das folgendermaßen erreichen.

if(isTouching(Katze.class))
    bellen();

Möchte er dagegen Zugriff auf das Kollisions-Objekt haben, um z.B. eine Methode an diesem aufzurufen, muss man sich das Objekt z.B. in einer lokalen Variablen speichern. Der folgende Code lässt sich allerdings nicht compilieren:

Katze k = getOneIntersectingObject(Katze.class);

Das liegt daran, dass die Methode getOneIntersectingObject(...) den Rückgabetyp Actor hat, was auch Sinn macht, da die Greenfoot-Entwickler ja nicht wissen konnten, dass wir eine Katze suchen wollen. Ändert man den Typ der Variablen k zu Actor, dann lässt sich diese Zeile zwar übersetzen, aber zusammen mit dem Aufruf zum Fauchen lässt sich der Code wieder nicht übersetzen:

Actor k = getOneIntersectingObject(Katze.class);
if(k != null)
    k.fauchen();

Die Ursache ist jetzt, dass k zwar auf eine Katze verweist, die Referenz auf diese aber nur vom Typ der Oberklasse Actor ist. Somit kann man keine Methoden der Klasse Katze aufrufen, sondern nur Methoden der Klasse Actor, obwohl es sich eigentlich um ein Objekt der Klasse Katze handelt. Man benötigt einen Mechanismus, um auszudrücken: "Ich möchte das Objekt als Katze behandeln, weil ich weiß, dass es eine Katze ist." Dies erreicht man durch einen Typecast (auf deutsch: Typumwandlung), indem man den Typ vor das Objekt in Klammern schreibt:

Katze k = (Katze) getOneIntersectingObject(Katze.class);
if(k != null)
    k.fauchen();

Oft ist ein Typecast ein Zeichen für einen schlechten Entwurf, hier lässt er sich aber nicht vermeiden.

Objekte entfernen

Meistens möchte man sich selbst oder einen anderen Actor, den man berührt, entfernen . Für das Entfernen von Actor-Objekten ist die Welt zuständig.

Um sich selbst zu entfernen muss man sich über getWorld() zuerst die Welt zurück geben lassen und ihr dann sagen (eine Methode aufrufen), dass sie einen selbst löschen soll. Für den Spezialfall, dass man ein kollidierendes Objekt entfernen möchte, bietet die Actor-Klasse direkt eine Methode removeTouching(...), die im Prinzip nur eine Abkürzung für das Überprüfen der Kollision und Entfernen über die Welt darstellt.

Soll der Hund also eine Katze entfernen, wenn er sie trifft, und anschließend aus Schuldgefühl Selbstmord begehen, geht das so:

if(isTouching(Katze.class))
{
    removeTouching(Katze.class);
    getWorld().removeObject(this);
}

oder alternativ:

Actor k = getOneIntersectingObject(Katze.class);
if(k != null)
{
    getWorld().removeObject(k);
    getWorld().removeObject(this);
}

Objekte erzeugen

Möchte man in Java ein Objekt erzeugen, kann man dies einfach durch Aufruf des Kontruktors, z.B. mit new Hund() tun. Damit wird zwar ein Hund erzeugt und existiert im Speicher des Computers. Allerdings muss man in Greenfoot einen Actor wie z.B. einen Hund dann auch der Welt hinzufügen, damit man diesen sehen, bewegen etc. kann.

In der Welt geht das z.B. so:

Actor h = new Hund();
addObject(h, 100, 50);

// oder etwas kürzer mit anonymen Objekten:
addObject(new Hund(), 100, 50);

Auch ein Actor kann neue Objekte erzeugen und der Welt dann sagen, dass sie eingefügt werden sollen:

World w = getWorld();
w.addObject(new Katze(), 50, 250);

// oder auch wieder kürzer
getWorld().addObject(new Katze(), 100, 250);

Text ausgeben

Möchte man Text ausgeben, kann man dies zwar prinzipiell mit System.out.println(..) tun, dies hat allerdings zwei deutliche Nachteile in Greenfoot (und anderen grafischen Systemen):

Am einfachsten lässt sich Text in der Welt ausgeben.

showText("Game over!!!", 150, 100);

Soll ein Actor Text über die Welt ausgeben, erreicht man das so:

getWorld().showText("Game over!!!", 150, 100);

// oder zentriert auf der Welt
World w = getWorld();
w.showText("Game over!!!", w.getWidth()/2, w.getHeight()/2);

Das Bild eines Actors kann auch Text ausgeben. Innerhalb einer Actor-(Unter)klasse kann man schreiben:

getImage().drawString("Wuff", 20, 60);

Die beiden Zahlen geben dabei den Abstand der Grundlinie des Textes zur linken oberen Ecke der Grafik an. Soll dabei die vorhandene Grafik ersetzt werden, sieht der Code folgendermaßen aus:

setImage(new GreenfootImage("Wuff", 24, Color.RED, Color.WHITE));

Um die Konstanten Color.RED etc. benutzen zu können, muss man am Anfang des Quellcodes - noch vor der Klasse - das Paket java.awt importieren:

import java.awt.*;
X

Fehler melden

X

Suche