Graphikfunktionen in Processing
Am Ende des Kapitels solltest du
- wissen, was eine Methode ist und wie man sie aufruft,
- wissen, was ein Parameter ist,
- wissen, wo du dich über die vordefinierten Methoden in Processing informieren kannst,
- die wichtigsten Methoden zum Erstellen geometrischer Formen kennengelernt haben,
- die wichtigsten Attribute der geometrischen Formen kennen und verändern können,
- wissen und verstehen, wie man Graphiken mit Hilfe von Mausfunktionen Dynamik verleiht.
Inhaltsverzeichnis |
Was ist eine Funktion bzw. Methode?
Processing verfügt über eine größere Anzahl "eingebauter" Funktionen zur Graphikprogrammierung. Eine Funktion oder Methode ist eine Zusammenstellung mehrerer Befehle (Wir werden hier den Begriff Methode verwenden, da es in Java genaugenommen keine Funktionen gibt). Anstatt in einem Programm jeden Befehl einzeln aufzurufen, wenn er benötigt wird, kann eine entsprechende Methode aufgerufen werden, die die auszuführenden Befehle enthält. Bei einem Aufruf der Methode werden alle in ihr zusammengefassten Befehle schrittweise ausgeführt, so als wären sie jeweils einzeln aufgerufen worden. Sehen wir uns den Aufruf einer Methode in Processing genauer an:
Der Methodenaufruf besteht aus dem Bezeichner (line) und den Parametern in der Klammer. Parameter sind dabei Übergabewerte, die ein Unterprogramm, d.h. die aufgerufene Methode, auf bestimmte Werte einstellen. Abgeschlossen wird der Aufruf durch ein Semikolon, das das Ende der Anweisung markiert.
Mit diesem Aufruf der Methode greifen wir auf eine Methode zu, die im Hintergrund folgendermaßen aussieht:
Wie wir sehen, enthält der Kopf der Methode in Klammern die vier Koordinatenwerte, die wir zum Zeichnen der Linie benötigen. Zusätzlich können wir auch den Datentyp der Parameter entnehmen. In diesem Fall sind dies vier Werte vom Typ float, d.h. Fließkommazahlen (Auf Datentypen werden wir im Kapitel Variablen näher eingehen). Im Rumpf der Methode befindet sich die eigentliche Befehlsfolge zum Zeichnen der Linie. Der große Vorteil besteht nun darin, dass uns diese relativ komplizierte Anweisungsfolge nicht zu kümmern braucht. Alles was wir wissen müssen, ist der Name der Methode und die Reihenfolge und der Datentyp der Parameter. Mit diesen Informationen können wir den Service der eingebauten Methode in Processing nutzen. Alle höheren Programmiersprachen bieten zu diesem Zweck mächtige Bibliotheken (libraries), die über ihre Dokumentation für den Programmierer nutzbar werden.
Geometrische Formen in Processing
Die Methoden zur Erstellung geometrischer Formen im Zeichenfenster finden wir in der Dokumentation auf der Processing-Website. Dort erhalten wir zu jeder Methode genaue Angaben zum Gebrauch, insbesondere zu den benötigten Parametern und ihrem Datentyp. Hier haben wir die wichtigsten Methoden zum Erzeugen geometrischer Formen:
Die Anwendung der Methoden soll folgendes Beispiel verdeutlichen. Dabei ist zu beachten, dass später erzeugte Formen über den früher gezeichneten liegen.
Konturen
Die Kontur bzw. Umrandung einer Form kann man mit der Methode stroke() einfärben. Die Dicke der Umrandung kontrolliert man mit der Methode strokeWeight().
Beispiel:
- //Festlegen der Farbe für die Kontur
- stroke(255,0,0);
- //Festlegen der Randstärke (in Pixel)
- strokeWeight(10);
- //Zeichnen der Figur
- rect(50,50,200,100);
In diesem Beispiel erkennt man auch die Standardeinstellungen für die Füllfarbe (weiß) und den Hintergrund (grau). Wird also die Farbe nicht explizit angegeben, greift das Programm auf diese Farben zurück. Die Grundeinstellung für die Konturfarbe ist schwarz.
Will man nun die Figur ohne Kontur zeichnen, kann man dies mit der Methode noStroke() erzielen. Erweitern wir zu diesem Zweck unser Beispiel um folgende Zeilen:
- //Abschalten der Kontur-Methode
- noStroke();
- //Füllfarbe, um die nachfolgende Figur hervorzuheben
- fill(240);
- //Zeichnen des zweiten Rechtecks
- rect(80,80,200,100);
Ohne die noStroke()-Methode würde das Ergebnis folgendermaßen aussehen:
Die Angaben zu Konturfarbe und Konturstärke gelten also bis sie geändert oder abgeschaltet werden.
Füllfarben
Die Frage der Füllfarben betrifft zum einen den Hintergrund des Zeichenfensters, zum anderen die Füllfarbe von Formen.
Mit background() lässt sich der Hintergrund des Zeichenfensters festlegen. Diese Eigenschaft wird üblicherweise in der setup()-Methode festgelegt:
void setup() {
- size(400, 400);
- background(200);
}
Die setup()-Methode ist für die statischen Eigenschaften unserer Graphiken zuständig, die bereits bekannte draw()-Methode dagegen für die dynamischen Aspekte. Diese Methode sorgt dafür, dass die Graphiken ständig neu gezeichnet werden. Ein Beispiel für die Dynamik ist folgendes kleines Programm:
int x=0;
void setup() {
- size(400,400);
}
void draw() {
- background(x);
- x=x+1;
}
Erläuterung: Der Hintergrund des Zeichenfensters ist zu Beginn schwarz (background(0)). Bei jedem Aufruf der Methode draw() wird der Wert für x um 1 erhöht und im nächsten Durchlauf die Hintergrundfarbe an den neuen Wert angepasst. Die Methode draw() aktualisiert das Zeichenfenster 60 mal pro Sekunde. Mit der Methode frameRate() können wir die Geschwindigkeit anpassen:
void setup() {
- size(400,400);
- frameRate(30);
}
Auf diese Weise halbieren wir die Aktualisierungsrate auf 30 mal pro Sekunde.
Die Methode fill() zum Festlegen der Füllfarbe haben wir ebenfalls bereits kennengelernt. Sie wir analog zur Methode stroke() bei den Konturen verwendet:
fill(255, 0, 0); rect(50, 50, 100, 100); rect(150, 50, 100, 100); fill(0, 255, 0); rect(250, 50, 100, 100); |
Die mit fill() festgelegte Füllfarbe bleibt solange gültig, bis sie geändert wird. Dabei ist zu beachten, dass die Methode fill() nur für zweidimensionalen Formen anwendbar ist. Man betrachte folgendes Beispiel:
fill(255, 255, 0); triangle(60, 10, 25, 60, 75, 65); line(60, 30, 25, 80); line(25, 80, 75, 85); line(75, 85, 60, 30); |
Analog zu noStroke() gibt es auch eine Methode noFill() durch die man die Füllfarbe entfernt. Auf diese Weise können wir das obige Ergebnis auch auf folgende Weise erzielen:
fill(255, 255, 0); triangle(60, 10, 25, 60, 75, 65); noFill(); triangle(60, 30, 25, 80, 75, 85); |
Aufgabe 1
Erstelle mit Hilfe des bisher Gelernten eine zusammengesetzte Figur (z.B. Auto, Lokomotive, Gebäude etc.) und nutze dabei möglichst viele der in Processing vorgegebenen Methoden für geometrische Formen.
Aufgabe 2
Informiere dich im Internet über den niederländischen Maler Piet Mondrian (1872-1944) und versuche mit Hilfe von Processing eines seiner Werke zu kopieren.
Aufgabe 3
Erstelle eine Processing-Gemälde im Stil des russischen Künstlers Wassily Kandinsky (1866 - 1944). (Beispiel)
Interaktion
Wir wollen nun unseren Graphiken etwas mehr Dynamik verleihen. Die meisten Anwendungen können mit der Maus gesteuert werden. Zu diesem Zweck muss das Programm die Position der Maus und Mausereignisse (z.B. Mausklick) erkennen. Processing stellt zu diesem Zweck die Systemvariablen mouseX und mouseY zu Verfügung, mit denen wir auf die aktuellen Koordinaten des Mauszeigers zugreifen können.
Statt einer statischen Linie line(0, 0, 100, 100) erhalten wir mit line(0, 0, mouseX, mouseY) eine Linie mit festem Startpunkt und variablem Endpunkt, der von der Position des Mauszeigers abhängt. Dadurch dass unsere Methode draw() unsere Graphik ständig aktualisiert, entsteht der Eindruck einer flexiblen Linie, deren Endpunkt dem Mauszeiger folgt.
Aufgabe 4
Mach dir klar, wodurch der Unterschied zwischen den beiden Graphiken zustande kommt und wie die Programme genau funktionieren.
void setup(){ size(200,200); }
background(200); line(0, 0, mouseX, mouseY); } |
void setup(){ size(200,200); background(200); }
line(0, 0, mouseX, mouseY); } |
Die für die Mausposition ermittelten Koordinatenwerte müssen nicht unbedingt für eine Positionsangabe verwendet werden, sondern können auch an anderer Stelle eingesetzt werden. Im folgenden Beispiel kann durch das Bewegen der Maus die Hintergrundfarbe verändert werden:
void setup(){
size(255,255);
}
void draw(){
background(mouseX, mouseY, mouseX);
}
Aufgabe 5
a) Erzeuge auf der Zeichenfläche ein Quadrat, das sich mit Hilfe des Mauszeigers bewegen lässt.
b) Ändere das Programm so ab, dass folgender Effekt entsteht:
Zusätzlich zu mouseX und mouseY stellt Processing mit pmouseX und pmouseY noch zwei weitere Systemvariablen zur Verfügung. Diese zwei Schlüsselwörter stehen für die vorhergehende (previous) Position des Mauszeigers, d.h. die Positionskoordinaten im vorhergehenden Durchlauf der draw()-Methode. Wir erinnern uns: Die Methode aktualisiert unsere Graphik standardmäßig 60 mal pro Sekunde. Auf diese Weise steht uns eine weitere interessante Interaktionsmöglichkeit zur Verfügung. Wir können beispielweise mit der line()-Methode zeichnen, indem wir sowohl Startpunkt als auch Endpunkt dynamisch verändern, dadurch dass wir den Endpunkt der Linie zur Startpunkt der Linie im nächsten Frame machen.
void setup(){ size(200,200); background(200); }
line(pmouseX, pmouseY, mouseX, mouseY); } |
Nun fehlt uns noch die Möglichkeit, mit einem Mausklick oder einem Tastendruck Einfluss auf unser Programm zu nehmen. Zu diesem Zweck müssen wir uns klar machen, was diese Aktionen bedeuten. Während wir mit setup() die statischen Eigenschaften unseres Programms festlegen, aktualisiert draw() ständig unsere Graphik. Ein Mausklick oder ein Tastendruck sind dagegen Ereignisse. Sie sind Teil des Programmablaufs, die damit verbundenen Aktionen treten aber nur auf, wenn das Ereignis ausgelöst wird. Deshalb brauchen wir weitere Codeblöcke um das erweiterte Programm umzusetzen. Processing stellt uns unter anderem die Methoden mousePressed() und keyPressed() zur Verfügung. Folgendes Beispiel soll die Arbeitweise verdeutlichen:
void setup(){ size(200,200); background(255); }
fill(175); rect(mouseX, mouseY, 15, 15); }
background(255); } |
Erläuterung: In der draw()-Methode haben wir hier keine Anweisungen. Sie sorgt nur dafür, dass das Zeichenfenster aktualisiert wird. Mit einem Mausklick wird die Methode mousePressed() aufgerufen, die dafür sorgt, dass an der Mausposition ein Rechteck gezeichnet wird. Bei Drücken einer Taste wird die Methode keyPressed() aufgerufen, die das Zeichenfenster weiß färbt und dadurch die gezeichneten Rechtecke wieder löscht.
Aufgabe 6
Erstelle ein Programm, das das Schreiben auf der Zeichenfläche mit Hilfe der Maus ermöglicht. Beachte dabei, dass der "Stift" auch abgesetzt werden muss.
Aufgabe 7
Die obige Methode zum Zeichnen eignet sich auch für die Herausforderung des Continuous Line Drawing.
Bilder
Wir können auf der Zeichenfläche auch Bilder (im JPG-, PNG- oder GIF-Format) einfügen. Dazu müssen wir zuerst ein PImage-Objekt erzeugen, das unser Bild aufnimmt. In der setup()-Methode laden wir das Bild mit der Methode loadImage und fügen es in der draw()-Funktion mit der Methode image ein. Vorbereitend müssen wir allerdings im betreffenden Sketchordner einen Unterordner names "data" anlegen und dort unser betreffendes Bild abspeichern.
Beispiel:
PImage photo; void setup(){ size(320, 291); photo = loadImage("meinPhoto.jpg"); } void draw(){ image(photo, 0, 0); }