Easing Effekt mit Processing (Teil 2)

By | 8. Mai 2012

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);
  }
}

Hier noch live anzuschauen:

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 auch noch hier anschauen.

Bis dahin
Marius

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *