Um die Verwendung von Variablen zu strukturieren gelten diese stets nur für einen bestimmten Bereich des Programms – einem Block. Blöcke werden durch geschweifte Klammern gebildet. Das bedeutet, dass setup(), draw(), mousePressed(), etc. als auch if-Abfragen und for-Schleifen eigene Blöcke bilden. Das folgende Bild zeigt die Blockstruktur an einem Beispiel.
Variablen können in all diesen Blöcken deklariert und verwendet werden, und sind von dort an nur innerhalb des selben Blocks, sowie Blöcken eines niedrigeren Levels innerhalb dieses Blocks verfügbar. Dieses Konzept nennt man »Gültigkeit von Variablen«.
int zahl = 20; void setup() { size(200, 200); background(255); ellipse(100, 100, zahl, zahl); } void draw() { } void mousePressed() { ellipse(mouseX, mouseY, zahl, zahl); }
Hier ist zahl eine sogenannte Globale Variable, da sie im obersten Block initialisiert wurde und demzufolgen in allen unterliegenden Blöcken verfügbar ist. “Lokale” Variablen sind demzufolge alle Variablen, die nicht global und somit in einigen Teilen des Programms nicht verfügbar sind.
void setup() { int zahl = 5; println(zahl); // ‘5’ } void draw() { println(zahl); // Fehler! zahl }
Globale Variablen können also für alle Funktionen des gesamten Programms verwendet werden, z.B. um verschieden Parameter im Programmverlauf mitzuzählen.
int count = 0; void setup() { size(100, 100); background(0); stroke(255); } void draw() { background(0); count = count + 1; line(0, count, 100, count); if (count == 100) { count = 0; } }
Lokale Variablen werden vorzugsweise bei allen Aufgaben verwendet, die nur in einem kleinen Teil des Programms stattfinden und demzufolge in anderen Teilen nicht benötigt werden. Die Verwendung von lokalen Variablen wann immer es möglich ist, gehört zu einem guten Programmierstil und hilft Fehler zu vermeiden. Desweiteren haben lokale Variablen den Vorteil, das Namen in unterschiedlichen Blöcken mehrfach verwendet werden können.
void setup() { size(200, 200); } void draw() { int zahl = 4; ellipse(random(200), random(200), zahl, zahl); } void mousePressed() { int zahl = 20; ellipse(mouseX, mouseY, zahl, zahl); }
Bereits aus Grafikprogrammen wie Photoshop und Illustrator ist uns das Zeichnen von Pfaden bekannt. Durch das Aneinanderreihen von Punkten legt man eine Abfolge von Linien fest, welche als Außenhaut der Form fungieren. In Processing werden diese Punkte durch den Aufruf von vertex() erzeugt. Begonnen und beendet wird das Zeichnen mit beginShape() und endShape():
// beginne eine Freiform beginShape (); // beginne nur Punkte zu zeichnen, // die aber nicht zu verbinden beginShape (POINTS); // beginne nur Linien zu zeichnen, // die resultierende Fläche aber nicht // zu füllen beginShape (LINES);
// beendet das zeichnen einer Freiform endShape ();
// vertex (x-koordinate, y-koordinate); vertex (30, 40); vertex (90, 20); vertex (60, 70); ...
Processing teilt den Ablauf des Zeichnens von Freiformen demnach in drei Schritte:
In diesem Beispiel wird eine durch fünf Punkte beschriebene Form gezeichnet. Sie ist axial symmetrisch zur y-Achse (Spiegelachse befindet sich auf y=100, die Hälfte der Zeichenfläche) und weiß gefüllt. Rechts, neben dem gerenderten Ergebniss, ist eine Grafik, welche die Lage der formbeschreibenden Punkte verdeutlicht. Wir beginnen oben-links mit dem Punkt (20, 40) und arbeiten uns Schritt für Schritt an der Outline entlang. Jeder Punkt wird dabei durch den Aufruf von vertex(x,y) definiert.
// Größe der Zeichenfläche festlegen size(220, 220); // Kantenglättung aktivieren smooth (); // Zeichnen einleiten beginShape (); // Freiform durch Angabe der Vertexpunkte // beschreiben (muss nicht geschlossen sein) vertex (20, 40); vertex (60, 150); vertex (110, 190); vertex (160, 150); vertex (200, 40); // Zeichnen beenden endShape ();
Mit dem im Vorherigen angesprochenen Parameter des beginShape() Befehls legt man die Art der Verbindungen zwischen den Vertexpunkten für den gesamten Zeichenprozess fest. Wenn die Initialisierung mit beginShape(LINES) durchgeführt wurde, werden immer zwei aufeinander folgende Punkte zu einer Linie verbunden. TRIANGLES erzeugt aus drei Punkten ein Dreieck – ignoriert jedoch in unserem Beispiel den vierten Punkt; QUADS generiert ein geschlossenen Viereck. Alle oben abgebildeten Beispiele wurden auf Basis des unteren Scripts erstellt. Lediglich der Zeichenmodi (im Beispiel LINES) wurde ausgetauscht.
// Kantenglättung aktivieren smooth (); // Zeichnen Einleiten beginShape (LINES); // Zeichnen der vier Vertexpunkte vertex (20, 20); // Linie a, Punkt 1 vertex (40, 80); // Linie a, Punkt 2 vertex (80, 80); // Linie b, Punkt 1 vertex (60, 20); // Linie b, Punkt 2 // Zeichnen Beenden endShape ();
Kurven werden wie die oben kennengelernte Vertexoutline durch eine Reihung von Punkten bestimmt. Jedoch werden die Punkte nicht geradlinig verbunden. Beeinflusst von allen Vertexelementen bewegt sich das “Zeichenwerkzeug” von Anfangs- zu Endpunkt und hinterlässt einen weichen, nicht kantigen, Pfad. Jeder Vertexpunkt wird dabei vom Pfad geschnitten. Processing benötigt mindestens vier Punkte um eine Kurve abzubilden. Durch die Interpolation müssen Anfangs- und Endpunkt doppelt angegeben werden. Anderenfalls ist die Darstellung verschoben.
Bezogen auf das Beispiel “Freiform 1” sind nun die vertex() Aufrufe durch curveVertex() ersetzt worden. Ebenfalls haben wir Start- und Endpunkt dupliziert. Wir erhalten, wie in der bekannten Version, einen Fläche – mit einer abgerundeten Outline.
// Größe der Zeichenfläche festlegen size(220, 220); // Kantenglättung aktivieren smooth (); // Zeichnen einleiten beginShape (); // Freiform durch Angabe der Kurven- // kontrollpunkte beschreiben curveVertex (20, 40); curveVertex (20, 40); curveVertex (60, 150); curveVertex (110, 190); curveVertex (160, 150); curveVertex (200, 40); curveVertex (200, 40); // Zeichnen beenden endShape ();
Im folgenden Beispiel werden drei Punkte einer Kurve definiert. Um keine fehlerhafter Darstellung zu erhalten sind Punkt 1 (0,0) und Punkt 3 (100, 100) doppelt angegeben. Modifiziert wird der Verlauf der Kurve durch die Position der Maus im Sketchfenster. Auf Grundlage derer Koordinaten wird der mittlere Punkt gesetzt.
void setup() { // Kantenglättung aktivieren smooth (); // Füllung deaktivieren noFill(); } void draw () { // Leere die Zeichenfläche background (255); // Zeichnen Einleiten beginShape (); curveVertex (0, 0); curveVertex (0, 0); curveVertex (mouseX, mouseY); curveVertex (100, 100); curveVertex (100, 100); // Zeichnen beenden endShape (); }
Das zweite Beispiel veranschaulicht neben der Verwendung des Befehls curveVertex() die Einbindung einer <em>for</em>-Schleife, sowie der random Funktion. Im globalen Bereich werden zwei elementare Variablen unseres Programms festgelegt:
step repräsentiert den Abstand zwischen den einzelnen Kurvenkontrollpunkten auf der x-Achse – Weg welcher von Schleifendurchgang zu Schleifendurchgang durch Multiplikation mit der Zählvariable i variiert.points steht für die Anzahl an Kontrollpunkten, welche die Kurve beschreiben. int da es nur eine ganze Menge an Punkten geben kann.
Nach der Initialisierung im setup() Block setzen wir noch den Inhalt der Variable step. Dazu teilen wir die Breite der Zeichenfläche durch die Anzahl an Punkten minus eins. Wir erhalte die nötige Distanz zwischen den Kontrollpunkten für eine gleichmäßige Verteilung.
Im draw() Block leeren wir das Sketchfenster zu Beginn. Anschließend weisen wir Processing mit dem Aufruf von beginShape() an aus alle folgenden Punkte ein grafisches Element zu erzeugen. Folgend werden die benötigten Punkte in einer for-Schleife generiert. Diese läuft beginnend von der linken Seite der Zeichenfläche bis zur Rechten – startet dann wieder von Neuem. Innerhalb wird jeweils die x und y Koordinate für den Punkt der aktuellen Position berechnet. Der y-Wert ist dabei zufällig (in den Grenzen der Mausposition) beeinflusst. Um den Ersten und Letzten Punkt doppelt anzugeben gibt es für beide Fälle jeweils eine if Bedingung. Am Ende schließen wir das Erstellen unseres Elementes mit dem Befehl endShape() ab.
/* Lege die beiden globalen Variablen "step" und * "points" fest. Sie stehen außerhalb von setup * bzw. draw und sind deshalb überall im Programm * erreichbar. Der Inhalt von step wird im setup- * Block gesetzt. * Bewege die Maus hoch und runter um die Amplitude * der horizontalen Kurve zu ändern. */ float step; int points = 15; void setup () { // Größe der Zeichenfläche definieren size (500, 140); // Kantenglättung aktivieren smooth (); // Anzahl der Einzelbilder pro Sekunde // auf fünf beschränken frameRate (5); // Lege die Schrittweite pro for-Schleifen- // durchgang auf der x-Achse fest. Abstand // der Kurvenkontrollpunkte auf der x-Achse. step = float (width) / (points - 1); } void draw () { // lösche den Inhalt der Zeichfläche background (255); // Zeichnen einleiten beginShape (); // führe diese Schleife für die Anzahl // von "points" aus (15 mal) – // Kontrollpunkte der Kurve for (int i=0; i < points; i = i + 1) { // berechne die x-Position des Kurvenpunktes float posx = i * step; // berechne die y-Position des Kurvenpunktes float posy = height / 2 + random (-mouseY, mouseY); // füge den Punkt unserer Fläche hinzu curveVertex (posx, posy); // füge den ersten Punkt doppelt ein if (i == 0) { curveVertex (posx, posy); } // füge den letzten Punkt doppelt ein if (i == points - 1) { curveVertex (posx, posy); } } // Beende das Zeichnen der Freiform endShape (); }