zurück

Processing:
Objektorientierte Programmierung

Ein einfaches Programm

Wir wollen ein simples Programm schreiben. In einem Fenster soll eine bunte Kreisscheibe gezeichnet werden. Ihr Ort und ihre Farbe sollen zufällig gewählt werden, ihr Radius wird von uns beim Programmstart gesetzt.

float x, y;       // Mittelpunkt des Kreises
int r;            // sein Radius
color c;          // seine Farbe


void setup() {
   size(200,200);
   ellipseMode(RADIUS);
   colorMode(HSB,360,100,100);
   x = random(width);
   y = random(height);
   c = color(random(255),random(255),random(255));
   r = 10;
}

void draw() {
   background(0);
   paintKreis();
}  

 
void paintKreis() {
   noStroke();   
   fill(c);
   ellipse(x,y,r,r);
}  

Wirklich ganz einfach. Und so sieht das Ganze dann aus:

 

Und jetzt interaktiv

Die Kreisscheibe soll nun auf uns reagieren können, indem sie dem Mauszeiger langsam nachläuft. Dazu basteln wir eine Funktion namens update(), die die Koordinaten x und y entsprechend anpasst. Das Nachlaufen steuern wir mit einer Tempo-Variable, die wir zufällig zwischen 0.01 und 0.1 wählen.

float x, y;       // Mittelpunkt des Kreises
int r;            // sein Radius
color c;          // seine Farbe
float tempo;      // easing-Variable


void setup() {
   size(200,200);
   ellipseMode(RADIUS);
   colorMode(HSB,360,100,100);
   x = random(width);
   y = random(height);
   c = color(random(255),100,100);
   tempo = random(0.01,0.1);
   r = 10;
} 
 
void draw() {
   background(0);
   updateKreis();
   paintKreis();
}  

 
void paintKreis() {
   noStroke();   
   fill(c);
   ellipse(x,y,r,r);
}
 
void updateKreis() {
   float dx = mouseX-x;
   float dy = mouseY-y;
   x += tempo*dx;
   y += tempo*dy; 
}  

Das Ganze mit mehr Übersicht

In diesem Programm werden zwei Aufgaben gelöst. Erstens wird das Fenster für die Ausgabe erzeugt und sein Inhalt regelmäßig aufgefrischt. Zweitens gibt es Programmzeilen, die mit der Kreisscheibe zu tun haben.

Es wäre doch sehr elegant, könnten wir diese zwei Teile möglichst komplett voneinander trennen. Dazu bekommt unser Processing-Sketch zwei Dateien - eine namens kreisprogramm (das ist auch der Name unseres Sketch-Folders) für das 'Hauptprogramm', eine zweite namens kreisklasse für die Kreisscheibe. Das könnte nun so aussehen:

kreisprogramm.pde

void setup() {
   size(200,200);
   erzeugeKreis(10);
} 
 
void draw() {
   background(0);
   updateKreis();
   paintKreis();
} 

kreisklasse.pde

float x, y;       // Mittelpunkt des Kreises
int r;            // sein Radius
color c;          // seine Farbe
float tempo;      // easing-Variable


void erzeugeKreis(int radius) {
   ellipseMode(RADIUS);
   colorMode(HSB,360,100,100);
   x = random(width);
   y = random(height);
   c = color(random(255),100,100);
   tempo = random(0.01,0.1);
   r = radius;
} 
 
void paintKreis() {
   noStroke();   
   fill(c);
   ellipse(x,y,r,r);
}
 
void updateKreis() {
   float dx = mouseX-x;
   float dy = mouseY-y;
   x += tempo*dx;
   y += tempo*dy; 
}  

Die Ausgabe des Programms ist genau gleich wie oben, aber wir haben den Programmtext in zwei logisch getrennte Einheiten aufgeteilt.

Und jetzt als Klasse

Die objektorientierte Programmiertechnik erlaubt es uns, noch einen wichtigen Schritt weiter zu gehen. Es ist möglich, die Funktionen, die mit dem Kreis arbeiten, und die Variablen, die mit dem Kreis zu tun haben in ein Paket zusammenzupacken.

Dazu denken wir so: Was ist unsere Kreisscheibe:
- sie hat EIGENSCHAFTEN : Mittelpunkt, Radius, Farbe, Tempo. Diese Variablen werden als ATTRIBUTE der Kreisscheibe bezeichnet.
- sie hat FÄHIGKEITEN : sie ändert ihren Ort, sie kann gezeichnet werden. Diese Funktionen bezeichnet man als METHODEN.

Damit hätten wir alles fixiert, was wichtig ist. Wir haben ein MODELL geschaffen, dieses wird als KLASSE bezeichnet. Um nun eine Kreisscheibe zu erhalten, muss sie anfangs ERZEUGT werden (mithilfe des KONSTRUKTORS aus der Klasse ABGELEITET), wodurch wir ein konkrete verwendbares Exemplar aus der Klasse erzeugen - ein OBJEKT.

Zur Schreibweise: während Variablennamen immer mit einem Kleinbuchstaben beginnen, pflegt man Klassennamen groß zu schreiben. Auf Attribute und Methoden greift man zu, indem man an den Objektnamen einen Punkt setzt und dann den Attribut- bzw. Methodennamen anhängt.

kreisprogramm.pde

Kreis scheibe;            // das Objekt soll scheibe heißen
 
void setup() {
   size(200,200);
   scheibe = new Kreis(10);
} 
 
void draw() {
   background(0);
   scheibe.update();
   scheibe.paint();
}  

kreisklasse.pde

class Kreis {
   
   float x, y;       // Mittelpunkt des Kreises
   int r;            // sein Radius
   color c;          // seine Farbe
   float tempo;      // easing-Variable


   Kreis(int radius) {            // das ist der Konstruktor
      ellipseMode(RADIUS);
      colorMode(HSB,360,100,100);
      x = random(width);
      y = random(height);
      c = color(random(255),100,100);
      tempo = random(0.01,0.1);
      r = radius;
   } 
 
   void paint() {
      noStroke();   
      fill(c);
      ellipse(x,y,r,r);
   }
 
   void update() {
      float dx = mouseX-x;
      float dy = mouseY-y;
      x += tempo*dx;
      y += tempo*dy; 
   }
}  

Sieht doch optisch gut aus!

Und noch ein positiver Nebeneffekt: die Klassenvariablen x,y,r,c und tempo waren ursprünglich Variable, die im Hauptprogramm definiert wurden, und damit sichtbar für alle weiteren Funktionen. Andere Programmteile mussten berücksichtigen, dass diese Variablennamen bereits vergeben sind.

Das ist nun anders - die Attribute sind innerhalb der Klasse GEKAPSELT und damit nach außen unsichtbar geworden.

Jetzt wird es COOL!

Wenn wir eine Kreisscheibe erzeugen können, können wir auch viele herstellen. Die Klasse muss dazu nicht verändert werden. Wir bereiten einfach im Hauptprogramm eine ganze Liste von Kreisen vor und bearbeiten sie gemeinsam in for-Schleifen.

kreisprogramm.pde

Kreis[] scheiben = new Kreis[100];     // 100 Kreisscheiben
 
void setup() {
   size(200,200);
   for (int i=0; i<scheiben.length; i++) scheiben[i] = new Kreis(10);
} 
 
void draw() {
   background(0);
   for (int i=0; i<scheiben.length; i++) {
      scheiben[i].update();
      scheiben[i].paint();
   }
}  

Das ist nett - 100 Kreisscheiben brauchen (fast) nicht mehr Schreibarbeit als eine einzige. Ohne Klassen hätten wir 100 Variable für die Radien, 100 für die x-Werte, 100 für die y-Werte, ... benötigt. Gut, dass es die objektorientierte Programmiertechnik gibt!

Du kannst Dir den Quelltext des Sketches runterladen. Ich hab noch ein paar kleine Änderungen angebracht, damit sich folgendes Verhalten für 50 Kreisscheiben ergibt: