Funktionen
Funktionen sind das wichtigste Konzept in Processing. Wir haben oben gesehen, wie man Funktionen aufruft, um dem Computer Anweisungen zu geben:
size( 640, 480 );
ruft die z.B. die Funktion „size“ mit den Parametern „640“ und „480“ auf. Der erste Parameter ist die Breite (width), der zweite Parameter die Höhe (height). Die Bedeutung und Reihenfolge der Parameter muss man jeweils in der Dokumentation nachlesen. Manche Funktionen können mit verschiedenen Parametern aufgerufen werden.
Funktionen können auch Werte zurückliefern, die man z.B. in einer Variablen speichern kann:
float wurzel = sqrt( 81 ); // sqrt() zieht die Quadratwurzel einer Zahl
oder in wiederum in einer Funktion verwenden:
float abstand = sqrt( sq( x2 - x1 ) + sq( y2 - y1 ) );
sq() berechnet das Quadrat einer Zahl, der Ausdruck oben berechnet den Abstand zweier Punkte (Satz des Pythagoras)
Eigene Funktionen schreiben
Man kann Funktionen nicht nur aufrufen, sondern auch eigene Funktionen schreiben. Die folgende Funktion berechnet das Quadrat einer Zahl und liefert es zurück:
float quadrat( float zahl ) { return zahl * zahl; }
die Funktion kann man z.B. so verwenden:
float ergebnis = quadrat( 16 );
- Zuerst gibt man den Typ der Funktion an. Wenn die Funktion keinen Wert zurückgibt, verwendet man „void“, z.B.
void smooth()
- Dann folgt der Name der Funktion, den man selbst wählen kann. Er muss allerdings mit einem Buchstaben beginnen und darf keine Leerzeichen enthalten. Typischerweise beginnen Funktionen mit einem Kleinbuchstaben, wenn man mehrere Wörter kombinieren will, kann man Unterstriche oder Großschreibung verwenden, z.B.
berechne_summe() oder berechneSumme()
- Anschließend die Klammern mit den Parametern. Jeder Parameter wird wie eine Variable definiert, also Typ und Name. Die Parameter werden später beim Aufruf der Funktion durch die Werte ersetzt, die man zwischen die Klammern schreibt. Die Namen der Parameter werden dabei nur innerhalb der Funktion verwendet, sollten aber sinnvoll benannt werden. Funktionen können auch ohne Parameter definiert werden, in diesem Fall bleiben die Klammern leer, z.B.
void smooth()
- Schließlich folgen geschweifte Klammern, zwischen denen die eigentlichen Anweisungen stehen, die ausgeführt werden, wenn die Funktion aufgerufen wird. Die Parameter können dabei innerhalb der Funktion wie ganz normale Variablen verwendet werden.
- Wenn die Funktion einen Wert zurückliefern soll, muss der Befehl „return“ in der Funktion verwendet werden, um die Funktion zu beenden und einen Wert zurückzuliefern. Der Ausdruck nach dem „return“ muss den gleichen Typ haben wie der Typ der Funktion, also wenn die Funktion als „float quadrat“ definiert ist, muss nach „return“ auch ein float Wert stehen, z.B. „zahl * zahl“.
Die obige Funktion „quadrat“ hat also den Typ float und erwartet einen Parameter vom Typ float. Die Funktion multipliziert die Zahl mit sich selbst und liefert das Ergebnis mit return zurück.
Wenn die Funktion mit „quadrat( 16 )“ aufgerufen wird, wird die die Funktion ausgeführt, wobei für den Parameter „zahl“ dann die „16“ eingesetzt wird. Der Variablen „ergebnis“ wird also der Wert 16*16 (= 256) zugewiesen.
Funktionen dienen vor allem dazu, längere, komplexere Programme in Module zu zerlegen und Teile davon für andere Projekte wieder verwenden zu können. Außerdem können Anweisungen, die in einem Programm öfter auftauchen an einer zentralen Stelle definiert werden. Dadurch werden die Programme kürzer und verständlicher.
Beispiel
Hier mal ein etwas komplizierteres Beispiel, das einen Stern zeichnet. Keine Angst, ihr braucht den Code nicht im Detail zu verstehen. Das schöne an Funktionen ist ja, dass man nur wissen muss, was sie tun (und welche Parameter sie erwarten) und nicht wie sie es tun…
void setup() { size( 400, 400 ); smooth() stroke( 0, 0, 255 ); fill( 255, 128, 0 ); } void draw() { background( 128 ); float posX = 200; // x-Position des Sterne float posY = 200; // y-Position des Sterns float minRad = 80; // innerer Radius des Sterns float maxRad = 120; // äußerer Radius des Sterns int numSpikes = 6; // Anzahl der Zacken int numVertex = numSpikes * 2; // wir brauchen doppelt so viele Ecken wie Zacken beginShape( ); // Zeichnen beginnen
for( int i = 0; i <= numVertex; i++ ) { // Schleife für die einzelnen Eckpunkte float angle = 2 * PI * i / numVertex ; // Winkel berechnen, von 0 bis 2*PI float rad = minRad; // rad ist entweder minRadius if ( i % 2 == 0 ) { // oder bei jedem 2. Durchlauf rad = maxRad; // der maxRadius } float x = posX + sin( angle ) * rad; // x-Koordinate ist x-Position + sin * radius float y = posY + cos( angle ) * rad; // y-Koordinate ist y-Position + cos * radius vertex( x, y ); // Eckpunkt zeichnen }
endShape(); }
Wir können nun das eigentliche Zeichnen des Sterns in eine eigene Funktion packen und die Variablen als Parameter übergeben:
void star( float posX, float posY, float minRadius, float maxRadius, int numSpikes) { beginShape( ); int numVertex = numSpikes * 2; for( int i = 0; i <= numVertex; i++ ) { float angle = 2 * PI * i / numVertex ; float rad = minRadius; if ( i % 2 == 0 ) { rad = maxRadius; } float x = posX + sin( angle ) * rad; float y = posY + cos( angle ) * rad; vertex( x, y ); } endShape(); }
Jetzt haben wir eine Funktion star(), die folgende Parameter erwartet:
- Die X- und y-Position des Sterns,
- den inneren und den äußeren Radius und
- die Anzahl der Zacken.
Dann können wir in unserem Programm einfach wie folgt Sterne zeichnen:
void setup() { size( 460, 460 ); smooth(); stroke( 128, 0, 0 ); fill( 255, 128, 0 ); } void draw() { background( 128 ); star( 100, 100, 30, 50, 8 ); star( 200, 200, 40, 45, 30 ); star( 300, 300, 20, 100, 4 ); }
Hier die Beispieldateien zum Download