#
Ziel: Das Pong-Spiel wird erweitert.
Die erste Version des Spiels sollte aus wenigen Funktionen bestehen. Schnell wurde aber klar, das dann Spagetticode entsteht. Deshalb wird das Spiel in viele kleine Funktionen zerlegt, um die Übersicht zu behalten und leicht Änderungen vorzunehmen sind.
| Funktion | Aufgabe |
|---|---|
| init | Es werden alle Variablen mit einem Startwert versehen. Der Bildschirm erhält eine weiße Hintergrundfarbe. Die Linie zwischen Anzeige- und Spielfeld wird gezogen. Die beiden Schläger werden gezeichnet. Die Funktion neustart wird aufgerufen. |
| neustart | Es werden zufällige Werte für den Startpunkt eines neuen Balls bestimmt und der Ball wird an diesem Punkt gezeichnet. Die Flugrichtung wird per Zufall festgelegt. Die Funktion anzeige wird aufgerufen. |
| anzeige | Der gesamte Anzeigeblock am oberen Rand wird erneuert. Da Text nicht gelöscht werden kann, zeichnet die Funktion ein weißes Rechteck über alles, erneuert die Linie und beschreibt den Anzeigeblock neu. |
| dauerhaft | In der ständig ablaufenden Schleife werden zuerst die hoch- und runter-Tasten auf gedrückt abgefragt. Ist eine gedrückt, wird die Funktion bewege_schlaeger aufgerufen. Der Funktion wird der Wert "hoch" oder "runter" übergeben. Als nächstes kümmert sich die Funktion um den nächsten Schritt des Balls. Sie fragt, ob er den oberen oder unteren Rand des Spielfeldes erreicht hat. Ist das der Fall, wird das Vorzeichen von dy, also der Änderung in y-Richtung gewechselt. Dann wird der Ball an der bisherigen Stelle gelöscht (ein weißer Kreis gezeichnet), die x- und y-Koordinate des Balls geändert und an der neuen Stelle ein roter Kreis gezeichnet. Ist das erledigt, wird je nach der Seite, auf der sich der Ball befindet, die Funktion test_rechts oder die Funktion test_links aufgerufen. |
| test_rechts und test_links | Die beiden Funktionen werden je nach Flugrichtung nach jeder Ballbewegung aufgerufen und testen, ob der Ball den Schläger berührt oder daneben gegangen ist. Im ersten Fall wird die Funktion treffer und im zweiten Fall die Funktion daneben aufgerufen. Hinweis: Die beiden Funktionen können auch zu einer Funktion zusammengefasst werden. |
| treffer | In der treffer-Funktion wir als erstes die waagerechte Flugrichtung geändert (dx) und die Trefferanzahl um 1 erhöht. Dann wird geprüft, ob die Anzahl der Treffer ohne Rest durch 3 teilbar ist. Ist das der Fall, wird die Länge des Schlägers um 5 Pixel verkleinert, die beiden Bereiche der Schläger mit je einem weißen Rechteck gelöscht und die Schläger neu gezeichnet. Als letztes wird die Funktion anzeige aufgerufen. |
| daneben | Der Ball wird durch das Zeichnen eies weißen Kreises gelöscht, die Variable leben um 1 erniedrigt und eine halbe Sekunde gewartet. Dann wird geprüft, ob die Variable leben größer als 0 ist, das Spiel also noch nicht beendet ist. Wenn das der Fall ist, wird die Funktion neustart aufgerufen. Ist das Spiel zu Ende, wird die boolsche Variable aktiv auf falsch gesetzt, die Anzeige durch Aufruf der Funktion anzeige erneuert und ein Hinweistext zum neuen Start des Spieles angezeigt. |
| bewege_schlaeger | Der Funktion wird als String die Richtung der Bewegung übergeben: "hoch" oder "runter". Dann wird über den Wert von dx überprüft, ob der linke oder der rechte Schläger bewegt werden soll. Bevor der Schläger verändert wird, prüft die Funktion, ob der Schläger den Rand erreicht hat. Ist das nicht der Fall, wird der Schläger durch ein weißes Rechteck gelöscht, die y-Koordinate des Schläger um 2 geändert und der Schläger als neues, blaues Rechteck gezeichnet. |
Gleich beim Start wird die Variable aktiv auf wahr gesetzt. Die unendliche Schleife prüft diese Variable und das Spiel läuft, wenn sie wahr ist. Sind alle Leben verspielt, wird aktiv auf falsch gesetzt und der Calliope mini wartet nun auf den Druck der Taste A auf dem GameKit. Damit geht aktiv wieder auf wahr und es geht von vorn los.
In der init-Funktion werden die Größen für den Ball, den oberen Textbereich und die Schläger festgelegt. Der gesamte Bildschirm wird weiß und die Schläger werden dargestellt.
Hinweis: Es hat sich bewährt, das Spielfeld mit allen Koordinaten, Schlägern und dem Ball aufzuzeichnen. Damit hat man einen Überblick, wann welcher Zustand erreicht ist.
neustart wird immer dann aufgerufen, wenn ein Ball ins Aus gegangen ist. Zuerst wird zufällig festgelegt, ob der neue Ball von links oder von rechts kommen soll. Dann wird gewählt, ob er vom Startpunkt aus nach oben oder nach unten startet. Als letztes wird der y-Wert des Startpunktes gewürfelt.
Damit ist für den neuen Ball alles bereit. Er wird gezeichnet und die anzeige-Funktion aufgerufen.
Da man auf dem Bildschirm keinen Text überschreiben kann, ist ein Löschen nur durch das Zeichnen eines weißen Rechtecks und einer Linie möglich. Damit ist der Text weg und es wird sofort der neue Text zusammengesetzt und geschrieben. Da das sehr schnell geht, sieht man nur, wie sich die Zahlen ändern.
Die dauerhaft-Schleife ist für den eigentlichen Spielablauf verantwortlich. Der Code ununterbrochen ausgeführt, falls die Variable aktiv auf wahr gesetzt ist.
Als erstes werden die beiden Tasten hoch und runter auf dem GameKit abgefragt. Falls das der Fal list, wird der jeweilige aktive Schläger in der Funktion um 2 Pixel bewegt.
Die folgende Entscheidung prüft, ob der Ball den unteren oder den oberen Rand des Spielfeldes erreicht hat. Wenn das der Fall ist, die die Variable dy, die für die Bewegung in y-Richtung verantwortlich ist, negiert. Damit realisiert man eine Reflexion an der Wand. Bewegt sich der Ball vorher nach oben, geht er im nächsten Schritt nach unten.
Die folgenden Zeilen zeichnen den Ball neu. Dazu wird der alte Ball gelöscht (also mit Weiß überzeichnet), die neunen Koordinaten berechnet und ein roter Kreis mit den neuen Koordianten gezeichnet.
Da das ununterbrochen wiederholt wird, sieht es dann so aus, also ob sich der Ball bewegt.
Auf Grund der begrenzten Rechenleistung des Calliope mini braucht hier auch keine Wartezeit eingebaut werden. Es sieht flüssig aus, ist aber nicht zu schnell.
Ist der Ball neu gezeichnet, wir gefragt, ob der Ball jetzt einen der Schläger erreicht hat oder im Aus ist. Das wird mit den beiden Funktioen test_links und test_rechts erreicht. dx bestimmt, welche Funktion aufgerufen wird. Ist dx negativ, bewegt sich der Ball gerade nach links. Nachdem das alles erledigt ist, beginnt die Prozedur von vorn.
Um die Test-Funktionen zu verstehen, sollte man sich den Bildschirm mit allen Objekten aufzeichnen und alle Größen und Abstände in Pixeln dranschreiben. Mir hat das nach einer konfusen Zeit geholfen.
Die Abfrage der 1. Entscheidung ist so groß, dass sie hier nicht auf den Bildschirm passt. Deshalb ist nur ein Teil dargestellt.
Ein Treffer auf der linken Seite ist dann, wenn:
Falls das alles zusammen nicht ist, muss noch geprüft werden, ober der Ball das linke Aus erreicht hat. Je nach Ergebnis wird treffer oder daneben aufgerufen.
Falls beides nicht zutrifft, ist der Ball irgendwo auf dem Spielfeld und er kann ruhig weiterfliegen.
Die Funktion test_rechts muss selber entwickelt werden.
Die treffer-Funktion wird immer dann aufgerufen, wenn im Test festgestellt wurde, dass der Ball einen Schläger berührt hat. Dann muss der Ball am Schläger reflektiert zurückfliegen. Erreicht wird das durch die Vorzeichenumkehr der Variable dx, die ja die Schrittlänge in x-Richtung angibt. Natürlich wird die Variable getroffen um ein erhöht.
Der darauf folgende Test prüft, ob die Anzahl getroffen ohne Rest durch drei teilbar ist. Das ist nach jedem dritten Treffer der Fall und der Schläger wird um fünf Pixel kürzer. Damit man das auch sofort sieht, werden beide Schläger erst gelöscht und dann wieder dargestellt.
Damit man seinen Erfolg auch sieht, wird zum Schluss die Anzeige erneuert.
Die daneben-Funktion ist keine schöne Funktion. Hier kann alles zu Ende sein!
Zuerst lässt man den Ball, der vom Schläger nicht zurückgeschossen wurde, verschwinden. Dann wird die Variable leben um eins erniedrigt.
Der Wert der Variablen legt dann fest, wie es weiter geht. Ist die Anzahl der Leben größer als 0, kann das Spiel weiter gehen. Damit man etwas Zeit zur Besinnung nach dem Fiasko hat, wird eine halbe Sekunde gewartet und der neustart aufgerufen.
Falls aber alles vorbei ist, wird aktiv auf falsch gesetzt, die Anzeige erneuert und ein Hinweistext ausgegeben.
Da die Variable aktiv steuert, was in der Dauerhaft-Schleife passiert, passiert jetzt nichts mehr.
Die Funktion zum Bewegen des Schlägers ist etwas umfangreicher, da sie vier Fälle behandeln muss: linker oder rechter Schläger, hoch oder runter.
Welcher Schläger bewegt werden muss, ist am Vorzeichen von dx zu erkenne. Ist es negativ, fliegt der Ball nach links und der linke Schläger muss bewegt werden. Die Richtung wird als String übergeben.
Vor der Bewegung muss geprüft werden, ob der Schläger überhaupt noch bewegt werden kann oder der Rand erreicht ist. Wenn er noch bewegt werden kann, wird zuerst die ursprüngliche Schläger gelöscht (mit weiß übermalt), der y-Wert um 2 geändert und der Schläger an der neuen Position wieder dargestellt. Fertig. Das Bild zeigt den Teil der Funktion, der den linken Schläger bewegt. Die Erweiterung für den rechten Schläger sollt dann kein Problem darstellen. Wenn doch: die oben erwähnte Zeichnung hilft echt weiter.
Der eigentliche Neustart des Spieles wird über die Taste A auf dem GameKit erreicht. Damit man nicht während eines laufenden Spiels neu starten kann, wird die Variable aktiv abgefragt. Ist sie noch wahr, hat A keine Wirkung.