Einstieg in Processing

Sie wissen bereits, was Klassen und Objekte sind, damit haben Sie beste Voraussetzungen den folgenden Teil fast mühelos zu bewältigen. Wir werden uns nun mit der Objektorientieren Programmierung (OOP) auseinandersetzen. Dabei soll es darum gehen, dass wir unsere Modellierung in ein Computerprogramm überführen. Als Programmiersprache werden wir Processing nehmen. Processing ist eine Objektorientierte Programmiersprache und ein Dialekt von Java. Processing bietet im Vergleich zu Java einige einfachere Befehle und eine deutlich einfachere Erstellung von grafischen Produkten. Die Schreibweise von Befehlen (Syntax) ist identisch. Damit bietet es für den schulischen Kontext eine gute Möglichkeit uns auszuprobieren und dabei auch etwas zu sehen. In Java ist das Erstellen von grafischen Produkten sehr komplex und kompliziert, was wir mit Processing etwas vereinfachen. Darüber hinaus ist Processing für Windows und MACOS verfügbar.

Als erstes sollten Sie sich Processing herunterladen und installieren.

Schauen wir suns also zunächst Processing etwas genauer an:

  1. Laden Sie sich zunächst aus dem Gruppenordner das Projekt „Einstiegsaufgabe“ und bearbeiten Sie die Aufgaben in dem Quelltext.

  2. Wie Sie sehen, kann mit dem fill()-Befehl die Farbe des Kreises geändert werden. Beim Abprallen von den Wänden, soll sich die Farbe des Kreises ändern. Am besten soll sich die Farbe zufällig ändern. Ergänzen Sie diesen Sachverhalt entsprechend.

  3. Legen Sie eine Variable für den Durchmesser des Kreises an (Variablenname soll d sein), weisen Sie dem Durchmesser einen Wert zu und setzen Sie an den Stellen, wo bisher der Wert des Durchmessers genutzt wurde, die Variable ein.

  4. Das praktische an Processing ist, dass wir auch Maus- und Tastatur-Eingaben verwenden können. Im Folgenden werden wir nacheinander schauen, wie das funktioniert:

Unten sind zwei Klassenkarten gegeben. Eine Klassenkarte zeigt die Figur eines Goblins und die andere, die eines Helden. Der Datentyp float stellt Dezimalzahlen dar und der Datentyp PImage ermöglicht das Laden von Bilddateien. Es gibt jeweils eine Operation, die genau so heißt, wie die Klasse. Dabei handelt es sich jeweils um den Konstruktor (eng. Constructor –> deshalb das C vor der Operation). Der Konstruktor enthält quasi die Anleitung wie ein neues Objekt der Klasse Held beim Erstellen aufgebaut sein soll.

Erklären Sie kurz die beiden Klassenkarten und was zu vermuten ist, was die beiden Klassen so machen.

  1. Im Gruppenordner finden Sie einen Ordner „Adventure01“. Kopieren Sie sich diesen Ordner und speichern Sie sich den Ordner für sich ab. Öffnen Sie anschießend den Ordner und starten Sie die Datei „Adventure01“. Starten Sie das Programm und schauen Sie, was geschieht. Klicken Sie auch mal das Fenster an und drücken Sie dann die Pfeiltasten.
    Analysieren Sie dann, was die Quellcodezeilen bedeuten. Machen Sie sich dazu Bilder des Quellcodes und schreiben Sie dann neben den Quellcode, was dieser macht. Die Klassenkarten auf der vorherigen Seite können Ihnen helfen.

  2. Unser Held und der Goblin sollen als Attribute natürlich Lebenspunkt haben und jeder Held soll mit 10 Lebenspunkten starten und jeder Goblin mit 5 Lebenspunkten. Ergänzen Sie bei den Attributen die Lebenspunkte und sorgen Sie dafür, dass bei jedem Helden und Goblin die Attribute mit den entsprechenden Werten gestartet werden.

  3. Unser Held braucht noch etwas Unterstützung von einem Zauberer.
    1. Implementieren Sie analog zur Klasse Held die Klasse Zauberer. Sie finden hierfür im Bilder-Ordner des Projekts bereits Sprite-Bilder, die Sie für den Zauberer nutzen können. Geben Sie dem Zauberer aber noch ein Attribut für Manapunkte. Zauberer starten aber immer oben rechts in dem Fenster und haben 5 Manapunkte.
    2. Erzeugen Sie analog zum Helden und zum Goblin ein Objekt der Klasse Zauberer und lassen Sie den Zauber auch sichtbar werden.
    3. Implementieren Sie für den Zauberer auch die Möglichkeit, dass dieser mittels der Tasten w, a, s, d bewegt werden kann.
  4. Erzeugen Sie ein zweites Objekt der Klasse Goblin, welches am unteren Rand patroulliert.

  5. Sowohl beim Helden als auch beim Zauberer ist es zurzeit möglich das Fenster zu verlassen. Verändern Sie die Operationen zur Bewegung, sodass geprüft wird, ob mit dem nächsten Schritt nicht das Fenster verlassen wird.
    1. Der Held geht den Schritt, wenn er noch nicht den Rand berührt hat, ansonsten kommt er einfach nicht weiter.
    2. Verlässt der Zauberer das Fenster, taucht er auf der anderen Seite wieder auf und das gleiche für unten. Hinweis: Beim Einstiegsszenario mit dem herumfliegenden Ball haben Sie etwas Ähnliches gemacht.
  6. Stellen Sie mit roten Kreisen die Lebenspunkt und mit blauen Kreisen die Manapunkte dar. Die Kreise sollen in der Nähe der Charakters erscheinen und beim Gehen mit der Figur mitgehen. Implementieren Sie die Lebens- und Manapunkte.

  7. Es soll getestet werden, ob die Lebenspunktedarstellung korrekt funktioniert. Dazu soll mittels Drücken einer Taste ein Lebenspunkt abgezogen und mittels einer anderen Taste ein Lebenspunkt hinzugefügt werden.
    1. Implementieren Sie diese Testmöglichkeit.
    2. Ergänzen Sie auch die Möglichkeit für das Testen der Manapunkte beim Zauberer.
Hilfen

Zwischenergebnisse

Ergebnise nach Aufgabe 7: hier

Bisher haben wir recht simple Operationen kennengelernt. Die Operationen haben Dinge für uns geprüft oder entsprechend das Aussehen unseres Helden verändert. Es gibt aber noch zwei weitere “Arten” von Operationen. Wir haben zum einen Operationen mit Rückgabewert und zum anderem Operationen mit Übergabeparameter.

Hier betrachten wir die Operationen mit Rückgabewert.

Operationen mit Rückgabewert machen etwas und geben danach einen Wert zurück. Schauen wir uns das am Beispiel des Helden einmal an. Der Held hat als ein Attribut seine Lebenspunkte. Ich möchte nun gerne diesen Wert einmal haben, um damit etwas zu machen.

public int getLp()
{
    return lp;
}

Wir erkennen, dass der Aufbau dieser Operation ähnlich zu dem Aufbau der bisherigen Operationen ist. Anders ist hier, dass statt dem void nun ein int steht. Bei Operationen mit Rückgabewert muss hier immer der Datentyp stehen, von dem der Wert ist, der zurückgegeben wird. Wir wollen den Wert des Attribut lp zurückgeben und dieser ist vom Datentyp int, also muss statt void int geschrieben werden. Außerdem muss bei einer Operation mit Rückgabewert immer auch die return-Anweisung auftauchen. Nach der return-Anweisung muss die Variable oder der Wert stehen, welcher zurückgegebn werden soll.

Um nun diese Operation zu verwenden und mir den Wert anzeigen zu lassen, bietet es sich an den Befehl println(); zu verwenden. Dieser gibt, das was in den runden Klammern geschrieben wird, auf der Konsole (der schwarze Bereich unter dem Editor) aus. Dazu wählt man zunächst das Objekt aus, auf welchem die Operation ausgefüghrt werden soll (hier: Gerald) und dann wird hinter dem Punkt der Name der Operation notiert. Führt man das nun aus, wird auf der Konsole der Wert 10 angezeigt, verringert man nun die Lebenspunkte und führt die Operation ernuet aus, kann festgestellt werden, dass ein anderer Wert angezeigt wird.
    
println(Gerald.getLp());
    
  1. Laden Sie sich zunächst hier die aktuelle Version unseres Programm herunter und starten Sie das Programm.

  2. Es wurde bereits beim Helden die Operation getLp() hinzugefügt. Nun soll beim Drücken der Taste z der aktuelle Wert des Objekts mit dem Namen Gerald auf der Konsole ausgegeben werden.
    Ergänzen Sie den beschriebenen Sachverhalt.

  3. Ergänzen Sie bei dem Helden noch ein Attribut name vom Datentyp String und weisen Sie diesem im Konstruktor der Klasse den Wert "Sir Lauch" zu.

  4. Implementieren Sie nun die Operation getName(), welche den Namen zurückgibt sowie dass beim Drücken von z sowohl Name als auch die Lebenspunkte ausgegeben werden.

  5. Ergänzen Sie analog zum Helden die Operationen und Attribute beim Zauberer und lassen Sie hier beim Drücken der Taste u Name, Lebenspunkte und Manapunkte ausgeben.
Hilfen

Zwischenergebnisse

Hier werden in Kürze Zwischenergebnisse erscheinen.

Wie bereits im vorherigen Kapitel angesprochen, gibt es auch Operationen mit Übergabeparametern.

Wier kenne auch bereits mehrere dieser Operationen. Diese Operationen kennzeichnen sich dadurch aus, dass sie Werte brauchen, damit sie etwas machen. So zum Beispiel die Operation circle();. Damit diese Operationen einen Kreis zeichnet, muss sie wissen, wo der Kreis hin soll und wie groß er sein soll. Solchen Operationen wurden so definiert, dass sie Werte erwarten.

Schauen wir uns das an einem kleinen Beispiel an. Wie immer muss zunächst die Funktion der Operationen definiert werden, bevor man diese verwenden kann. Dazu fügt der Entwickler in der entsprechenden Klasse eine Operation hinzu. Die Operation soll folgendes machen: Der Zauberer ist recht ängstlich und fühlt sich nur in einem kleinen Bereich in der Mitte des Fensters wohl. Befindet sich der Zauberer in der Mitte gibt die Operationen auf der Konsole einen Smiley aus. Um dieses zu erreichen, hat die Operation wohlfuehlen(int hoehe, int breite) zwei Parameter. Also erwartet die Operation zwei Werte, mit denen sie dann etwas machen kann.

public void wohlfuehlen(int hoehe, int breite)
  {
    if ((posY < ((hoehe/2)+20)) && (posY > ((hoehe/2)-20)))
    {
      if ((posX < ((breite/2)+20)) && (posX > ((breite/2)-20)))
      {
        println(":-)");
      }
    }
  }

Diese Operation wird in die Klasse geschrieben. Sie regelt nur, was passiert mit den beiden Platzhaltern/Parametern hoehe und breite. Die beiden Parameter haben zu diesem Zeitpunkt keine konkreten Werte. Die erhalten die beiden erst, wenn die Operation genutzt wird. Das geschieht in der Adventure-Datei. Dort muss an geeigneter Stelle immer wieder die Operation aufgerufen werden.

Merlin.wohlfuehlen(height, width);
Damit wird die Operation ausgeführt und erhält in unserem Beispiel die Werte der beiden Variablen und width und height übergaben. Ist in width bspw. der Wert 50 gespeichert, wird überall in der Operation, wo der Parameter breite genutzt wird, der entsprechend übergebene Wert von 50 genutzt.
  1. Laden Sie sich hier die aktuelle Version unseres Szenarios herunter.
  2. Der Zauberer soll sich heilen können. Dazu soll es die Operation heilen(int zahl) geben. Diese erwartet einen Zahlenwert, welcher dann zu den aktuellen Lebenspunkten hinzugerechnet wird.
    1. Implementieren Sie die Operation und testen Sie diese, indem beim Drücken einer Taste die Operation ausgeführt wird und dann eine festgegelegte Anzahl an Lebenspunkten geheilt werden.
    2. Der Zauber kann natürlich nur gewirkt werden, wenn noch genug Manapunkte vorhanden sind.
      Verändern Sie die Operation, sodass heilen(int zahl) ausgeführt wird und dabei die Manapunkte entsprechend reduziert werden.
      Hinweis: Ignorieren Sie zunächst, ob noch genug Manapunkte vorhanden sind.
    3. Der Zauber soll nun nur noch gewirkt werden können, wenn ausreichend Manapunkte vorhanden sind. Sind nicht mehr genug Manapunkte da, soll auf der Konsole (println();) eineentsprechende Ausgabe erscheinen.
  3. Sir Lauch ist nicht mehr mit seinem Namen zufrieden. Die Operation setName(String neu) soll einen neuen Namen in Form einer Zeichenkette übergeben bekommen und diesen Wert dann in dem Attribut name der Klasse Held speichern.
    Implementieren Sie die Operation und testen Sie diese.
  4. Der Held soll nun auch Heiltränke bekommen. Dazu erhält die Klasse Held das neue Attribut heiltränke vom Datentyp Ganzzahl und jedes Objekt der Klasse Held startet mit 5 davon.
    1. Ergänzen Sie zunächst das Attribut und den Startwert im Konstruktor.
    2. Implementieren Sie nun die Operation heiltrankTrinken(int anzahl), welche eine bestimmte Anzahl an Heiltränken trinken lässt und dadurch entsprechend viele Lebenspunkte zurückgibt. Bedenken Sie, dass nur so viele Heiltränke getrunken werden können, wie vorhanden sind.