Hi, schau doch mal hier vorbei, dort steht, was du auf meinem Blog so alles finden kannst

Neue Processing Kategorie

Hi,

in Kürze gibt’s hier auch Artikel zu Processing in denen ich dir Aufgaben stelle, die zu lösen sind. Dabei lernst du, wie Codes zu verändern sind, was für Befehle notwendig sind um zu einem bestimmten Ziel zu gelangen. Allgemein wird es dir dazu dienen dich erstens mehr mit Processing auseinanderzusetzen und zweitens Aufgaben selbstständig zu lösen =)

In einem Artikel stehen die Aufgaben, im darauffolgenden Artikel findest du jeweils den Link mit der Auflösung zu diesen Aufgaben. Die Lösung gibt’s also immer erst im nächsten Artikel.

Bis dahin noch viel Spaß mit Processing
Marius

Processing – Nützliches, Tipps und Tricks

Hi,

heute möcht Ich dir ein paar nützliche Dinge mit Processing zeigen. Das betrifft nicht nur die IDE und spezielle Codes, sondern auch mathematische Tipps. Zugegeben, die IDE (also das Programm in welches du deinen Code reinhackst und über STRG+R ausführst) ist wirklich mehr als klein gehalten, und es gibt auch keine Autovervollständigungen oder sowas wie IntelliSense und eine direkte Projektverwaltung ist auch nicht mit drin, aber abgesehen von dem was Processing nicht kann sehen wir uns lieber an was es kann, denn das ist mehr als auf den ersten Blick vielleicht zu erwarten ist.
Du hast dich vielleicht schonmal gefragt wie Ich den Processing-Code in meinen Beispielen farblich so korrekt in meine Artikel einbringe. Tja, das tolle ist, dass sich der

Processing-Code als HTML kopieren

lässt. Für Leute die selbst Tutorials zu Processing schreiben ist diese Funktion ein wahrer Segen und auch für solche die Ihren Code einfach anderen zeigen möchten ist es praktisch. Markiere mit der Maus einfach die gewünschte Textpassage oder mit STRG+A den kompletten Code und wähle dann im Menü [Edit]->[Copy as HTML], alternativ drücke die Tastenkombi [STRG+Shift+C]. Ein kleiner Bug ist, dass diese Funktion manchmal den Geist aufgibst, das siehst du dann wenn unten im schwarzen Fenster irgendwas in roter Schrift steht, kommt aber in den seltensten Fällen vor und nach einem Neustart von Processing funktioniert es wie gehabt.

Negative in Positive Zahlen umkehren, oder Positive in Negative

Eine weitere coole Sache ist, wie Ich finde, die Funktion abs(), mit dieser kann jede negative Zahl in eine positive gekehrt werden. So wird aus -17 dann 17, aus -7823 wird 7823 und so weiter. Umgekehrt funktioniert das mit der abs()-Funktion nicht, positive Zahlen lassen sich nicht in negative umkehren. Dafür gibt’s aber einen anderen Trick, kennst du vielleicht noch aus der Schule. Man rechnet einfach die gewünschte Zahl mal minus 1. Beide Möglichkeiten demonstriere Ich dir anhand eines kleinen Beispiels:

void setup()
{
  int a, b, c, d;
  a = -8;
  b = 12;
  c = -884;
  d = 9;
  println("a: " + a);
  println("b: " + b);
  println("c: " + c);
  println("d: " + d);
  a = abs(a);
  b = b * -1;
  //Dasselbe wie eine Zeile darüber nur mit kürzerer Schreibweise:
  c *= -1;
  d = abs(d);
  println("-----------");
  println("a: " + a);
  println("b: " + b);
  println("c: " + c);
  println("d: " + d);
}

Schau dir die Ausgabe im schwarzen Fenster unten gut an -du wirst scrollen müssen-, dann wird dir einiges klar werden, schwer ist es eigentlich nicht. Wichtig ist soetwas zum Beispiel wenn du willst dass ein Objekt -beispielsweise ein Rechteck oder eine Ellipse- sobald es an eine Wand oder ein anderes gewünschtes Objekt stößt die Richtung umkehrt und “abprallt”, in einem der letzten Artikel habe Ich das schon eingesetzt.

Was wirklich ätzend ist, wenn du deinen Code schreibst und dich nach einiger Zeit selbst nicht mehr auskennst, weil das ein unstrukturiertes Durcheinander ist und die Zeilen nicht alle sauber eingerückt sind. Zum Glück stellt uns Processing auch dafür eine Möglichkeit zur Verfügung, die

Auto-Formatierung

Mit dieser Funktion wird dein Code automatisch korrekt eingerückt und formatiert. Dafür drücke einfach zwischendurch mal [STRG+T], schon ist dein Code wieder sauber formatiert. Ganz einfache Sache aber ich find’s super =)

Sketch im Vollbildmodus laufen lassen

Schonmal versucht ein Projekt im Vollbildmodus laufen zu lassen? Klar, du kannst den Sketch öfter starten und die Breite und Höhe durch ausprobieren ermitteln und demnach anpassen. Viel einfacher geht das jedoch ohne lästiges ausprobieren, indem du einfach auf die vordefinierten Variablen screen.width und screen.height zurückgreifst und diese als Parameter an die Funktion size() übergibst. Mehr kannst du in der Referenz unter screen nachlesen. screen.width und screen.height haben als Wert automatisch immer die Breite und Höhe des gesamten Bildschirms, also keine PI mal Daumen Angaben mehr =)

Apropos PI mal Daumen, wusstest du dass Processing auch eine

PI Konstante … Konstanten?!

mitbringt? PI kennst du sicherlich, dieses 3,14159…. Damit kannst du spezielle Kreis-Berechnungen und einiges mehr anstellen. Aber nicht nur das, Processing hat noch mehr auf Lager, denn außer PI gibt es noch QUARTER_PI, HALF_PI und TWO_PI. QUARTER_PI ist ein Viertel von PI, HALF_PI die Hälfte von PI und TWO_PI das doppelte von PI. Damit kannst du dir wieder eine Zeile Code sparen in welcher du PI erstmal zur Hälfte, einem Viertel oder einem Doppelten umrechnen musst. Wieso PI-Konstante und nicht PI-Funktion? Ganz einfach, PI ist ein konstanter Wert und keine Funktion in der noch extra etwas berechnet werden müsste. Gehen wir näher auf die Bedeutung von Konstanten ein, eine Konstante ist wie eine Variablen deren Wert nicht geändert werden kann. Wenn du in eigenen Programmen Konstanten verwenden willst geht das auch, du kannst diesen zu Anfangs einen Wert zuweisen der aber im weiteren Programmablauf an keiner Stelle im Code mehr geändert werden kann. Natürlich kann diese Variable von jeder Stelle aus im Code verwendet werden, das schon, aber ändern kannst du sie nicht mehr, und wenn du es versuchst wird das Programm nicht starten weil eine kluge Entwicklungsumgebung bei solchen Sachen sehr pingelig ist ;-) Variablen sind dynamisch, also variabel und Konstanten sind feste, unveränderbare Werte, konstant eben. Auf die Bedeutung dieser und einiger weiterer Spezialbegriffe werde Ich in einem der kommenden Artikel noch zu sprechen kommen, Ich habe vor eine Art Glossar für Fachbegriffe im Zusammenhang mit Processing zu erstellen. Ich werde dabei auf die jeweiligen Stellen in der Processing-Referenz verweisen oder auf Wikipedia verlinken und auch mit eigenen Worten die Begriffe erläutern und hier und dort meinen Senf dazukommentieren. Wo wir gerade vom Kommentieren sprechen, du weißt sicherlich bereits dass du in Processing

Zeilen auskommentieren

kannst, aber Ich finde das dauert immer ewig. Man muss wenn man eine Zeile auskommentieren möchte an den Zeilenanfang springen und dann “//” eingeben, bei mehreren Zeilen dann davor ein “/*” und ans Ende ein “*/”. Einfacher geht das finde Ich, wenn man die zu auskommentierenden Codepassagen einfach mit der Maus markiert und dann im Menü [Edit]->[Comment/Uncomment] wählt. Normaler Code wird dann auskommentiert, umgekehrt, also wenn die Zeilen bereits auskommentiert sind, werden sie wieder zu normalen Codezeilen. Zumindest bei mehrzeiligen Codeteilen lohnt sich hier der Griff zur Maus den Ich als Programmierer zugegeben doch eher meide ;-)

Haufenweise Beispiel-Sketche

Ich habs vor kurzem schon angesprochen und du wirst es vielleicht auch schon entdeckt haben, Processing bringt eine beträchtliche Reihe an Beispiel Sketchen mit, an denen du dich orientieren kannst. Zu finden sind diese im Menü über [File]->[Examples...]. Einfach draufklicken, dauert eventuell ein paar Sekunden bis das Fenster aufgeht. Dort sind massig Beispielprojekte die du öffnen und ausführen kannst. Anfangs eine sehr spannende Sache um auch mal zu sehen was mit Processing alles möglich ist. Du kannst dir aus den geöffneten Sketchen Codepassagen und Algorithem ansehen und herauskopieren, besser ist es aber sicherlich -so hab Ich das gemacht- wenn du dir anschaust was der Sketch macht (einfach mit STRG+R ausführen) und dann versuchen das nach eigenem ermessen nachzuprogrammieren. Aus diesen Beispiel-Projekten kannst du dir viele Ideen für eigene Projekte holen. Es macht echt Spaß, wühl dich mal durch ;-)

Gespeichert … oder doch nicht?

Wenn du Processing startest bekommt der Sketch zunächst einen temporären Dateinamen bestehend aus dem Wort sketch, dem aktuellen Monat, den Tag (als Zahl) und einen Buchstaben, also wenn für den heutigen Tag bereits ein Sketch so abgespeichert wurde “a”, dann “b”, dann “c” und so weiter. Wenn Ich bei mir jetzt in diesem Moment Processing starte habe Ich zwischen dem weißen Codefenster und dem Menü einen Tab in dem folgendes drinsteht: sketch_may09b. Aber ganz egal was dort steht (wieso hab Ich jetzt so weit ausgeholt O.o), du wirst vielleicht bemerkt haben dass wenn du Code eintippst dahinter immer dieses Paragraphen-Zeichen (§) auftaucht. Hast du dich mal gefragt wofür das ist? Falls du nicht von selbst drauf kommst, dieses Zeichen gibt an, dass das Programm (also dein Sketch) so wie es jetzt ist noch nicht abgespeichert wurde. Wenn du also tippst und zwischendurch speicherst, verschwindet dieses §-Zeichen. Sobald du aber auch nur eine Taste drückst wird es wieder angezeigt, da der Sketch mit exakt diesem Inhalt wie er in dieser Sekunde ist noch nicht abgespeichert wurde. So hast du immer im Blick ob dein Sketch gepsichert ist oder nicht. Wenn das §-Zeichen angezeigt wird und du versuchst, Processing zu beenden, wirst du durch einen Dialog gefragt ob du noch abspeichern möchtest. Wird das §-Zeichen nicht angezeigt und du schließt Processing, taucht dieser Dialog nicht auf da ja scheinbar vor kurzem gespeichert und in der Zeit bis zur Schließung von Processing nichts mehr am Code hinzugefügt oder verändert wurde, dein Projekt ist also in jedem Fall vor Datenverlust geschützt (es sei denn du bekommst einen Bluescreen, der Strom ist auf einmal weg oder ein Meteor ist direkt mitten in deinen Rechner geknallt, Ich gehe aber davon aus dass deine Kiste läuft ;-) )

Zu Tipps und Tricks für Processing gibt’s demnächst noch einen Teil (oder mehrere, mal schauen), hoffe Ich konnte dir heute wieder was nützliches beibringen ;-)

Bis dahin
Marius

KategorienAlle, Processing Tags:

Easing Effekt mit Processing (Teil 2)

Hi,

wie schon im vorvorletzten Artikel angekündigt geht es heute darum, unsere Kugel(n) und deren Eigenschaften in eine separate Klasse auszulagern. Wenn das getan ist, können wir beliebig viele Kugeln erzeugen.
Erstellen wir also zuerst einen neuen Tab, vergeben einen Namen für die Datei und schreiben dann die Klasse. Ich nenne sie hier ball. Den Code vom letzen mal hast du hoffentlich noch, ansonsten zieh dir den Artikel einfach nochmal rein. Wenn du das Projekt (den Sketch also) in Processing offen vor dir hast, kannst du eben beschriebenes durchführen. Jetzt schneide schonmal die Codeteile für die Kugel aus und füge sie der Klasse hinzu. Ich habe das mit 1 Funktion gelöst, void display_ellipse(). Die Klasse sollte also so ausschauen bei dir:

class ball
{
  float x, y;
  float targetX, targetY;
  float easing = 0.05;
  float ball_size = 20;

  void display_ellipse()
  {
    targetX = mouseX;
    targetY = mouseY;
    float dx = targetX - x;
    float dy = targetY - y;
    if (abs(dx) > 1)
    {
      x += dx * easing;
    }
    if (abs(dy) > 1)
    {
      y += dy * easing;
    }
    fill(#FFFFFF);
    ellipse(x, y, ball_size, ball_size);
  }
}

In der IDE sollten auch bei dir 2 Tabs offen sein:

Die Klasse steht, was jetzt noch fehlt ist eine Instanz der Klasse in der easing.pde. Das mit den Arrays machen wir gleich, vorerst aber nur um zu sehen dass sich am Ergebnis selbst dadurch nichts geändert hat hier die easing.pde:

void setup()
{
  smooth();
  background(#000000);
  size(300, 300);
  noStroke();
  balls = new ball();
}

ball balls;;

void draw()
{
  background(0);
  balls.display_ellipse();
}

Drücke jetzt STRG+R um den Sketch auszuführen.

Machen wir jetzt ein Array daraus und erstellen wir direkt mehrere Instanzen. Dafür bedienen wir uns der Schreibweise wie auch beim letzen Artikel:

void setup()
{
  smooth();
  background(#000000);
  size(300, 300);
  noStroke();
  for (int i = 0; i < ball_amount; i++)
  {
    balls[i] = new ball();
  }
}

int ball_amount = 10;
ball[] balls = new ball[ball_amount];

void draw()
{
  background(#000000);
  //fill(#000000, 32);
  //rect(0, 0, width, height);
  for (int i = 0; i < balls.length; i++)
  {
    balls[i].display_ellipse();
  }
}

Du siehst, wir erstellen ein Array mit 11 möglichen Werten (wir haben trotzdem nur 10 Kugeln, da in der Schleife die letzte davon unterschlagen wird). Also 10 Kugeln die mit Verzögerung der Maus folgen … richtig? Doch halt … bevor du den Sketch nun ausführst, kommt dir an dem Code irgendetwas komisch vor? Hast du nicht auch das Gefühl dass da irgendwas nicht stimmen kann? Naja, Drück nochmal STRG+R und schau was passiert.

Gemacht? Ich bin sicher dir ist was aufgefallen. Wir haben zwar 10 Kugeln, allerdings ist für alle die selbe Verzögerung eingestellt, denn die easing Variable in class ball ist immer 0.05. Tjoa und was nun? Wir schreiben den Code einfach um und weisen der Variable direkt nach der Instanziierung einen dynamischen Wert zu. Hierfür bedienen wir uns der Schleife in void setup(). Ich hab dafür eine Variable “di” erstellt, die setze Ich auf 0.02. In der Schleife zähle Ich zu “di” immer +0.01 dazu. So haben wir für jede Kugel nicht nur unterschiedliche Werte, sondern sie werden auch inkrementiert. Dadurch erreichen wir, dass die Kugeln der Maus mit einer Art Schlangenbewegung folgen, jede Kugel hat immer ein bisschen mehr oder weniger (je nachdem wo für dich jetzt vorne oder hinten ist) Verzögerung als ihre Vorgängerkugel (oder die nachfolgende).
Wichtig ist, dass wir die Zuweisung von “di” zu “balls.easing” in void setup() machen, wenn wir es in draw() machen würden, würden die Kugeln bei jedem Durchlauf einen anderen Wert für easing haben (aber auch das kannst du probeweise ausprobieren :P ).

Schaun wir uns den Kram jetzt erst mal an:

void setup()
{
  smooth();
  background(#000000);
  size(300, 300);
  noStroke();
  float di = 0.02;
  for (int i = 0; i < ball_amount; i++)
  {
    balls[i] = new ball();
    balls[i].easing = di;
    di += 0.01;
  }
}

int ball_amount = 10;
ball[] balls = new ball[ball_amount];

void draw()
{
  background(#000000);
  //fill(#000000, 32);
  //rect(0, 0, width, height);
  for (int i = 0; i < balls.length; i++)
  {
    balls[i].display_ellipse();
  }
}

Nochmal kurz erklärt, Variable ball_amount gibt an, wieviele Kugeln wir wollen. Auch den Wert kannst du variieren. Bei vielen Kugeln (mehr als 50 oder so) solltest du den Anfangswert für “di” heruntersetzen auf etwa 0.005, und demensprechend auch den Inkrementierungswert (derzeit ja 0.01) auf etwa 0.001.

Im folgenden Codebeispiel habe Ich noch hinzugefügt dass die Kugeln größer werden, außerdem ist die Fenstergröße hier auf 500×500 gesetzt. Außerdem füge Ich Linien zwischen den Kugeln hinzu, und je näher die Kugel ihrer Vorgängerkugel ist, desto dünner wird diese Linie. Und nochwas kommt hinzu, nämlich eine Transparenz der Kugeln. Dafür muss in void draw_ellipse() Die Zeile fill(#FFFFFF); verändert werden in fill(#FFFFFF, 127);.

So nun der Code von easing.pde und ball.pde:

easing.pde:

void setup()
{
  smooth();
  background(#000000);
  size(500, 500);
  noStroke();
  float di = 0.02;
  float bs = 10;
  for (int i = 0; i < ball_amount; i++)
  {
    balls[i] = new ball();
    balls[i].easing = di;
    balls[i].ball_size = bs;
    bs += 1;
    di += 0.005;
  }
}

int ball_amount = 10;
ball[] balls = new ball[ball_amount];

void draw()
{
  background(#000000);
  //fill(#000000, 32);
  //rect(0, 0, width, height);
  for (int i = 0; i < balls.length; i++)
  {
    stroke(255);
    if(i >= 1)
    {
      strokeWeight(dist(balls[i].x, balls[i].y, balls[i-1].x, balls[i-1].y)/100);
      line(balls[i].x, balls[i].y, balls[i-1].x, balls[i-1].y);
    }
    noStroke();
    balls[i].display_ellipse();
  }
}

ball.pde

class ball
{
  float x, y;
  float targetX, targetY;
  float easing = 0.05;
  float ball_size = 20;

  void display_ellipse()
  {
    targetX = mouseX;
    targetY = mouseY;
    float dx = targetX - x;
    float dy = targetY - y;
    if (abs(dx) > 1)
    {
      x += dx * easing;
    }
    if (abs(dy) > 1)
    {
      y += dy * easing;
    }
    fill(#FFFFFF, 127);
    ellipse(x, y, ball_size, ball_size);
  }
}

Damit würde Ich dieses Projekt eigentlich als fertig ansehen. Auch wenn Ich noch einen Haufen Ideen hätte was man da noch alles einbauen könnte =) Mein Ergebnis kannst du dir hier anschauen.

Bis dahin
Marius

KategorienAlle, Processing Tags:

Klassen in Processing

Hi,

ja, heute geht’s um Klassen. Komplizierte Angelegenheit für manche, dennoch, wenn man das Prinzip einmal verstanden hat ist es nicht nur einfach sondern es erleichtert vieles und bietet viel mehr Möglichkeiten wirklich etwas mit Processing anzufangen. Du kannst dir zuallererst eine Übersicht über dieses Thema verschaffen wenn du dir die beiden Wikipedia-Artikel zu Klassen und Objektorientierter Programmierung (OOP) durchliest. Klassen ergeben erst im Zusammenhang mit Arrays einen Sinn.

Sehen wir uns hierzu folgendes Beispielprojekt an:

void setup()
{
  smooth();
  size(300, 300);
  background(#000000);
  ax = int(random(10, width - 10));
  ay = int(random(10, height - 10));
  bx = int(random(10, width - 10));
  by = int(random(10, height - 10));
  cx = int(random(10, width - 10));
  cy = int(random(10, height - 10));
}

int ax, ay, bx, by, cx, cy;
int adx = 1;
int ady = 1;
int bdx = 1;
int bdy = 1;
int cdx = 1;
int cdy = 1;
int r = 10;

void draw()
{
  background(#000000);
  ax+=adx;
  ay+=ady;
  bx+=bdx;
  by+=bdy;
  cx+=cdx;
  cy+=cdy;
  if(ax>=width-r||ax<=r){adx*=-1;}
  if(ay>=height-r||ay<=r){ady*=-1;}
  if(bx>=width-r||bx<=r){bdx*=-1;}
  if(by>=height-r||by<=r){bdy*=-1;}
  if(cx>=width-r||cx<=r){cdx*=-1;}
  if(cy>=height-r||cy<=r){cdy*=-1;}
  fill(255);
  noStroke();
  ellipse(ax, ay, r, r);
  ellipse(bx, by, r, r);
  ellipse(cx, cy, r, r);
}

Es funktioniert. Abgesehen davon … schau dir mal an wieviel Schreibarbeit das ist. Stell dir vor du würdest hier nun 10 Kugeln haben wollen, dann bräuchtest du für die Richtung noch 7 weitere Variablen, und 14 weitere für die Koordinaten. Ich würde da sicher bald den Überblick verlieren. Und genau dafür sind Klassen da, damit soetwas nicht passiert, bzw. gar nicht erst nötig ist.
Eine Klasse zu erstellen ist nichts anderes als die Definition und Funktionalität des Objektes in einen eigenen Bereich auszulagern. Dieses Objekt wird dann im Projekt instanziiert, beliebig oft wenn man es möchte.

Um die Funktionalität und die Eigenschaften dieser Kugeln in eine eigene Klasse auszulagern müssen wir erst einmal eine erstellen. Das geht entweder direkt im Code oder du legst für die neue Klasse gleichzeitig auch eine neue .pde-Datei an. Vorteilhafter ist es wenn man es in eine neue Datei packt, allein schon wegen der Übersichtlichkeit.

Eine Klasse wird mit “class” eingeleitet, allerdings kommen dahinter keine Klammern, da an eine Klasse direkt keine Werte übergeben werden. Warum? Weil eine Klasse keinen Rückgabewert (return) hat, auf die Variablen und Eigenschaften der Klasse greifen wir über Klassenname.Variable zu, und das geht erst nachdem wir eine Instanz der Klasse im Projekt instanziiert haben -> Objektinstanz.

Schreiben wir also alles was wir benötigen um dasselbe Ergebnis zu bekommen, nur eben diesmal ausgelagert in eine Klasse. Wir brauchen wieder die X/Y Koordinaten und die Richtung, dann noch eine Funktion für die Kollision. So sieht die Klasse nun aus:

class ball
{
  int posX, posY;
  int dx, dy;
  int kugel_radius = 25;
  
  void einstellungen()
  {
    dx = 1;
    dy = 1;
    posX = int(random(kugel_radius, width - kugel_radius));
    posY = int(random(kugel_radius, height - kugel_radius));
  }
  
  void zeige_kugel()
  {
    fill(#FFFFFF);
    noStroke();
    ellipse(posX, posY, kugel_radius * 2, kugel_radius * 2);
  }
  
  void kollision()
  {
    if(posX >= width - kugel_radius || posX <= kugel_radius)
    {
      dx *= -1;
    }
    if(posY >= width - kugel_radius || posY <= kugel_radius)
    {
      dy *= -1;
    }
    posX += dx;
    posY += dy;
  }
}

Du siehst, Funktionalität, Kollision und Anzeige der ellipse sind allesamt eingestellt. Die Funktion einstellungen() ist nur dafür da um die Startparameter festzulegen, kann man aber auch gleich bei der Deklaration machen. Daher wird später diese Funktion auch nur einmal aufgerufen, und zwar in void setup().

Schön, damit können wir kaum was anfangen, schließlich wird in Processing void setup() und void draw() ausgeführt, und dort ist noch keine Instanz der Klasse erstellt worden. Folglich wird also gar nichts passieren.

Wir wollen aber ja, dass was passiert. Die Klasse ist bei der Instanziierung selbst Datentyp mit dem das Objekt instanziiert wird. Das heißt, die Variable die erstellt wird ist vom Typ ball (zumindest hab Ich die Klasse bei mir so genannt). Eine Zahl ist vom Typ int oder float, wir deklarieren also int variable = 12;
Bei der instanziierung ist es beinahe genauso, wir schreiben

ball balls;

Was die Deklaration(bei normalen Variablen) von einer Instanziierung unterscheidet ist das Schlüsselwort new. Erst dadurch wird das deklarierte balls auch Instanz der Klasse. Die Deklaration erfolgte global, die Instanziierung möchte Ich aber lieber in void setup() schreiben:

  balls = new ball();

Jetzt haben wir alles was wir brauchen. Ich habe die Instanz der Klasse ball einfach balls genannt. Nun können wir über Klassenname.Funktionsname einfach die Funktionen aus Klasse ball aufrufen. Funktion einstellungen() rufen wir in void setup() auf, den Rest in void draw().

Der komplette Code:

void setup()
{
  smooth();
  size(300, 300);
  background(#000000);
  balls = new ball();
  balls.einstellungen();
}

ball balls;

void draw()
{
  background(#000000);
  balls.zeige_kugel();
  balls.kollision();
}

So, das war's, führe den Code bei dir aus und schau was passiert :-)

Das mit den Klassen ist eine tolle Sache, aber was habe Ich vorhin gesagt? Sie ergeben erst in Verbindung mit Arrays richtig Sinn. Arrays haben wir im letzten Artikel behandelt. Und wie können wir das hier nutzen? Nun, ganz einfach, wir machen aus balls ein Array (die Kreise werde Ich im nächsten Schritt etwas kleiner gestalten). So können wir soviele Bälle durchs Fenster fliegen lassen wie wir möchten, und müssen dabei alles nur ein einziges mal schreiben.

Die Klasse ball bleibt dieselbe, an dieser ändert sich ja nicht. Nur in unserem Hauptfenster ändert sich die deklaration geringfügig. Wir schreiben also die Deklaration in ein Array um, in void setup() müssen wir anschließend in einer Schleife das Array durchgehen und jedes Objekt instanziieren.

Wenn jeder Wert im Array (Objektinstanzen) instanziiert wurde, kann jederzeit eine Funktion der Klasse ball über balls[index].funktionsname() und jede Variable über balls[index].variable geändert werden.
So können beispielsweise Zufallswerte für Geschwindigkeit und Farbe einzelner Kugeln festgelegt werden.

void setup()
{
  smooth();
  size(500, 500);
  background(#000000);
  for (int i = 0; i < balls.length; i++)
  {
    balls[i] = new ball();
    balls[i].einstellungen();
  }
}

ball[] balls = new ball[20];

void draw()
{
  background(#000000);
  for (int i = 0; i < balls.length; i++)
  {
    balls[i].zeige_kugel();
    balls[i].kollision();
  }
}

So einfach geht das. Mit balls[i] können wir nun auf alle Variablen, Funktionen und Eigenschaften der Klasse ball zugreifen. Wir haben in dem Beispiel 20 mal eine Objektinstanz der Klasse ball erstellt die alle aus dem Array heraus über balls[index] angesprochen werden können, so kann zum Beispiel die 3 Kugel vergrößert werden wenn wir schreiben balls[2].kugel_radius = 20; (Index 2 = dritte Kugel, da ja index 0 = 1. Kugel, index 1 = 2. Kugel, index 2 = 3. Kugel etc..).

Du siehst, mit Klassen zu arbeiten macht Spaß und es lassen sich vielerlei Ergebnisse praktischer realisieren als ohne. Du musst die Funktionalität eines Objektes (wie hier beispielsweise die Bewegung und das abprallen an den Wänden etc..) nur einmal schreiben, die Klasse ist somit ein Programm für sich. Und über das Hauptprogramm kannst du Objektinstanzen der Klasse erstellen und beliebig viele Objekte erzeugen.

Wir werden in den nächsten Projekten noch viel mit Klassen umsetzen und herumexperimentieren. Versuche zur Übung doch einmal, 5 Rechtecke mit Füllfarbe deiner Wahl irgendwo auf dem Fenster zu platzieren (sie sollen sich nicht bewegen). Schreibe dazu dann eine Funktion mit der du ein Rechteck mit Mausklick nehmen und per Drag&Drop an eine andere Stelle platzieren kannst. Auch immer gut zum nachforschen sind die Samples die Processing von sich aus mitbringt, diese kannst du im Menü über "File->Examples..." erreichen. Lade dir ein paar Projekte hieraus und schau an wie sie funktionieren, wie das Ergebnis aussieht und versuch das nach eigenem ermessen ohne nachschauen im Quellcode umzusetzen, mir persönlich macht das Spaß, man kommt automatisch auf neue Ideen die man umsetzen möchte und verliert so auch nicht den Spaß wenn mal was nicht gleich so klappt wie man's gern hätte.

Bis demnächst
Marius

KategorienAlle, Processing Tags:

Favicon Plugin made by Alesis