Informatik

Futter fressen

Jetzt bekommt dein Donut etwas zu fressen. Jede Sekunde erscheint irgendwo ein kleiner Donut. Berührt dein Donut ihn, frisst er ihn und wird um dessen Stärke größer.

Jede Sekunde ein Donut

Die Bühne hat, wie jede Figur, eine Methode run(), die bei jedem Bild aufgerufen wird. getTimer().everyMillis(1000) ist genau einmal pro Sekunde true – dann ruft run() die Methode erzeugeFutter() auf.

Das Futter soll nicht direkt auf dem Spieler entstehen, sonst wäre es sofort gefressen. Deshalb würfelt eine fußgesteuerte Schleife die Position so lange neu, bis das Futter den Spieler nicht berührt:

int versuche = 0;
do {
   futter.setPosition(Random.random(-400, 400), Random.random(-300, 300));
   versuche++;
} while (futter.isTouchingSprite(spieler) && versuche < MAX_VERSUCHE);
 
if (futter.isTouchingSprite(spieler)) {
   futter.remove();
}

Warum der Zähler versuche? Ohne ihn liefe die Schleife, bis eine freie Stelle gefunden ist. Solange dein Donut klein ist, klappt das fast immer beim ersten Wurf. Aber er wächst – und irgendwann ist er so groß, dass er die ganze Bühne bedeckt. Dann gibt es keine freie Stelle mehr, die Schleife endet nie, und das Spiel friert ein. Deshalb gibt die Schleife nach MAX_VERSUCHE Würfen auf, und das Futter kommt wieder von der Bühne.

Eine Schleife, die so lange würfelt, bis sie Glück hat, braucht eine Obergrenze. Sonst hängt das Programm, sobald es kein Glück mehr geben kann.

Wer frisst wen?

Fressen kann jeder Donut, deshalb steht es in der Oberklasse Donut:

public void run() {
   Donut anderer = this.getTouchingSprite(Donut.class);
   if (anderer != null && staerke >= anderer.getStaerke()) {
      this.setStaerke(staerke + anderer.getStaerke());
      anderer.remove();
   }
}

getTouchingSprite(Donut.class) liefert einen Donut, den dieser gerade berührt – oder null, wenn er keinen berührt. Ist der andere nicht stärker, wird er gefressen: seine Stärke kommt dazu, und er verschwindet von der Bühne.

Der SpielerDonut hat aber schon ein eigenes run() für die Bewegung. Damit er trotzdem fressen kann, ruft er am Ende super.run() auf – das run() der Oberklasse.

Überschreiben und super: Hat eine Unterklasse eine Methode mit demselben Namen wie die Oberklasse, wird nur die der Unterklasse ausgeführt. Mit super.methode() ruft man die Methode der Oberklasse zusätzlich auf.

Die Hitbox

Zwei Figuren berühren sich, wenn sich ihre Hitboxen überschneiden. Ohne eigene Hitbox ist das das ganze Rechteck des Bildes – auch die leeren Ecken um den runden Donut. setHitbox(new Ellipse(0, 0, 512, 480)) legt stattdessen eine Ellipse in das Bild, die genau so groß ist wie der Donut. Die Zahlen beziehen sich auf das Originalbild mit 512 × 480 Pixeln; beim Verkleinern wächst die Hitbox mit.

a) Entferne super.run(); aus SpielerDonut. Was passiert, und warum?

b) Entferne die Zeile mit setHitbox aus Donut. Fahre mit deinem Donut so an das Futter heran, dass sich nur die Ecken der Bilder berühren.

c) Auch das Futter ist ein Donut und hat dasselbe run(). Was passiert, wenn zwei Futter-Donuts nebeneinander entstehen?

d) Lass das Futter alle 200 Millisekunden erscheinen. Wie schnell wächst dein Donut jetzt?

e) Setze die Stärke des SpielerDonut im Konstruktor auf 250 und starte. Was passiert mit dem Futter? Was wäre ohne die Obergrenze MAX_VERSUCHE passiert?

Tipp zu c)

Lies das run() von Donut noch einmal und achte darauf, wer this ist, wenn ein Futter-Donut es ausführt.

Weiterspielen

Punkte. Zeige oben auf der Bühne die aktuelle Stärke deines Donuts an.

Ein Text braucht eine Position und eine Breite. Die x-Koordinate ist die Mitte des Textes.

Giftige Donuts. Lass gelegentlich einen grünen Donut erscheinen, der beim Fressen die Stärke verringert. Dafür brauchst du eine weitere Unterklasse von Donut.

Futter fressen

Teilbare URL erstellen

Abschnitte auswählen