Schlagwort-Archiv: marius

Email lässt sich nicht öffnen oder löschen – [Kein Absender] vom 01.01.1970

Hi,

neulich hatte ich dieses Problem, dass keine Mails mehr auf meinem iPhone eingegangen sind. Es stand dran, dass die Mail keinen Absender hat und leer wäre (Diese E-Mail hat keinen Inhalt), außerdem wohl vom 01.01.1970 laut Datum ( Hintergrundlektüre ). Blöd war außerdem, dass sich die Mails nicht löschen ließen.
Ich hab’ erstmal viel gegoogelt, was mir aber kaum was gebracht hat. Deswegen hab’ ich das Teil einfach ausgeschaltet und danach wieder ein. Scheint auch was gebracht zu haben, denn die Mails die ich bekommen habe wurden wieder normal angezeigt. Dachte das mit diesem “Nach einem Neustart ist alles wieder gut” sei eigentlich so ein Windows-Ding, aber hier hat es geholfen, und ich hoffe dass dir das auch was bringt :-)

Grüße
Marius

[GMX] Fehler beim senden der Nachricht – der Mailserver antwortete 5.7.0 Authentication expired (mp033)

Hi,

was ist nun wieder los? Du willst dir in deinem Email-Client ein Mailkonto anlegen, die Nachrichten treffen ein aber beim versenden bekommst du so eine Fehlermeldung um die Ohren geklatscht:

Fehler beim senden der Nachricht – der Mailserver antwortete 5.7.0. Authentication expired (mp033)

Nun, das liegt daran dass das Kennwort für dieses Konto vermutlich vom Provider zurückgesetzt wurde (aus welchen Gründen das auch bei dir der Fall sein mag). Wenn du also die Möglichkeit hast, logge dich über die Weboberfläche ein (in meinem Fall war das bei GMX). Hier wirst du möglicherweise gezwungen, ein neues Passwort zu vergeben, andernfalls mach es einfach, auch wenn es nicht gefordert wird.
Trage das neu vergebene Kennwort anschließend in deinem Email-Client ein. Wenn alles klappt, klappt’s jetzt wieder :-)

Gruß
Marius

[Lösung] HTML-Form wird nach Enter nicht abgesendet (InternetExplorer)

Hi,

neulich wollte ich für eine Seite eine Suchfunktion implementieren, hierfür sollte ein Textfeld und ein Button verwendet und die im Textfeld enthaltenen Daten der Form via POST zur Zielseite übertragen werden.
Wie man es von Browsern gewohnt ist, wird irgendwas ins Textfeld getippt und anschließend Enter gedrückt, um das Formular abzusenden. Das hat im InternetExplorer (ja, manchmal überprüf’ ich ob selbst der IE meine Seiten korrekt darstellt .. wenn ich Lust dazu hab’) natürlich mal wieder nicht funktioniert wie es sollte.

Das ist ein bekannter Fehler, bzw. eine bekannte Eigenart des IE die sich ergibt, wenn man in seiner Form (

) außer dem SubmitButton nur ein einziges Textfeld mit drin hat.

Abhilfe kann hier schaffen, ein zweites input-Feld hinzuzufügen. Da es offenbar nicht benötigt wird (sonst hättest du das Problem schließlich nicht) kann man dieses unsichtbar und -zur Sicherheit- auf DISABLED setzen. Beispiel:

Sobald du das hast, funktioniert das Absenden des Formulars durch drücken von Enter auch schon wieder.
Ich hoffe auch dir wird das nützlich sein :-)

Gruß
Link

[PHP] Datei herunterladen anstatt anzusehen

Hi,

jeder kennt’s. Da will man Files zum Download anbieten – und dann scheitert’s an Textdateien, die sich bloß im Browser anzeigen lassen. Aber es funktioniert trotzdem … wenn man weiß wie’s funktioniert ;-) Unf funktionieren tut es eigentlich ganz einfach:

	$file = "./testdatei.txt";
	$fsize = filesize($file);
	header("Content-Type: application/force-download");
	header("Content-Disposition: attachment; filename=Datei.txt");
	@readfile($file);

Ich hab hier mal ein Testprojekt hochgestellt, probier’s aus.
Vielleicht könnte dir das nützlich sein :-)

Bis dahin
Marius

[Lösung] MySQL Autoincrement Wert anpassen / verändern

Hi,

ist es euch schonmal passiert dass ihr in eurer MySQL-Datenbank ausversehen Mist eingetragen habt? Und dass dann die ID nicht mehr gestimmt hat die über die Autoincrement-Spalte generiert wurde? Vielleicht, vielleicht auch nicht. Mir ist es passiert. Was tut man in einem solchen Fall? Dass der AutoIncrement bei einem anderen geänderten Wert weiterlaufen soll lässt sich so nämlich nicht einstellen (was ja, wenn man bedenkt wofür der Autoincrement überhaupt da ist auch gut ist).
Jetzt hab ich also in der Datenbank einen Datensatz, der da so gar nicht rein sollte (wie und warum das auch immer passiert). Klar, ich könnte diesen manuell löschen, das ginge. Was aber dann nicht mehr gegeben ist, ist die fortlaufende Nummer. Manchmal ist es wichtig dass die Einträge lückenlos sind oder gar sein müssen. Mit einem Trick geht es aber trotzdem.

Stellen wir uns folgende Werte vor:

ID Produkt
0 Apfel
1 Feuerzeug
2 Chips
3 Cola
4 Brötchen
5 Zeitschrift

und nehmen wir an, Zeitschrift wäre der Datensatz der da nicht hingehört. Lösche diesen nun:
Jetzt könntest du den Datensatz von neuem eintragen. Allerdings wird dieser dann ID #6 haben, an die #5 kommen wir nicht mehr. Was nun zu tun ist:

Schritt 1
Datenbankoberfläche öffnen (phpMyAdmin o.ä.)

Schritt 2
Betreffende Tabelle exportieren, danach löschen (nicht leeren).

Schritt 3
Export in Datei öffnen. Dort wo der CREATE TABLE-Befehl ist findest du unten sowas ähnliches wie

ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

Den Wert änderst du in “5″. Speichere die Datei

Schritt 4
Importiere die Datei nun, oder kopiere den Inhalt des Exportes und führe ihn über die SQL-Funktion aus.

Und das war’s. Im Endeffekt haben wir jetzt die Tabelle und deren enthaltene Datensätze gelöscht und wieder neu importiert. Und zuvor noch die ID geändert.
Was du noch machen könntest: den Export direkt ohne den AutoIncrement erstellen (Haken rausnehmen). Ich weiß zwar nicht ob der dann bei Null anfängt oder nach der höchsten ID weitermacht, aber ich würd’s nicht darauf ankommen lassen und die zuerst beschriebene Methode anwenden.

Vielleicht hilft dir dieser Tipp ja :-)

Viele Grüße
Marius

[Lösung] Fax versenden ohne 0 vorzuwählen

Hi,

wenn man (in der Firma, kann aber auch Zuhause sein) eine TK-Anlage hat, ist es oftmals so, dass man eine 0 (Null) vorwählen muss, um externe Anrufe zu tätigen oder Faxe versenden zu können.
Das kann lästig sein (man muss eine Taste mehr drücken :O) und ist zudem -so finde ich- fehleranfällig. Denn nicht jedem Laien ist klar, dass da eine zusätzliche Null vorgewählt werden muss, und so wird das Fax vermutlich dann nie beim Empfänger ankommen..

Praktischerweise hatte ich vor kurzem ebendiese Aufgabenstellung, wie kann ich ein Fax versenden, ohne die Null vorzuwählen? Ganz einfach. Über das Panel in die Konfiguration der TK-Anlage gehen und dort nach der Option “spontane Amtsholung” suchen. Es kann auch “automatische Amtsholung” heißen. Dort also den Haken setzen (oder über eine Auswahlbox diese Option nehmen) und die Konfiguration sichern und zur TK-Anlage senden, Fertig.

Ist das geschehen, können externe Anrufe getätigt und Faxe versendet werden, ohne dass eine zusätzliche Null vorgewählt werden muss=)
Hoffe dass das jemandem hilft der es noch nicht weiß ;-)

Grüße
Marius

Verschwindende Objekte – Processing und Arrays

Hi,

heute hab’ ich mich mal an eine Sache rangemacht die ich schon längst mal selbst in Processing realisieren wollte. Irgendwo hatte ich mal gesehen wie in einem Sketch eine Ellipse der Maus folgte, und diese dann Spuren hinterherzog die langsam verschwanden. Das fand ich ziemlich gut gemacht, und heute hatte ich spontan den Einfall, das selbst zu versuchen. Vorab möchte ich dir anhand eines Screenshots zeigen, wie es am Ende aussehen wird:

Verschwindende Formen

Verschwindende Formen

Ich schlage vor, wir fangen einfach mal an. Dafür muss aber erst einmal geklärt sein, was wir wollen und wie es funktioniert. Also was wollen wir, bzw. was will ich … ich will, dass Ellipsen meiner Maus folgen, diese aber mit der Zeit auf der Strecke kleiner werden bis sie weg sind. Aussehen wird es am Ende so wie in meinem Sketch auf OpenProcessing, hier der Sketch zum ausprobieren:

Bewege einfach mal die Maus um zu sehen was passiert. Drücke die Tasten 1, 2 oder 3 um den Modus für die Anzeige zu wechseln (klick’ vorher am besten einmal in den Sketch, damit dieser den Fokus hat).
Cool und wie funktioniert das?! …… also ich hab’ mir bei meinen Überlegungen gedacht wir brauchen auf jeden Fall schonmal temporäre Variablen, die nur dazu genutzt werden um die “alten” Ellipsen zu zeichnen, also die, die ich mit der Maus bereits abgefahren habe. Denn die werden ja dann mit der Zeit immer kleiner. Eine Variable wird dafür natürlich nicht reichen, wir brauchen eine für X und Y, damit wir die Ellipsen im Raum platzieren können. Und Variablen reichen dafür eh nicht, was wir brauchen sind Arrays. Würden wir nur eine Variable nehmen, dann könnten wir es höchstens noch gerade so machen, dass jede nachziehende Ellipse erst gezeichnet wird, wenn die vorherige komplett verschwunden ist, wir würden also im Endeffekt immer nur eine sehen. Und das wollen wir nicht, was wir wollen ist ja, dass überall dort wo wir mit der Maus sind/waren, Ellipsen auftauchen die dann wieder verschwinden (kleiner werden bis sie weg sind). Also ein Array in dem wir die X- und eines in dem wir die Y-Koordinaten ablegen.
Und du brauchst noch eine Variable “count”, die am Ende von void draw() immer um +1 hochgezählt wird. Die aktuellste, neueste Ellipse hat als Koordinaten im Array dann immer den größten Index, also “count”.

Bevor es daran geht, dafür zu sorgen dass die Ellipsen kleiner werden, musst du dir erst einmal vorstellen können, was bis dahin passiert. Wir bewegen quasi die Maus und zeichnen an jede Position, an dem die Maus ist, eine Ellipse. Klar kannst du’s auch ohne Array machen und lediglich ellipse(mouseX, mouseY, 50, 50); schreiben, allerdings würde dir das wenig bringen, am Anfang von void draw() wird immer background(0); ausgeführt, man würde davon also nichts sehen. Deswegen die Arrays, damit die Koordinaten aus dem Array in einer Schleife abgefragt, und die Ellipsen dann jedes mal neu gezeichnet werden können.
Lassen wir die Maus einmal folgende Koordinaten fahren:

Position 1: X=6 Y=193
Position 2: X=6 Y=192
Position 3: X=6 Y=191
Position 4: X=6 Y=190
Position 5: X=6 Y=189
Position 6: X=7 Y=189
Position 7: X=7 Y=188
Position 8: X=8 Y=188
Position 9: X=8 Y=187
Position 10: X=8 Y=186
Position 11: X=9 Y=186
Position 12: X=9 Y=185
Position 13: X=10 Y=184
Position 14: X=11 Y=182
Position 15: X=11 Y=181
Position 16: X=12 Y=180
Position 17: X=13 Y=179
Position 18: X=14 Y=178
Position 19: X=15 Y=176
Position 20: X=16 Y=175
Position 21: X=17 Y=174
Position 22: X=18 Y=173
Position 23: X=19 Y=173
Position 24: X=19 Y=172
Position 25: X=20 Y=172
Position 26: X=21 Y=171
Position 27: X=22 Y=171
Position 28: X=23 Y=170
Position 29: X=24 Y=169
Position 30: X=26 Y=169
Position 31: X=28 Y=168
Position 32: X=29 Y=168
Position 33: X=31 Y=167
Position 34: X=32 Y=167
Position 35: X=34 Y=167
Position 36: X=36 Y=166
Position 37: X=38 Y=166
Position 38: X=40 Y=166

Für dieses Beispiel hab ich die Maus einfach in paar Sekunden bewegt und die Koordinaten aufgezeichnet. Das sind also die einzelnen “Stationen” die die Maus abgefahren hat, und nun stell dir vor, dass diese Koordinaten jedes mal in ein Array geschrieben werden. Array für X-Koordinaten hätte an Index 0 also den Wert 6, das Array für Y-Koordinaten den Wert 193. Durch eine extra Variable (-> count) bestimmen wir noch den Index, der um 1 hochgezählt wird. Zu Anfangs lege ich für count den Wert 0 fest.

Schaun wir mal was void draw() macht:
count hat den Wert 0, Array (ich nenne die Arrays einfach mal X und Y) X hat an Index “count” (also Null) den Wert 6, Array Y hat an Index “count” (also Null) den Wert 193. Daraus folgt:
X[count] = 6
Y[count] = 193

Count wird um +1 hochgezählt:
count++;
void draw() ist am Ende angelangt, alles also wieder von vorn..
Nächster Durchlauf in void draw(), count hat mittlerweile den Wert 1, Array X bekommt an Index 1 (->count ist ja 1) den Wert 6, Array Y bekommt an Index 1 den Wert 192. count wird hochgezählt und hat jetz den Wert 2, void draw() ist am Ende, alles wieder von vorne …. und so weiter. Unser Array wird mit der Zeit ziemlich voll.

Aber zum wesentlichen: In einer Schleife wird das Array durchlaufen, logischerweise nur soweit wie das Array Werte hat, bzw. die Anzahl des Wertes der Variable “count”. In der Schleife dann werden die Ellipsen gezeichnet. Im Code sieht es dann in etwa so aus:

/**
 * Verschwindende Formen
 *
 * Dies soll anhand eines coolen Beispiels zeigen, was
 * man mit Arrays alles anstellen kann.
 *
 */

void setup()
{
  //Das Übliche, schwarzer Hintergrund, Größe und smooth
  size(300, 300);
  background(0);
  smooth();
}

//Variablen für temporäre (!) Koordinaten und Größe der Formen
int tpx[] = new int[100];
int tpy[] = new int[100];
//Count wird in void draw() kontinuierlich inkrementiert
int count = 0;

void draw()
{
  //Hintergrund neu zeichnen und aussehen der Objekte angeben
  background(0);
  noStroke();
  fill(#ffffff, 127);
  //Die Koordinaten des aktuellen (neuesten) Objekts
  //werden festgelegt
  tpx[count] = mouseX;
  tpy[count] = mouseY;

  //In der Schleife werden nun alle Objekte bis zum aktuellen
  //Höchstwert durchlaufen (count wird je um 1 erhöht, siehe
  //letzte Zeile in void draw()
  for (int i = 0; i < count; i++)
  {
    noStroke();
    //Die Ellipsen werden gezeichnet
    ellipse(tpx[i], tpy[i], 50, 50);
  }


  //Zum Schluss wird diese Variable noch um +1 inkrementiert
  count++;
}

Du siehst die zwei temporären Arrays für X- und Y-Koordinaten tpx und tpy und die Variable count. In der Schleife in draw() geht’s dann los, die Werte werden aus dem Array geholt, mit diesen Werten werden die Ellipsen gezeichnet. Mit der Zeit (also nach jedem Durchlauf von draw()) kommt in das Array immer mehr rein. Tja, jetzt führe den Sketch doch mal aus und schau was passiert…
Dir wird aufgefallen sein, dass mir, wenn ich für die Größe des Arrays eine feste Angabe machen, Processing irgendwann eine “ArrayIndexOutOfBoundsException” werfen wird. In diesem Beispiel habe ich 100 genommen. Ich könnte jetzt auch 1000 nehmen oder 100000, dann hätten wir zwar mehr Zeit uns unser Ergebnis anzusehen, trotzdem wird es irgendwann abbrechen weil “count” die maximal angegebene Größe des Arrays (hier 100) überschreitet.
Es gibt aber natürlich Möglichkeiten, dem entgegenzuwirken, beispielsweise indem wir einfach das Array jedes mal erweitern. Das heißt ich setzte in meinem Beispiel die maximale Größe des Arrays immer auf -sagen wir mal zwei- Werte mehr als count – der Sketch würde also unendlich lange laufen (naja, fast..) wenn wir so wollen.
In dem Zuge lernst du also auch gleich den Befehl expand() kennen. Mit dem kannst du Arrays erweitern. Folgender Code bringt uns zu in dieser Richtung zum Ziel:

/**
 * Verschwindende Formen
 *
 * Dies soll anhand eines coolen Beispiels zeigen, was
 * man mit Arrays alles anstellen kann.
 *
 */

void setup()
{
  //Das Übliche, schwarzer Hintergrund, Größe und smooth
  size(300, 300);
  background(0);
  smooth();
}

//Variablen für temporäre (!) Koordinaten und Größe der Formen
int tpx[] = new int[1];
int tpy[] = new int[1];
//Count wird in void draw() kontinuierlich inkrementiert
int count = 0;

void draw()
{
  //Hintergrund neu zeichnen und aussehen der Objekte angeben
  background(0);
  noStroke();
  fill(#ffffff, 127);
  //Die Koordinaten des aktuellen (neuesten) Objekts
  //werden festgelegt
  tpx[count] = mouseX;
  tpy[count] = mouseY;

  //In der Schleife werden nun alle Objekte bis zum aktuellen
  //Höchstwert durchlaufen (count wird je um 1 erhöht, siehe
  //letzte Zeile in void draw()
  for (int i = 0; i < count; i++)
  {
    noStroke();
    //Die Ellipsen werden gezeichnet
    ellipse(tpx[i], tpy[i], 50, 50);
  }
  //Array wird immer um 2 mehr als count erweitert
  tpx = expand(tpx, count+2);
  tpy = expand(tpy, count+2);

  //Zum Schluss wird diese Variable noch um +1 inkrementiert
  count++;
}

Und schon klappt es. So, jetzt haben wir es geschafft, dass an allen Positionen an denen wir mit der Maus waren, Ellipsen gezeichnet werden. Du wirst dich vielleicht noch fragen, wieso wir vor der Schleife noch sagen, dass tpx[count] und tpy[count] jeweils mouseX und mouseY als Wert haben. Diese Werte werden ja nämlich nur ein mal zugewiesen, deswegen bleiben die Ellipsen auch auf ihren Positionen. Die neueste Ellipse (am höchsten Index, und der Index ist immer der Wert von count) bekommt als Werte mouseX und mouseY, am Ende von draw() wird count wieder um +1 erhöht. Sagen wir count hat den Wert 27, dann würden wir im Code sinngemäß folgende Zuweisung machen:
tpx[27] = mouseX;
tpy[27] = mouseY;
Jetzt wird count am Ende hochgezählt, ist nun also bei 28. Der Wert im Array an Index 27 wird also nun nie wieder angerührt und bekommt keine Wertzuweisung mehr. Durch die for-Schleife wird die Ellipse zwar jedes Mal neu gezeichnet, allerdings wird sich die Position nicht mehr verändern. Und jetzt geht’s nämlich darum, dass die Teile kleiner werden.

Für diesen Effekt brauchst du wieder die Arrays, in welche wir die Größe der Ellipse speichern. Anders als bei den Arrays für die Koordinaten brauchst du hiear aber nur eines, denn ich möchte für Breite und Höhe der Ellipsen immer dieselben Werte haben, quasi also runde Kreise ;-)
Den Anfangswert (wie für X und Y ja mouseX und mouseY festgelegt sind) weise ich dem Array für den Index wieder über die count-Variable zu. Ich hab’ spontan einfach einmal den Wert 50 für die Größe unserer Ellipse gewählt.
Aber wie geht’s jetzt weiter? Also erreichen möchten wir ja, dass die Ellipsen kleiner werden. Da alle Ellipsen ja immer dort neugezeichnet werden, wo die Maus schonmal langgefahren ist, könnten wir eigentlich genauso einfach in der for-Schleife angeben, dass für Größe[i] immer kleiner wird… machen wir das mal, in meinem Sketch heißt die Variable für die Größe der Ellipsen “ts”:

/**
 * Verschwindende Formen
 *
 * Dies soll anhand eines coolen Beispiels zeigen, was
 * man mit Arrays alles anstellen kann.
 *
 */

void setup()
{
  //Das Übliche, schwarzer Hintergrund, Größe und smooth
  size(300, 300);
  background(0);
  smooth();
}

//Variablen für temporäre (!) Koordinaten und Größe der Formen
int tpx[] = new int[1];
int tpy[] = new int[1];
float ts[] = new float[1];
//Count wird in void draw() kontinuierlich inkrementiert
int count = 0;
//Eine Variable um die Ansicht zwischen Ellipse und Rechteck zu wechseln
int form = 1;

void draw()
{
  //Hintergrund neu zeichnen und aussehen der Objekte angeben
  background(0);
  noStroke();
  fill(#ffffff, 127);
  //Die Koordinaten des aktuellen (neuesten) Objekts
  //werden festgelegt
  tpx[count] = mouseX;
  tpy[count] = mouseY;
  //Ausgangsgröße der Form (Ellipse, etc..)
  ts[count] = 50;

  //In der Schleife werden nun alle Objekte bis zum aktuellen
  //Höchstwert durchlaufen (count wird je um 1 erhöht, siehe
  //letzte Zeile in void draw()
  for (int i = 0; i < count; i++)
  {
    noStroke();
    //Die Ellipsen werden gezeichnet
    ellipse(tpx[i], tpy[i], ts[i], ts[i]);
    //Faktor, um den das Objekt kleiner wird - bestimmt
    //auch Geschwindigkeit. Hier wird immer um 1 verkleinert
    ts[i] -= 1;
  }

  //Hier werden die Arrays erweitert, und zwar immer um 
  //jeweils 2 mehr als count
  tpx = expand(tpx, count+2);
  tpy = expand(tpy, count+2);
  ts = expand(ts, count+2);

  //Zum Schluss wird diese Variable noch um +1 inkrementiert
  count++;
}

So, jetzt lass den Sketch mal laufen …. ich weiß was passiert, du wirst denken du hättest es endlich geschafft, doch nach wenigen Sekunden wirst du bemerken, dass da etwas noch gehörig schief läuft! Klar, die Ellipsen werden kleiner, allerdings hab ich an keiner Stelle im Code festgelegt was passieren soll wenn die Größe unter Null liegt, dann bekommen wir nämlich negative Werte. Processing nimmt das Vorzeichen (Minus) einfach weg und die Kreise werden wieder größer, und nach etwa 7 Sekunden wird der Sketch saumäßig lahm. Wenigstens ist dir noch aufgefallen, was der Fehler ist. Und mit einer einfachen If-Bedingung fragst du noch ab, ob die Größe (ts) größer oder kleiner als Null ist. Oder anders herum -so wie ich es gemacht habe- soll Variable ts nur heruntergezählt werden, wenn ts größer als Null ist. Ergänze deinen Code nun also noch um diese Abfrage und der Sketch ist so wie er ist fertig:

/**
 * Verschwindende Formen
 *
 * Dies soll anhand eines coolen Beispiels zeigen, was
 * man mit Arrays alles anstellen kann.
 *
 */

void setup()
{
  //Das Übliche, schwarzer Hintergrund, Größe und smooth
  size(300, 300);
  background(0);
  smooth();
}

//Variablen für temporäre (!) Koordinaten und Größe der Formen
int tpx[] = new int[1];
int tpy[] = new int[1];
float ts[] = new float[1];
//Count wird in void draw() kontinuierlich inkrementiert
int count = 0;
//Eine Variable um die Ansicht zwischen Ellipse und Rechteck zu wechseln
int form = 1;

void draw()
{
  //Hintergrund neu zeichnen und aussehen der Objekte angeben
  background(0);
  noStroke();
  fill(#ffffff, 127);
  //Die Koordinaten des aktuellen (neuesten) Objekts
  //werden festgelegt
  tpx[count] = mouseX;
  tpy[count] = mouseY;
  //Ausgangsgröße der Form (Ellipse, etc..)
  ts[count] = 50;

  //In der Schleife werden nun alle Objekte bis zum aktuellen
  //Höchstwert durchlaufen (count wird je um 1 erhöht, siehe
  //letzte Zeile in void draw()
  for (int i = 0; i < count; i++)
  {
    noStroke();
    //Die Ellipsen werden gezeichnet
    ellipse(tpx[i], tpy[i], ts[i], ts[i]);

    //Solange die Größe des Objekts größer als Null
    //ist, kann das Objekt verkleinert werden, sobald es
    //kleiner ist als Null, passiert einfach nichts mehr
    if (ts[i] > 0)
    {
      //Faktor, um den das Objekt kleiner wird - bestimmt
      //auch Geschwindigkeit. Hier wird immer um 1 verkleinert
      ts[i] -= 1;
    }
  }

  //Hier werden die Arrays erweitert, und zwar immer um 
  //jeweils 2 mehr als count
  tpx = expand(tpx, count+2);
  tpy = expand(tpy, count+2);
  ts = expand(ts, count+2);

  //Zum Schluss wird diese Variable noch um +1 inkrementiert
  count++;
}

Und -du hast es bestimmt gesehen- nicht vergessen, das Array “ti” wieder zu erweitern ;-) So sieht es doch ziemlich geil aus, finde ich.

Nicht relevant, aber gut zu wissen:
Wenn du aufmerksam bist und gut rechnen kannst ist dir vielleicht noch etwas aufgefallen… Du kannst angeben, um wieviel die Größe jedes mal verringert wird. Im eben gezeigten Sketch habe ich den Wert 1. Wenn du aber zum Beispiel 0.75 wählst, ziehst du Punkte hinter dir her, die nicht mehr verschwinden. Wenn du für background weiß wählst (background(255);) und für Füllfarbe Schwarz (fill(0);), kannst du es genauer beobachten. Versuche dabei, die Maus nur langsam zu bewegen. Das passiert, weil du Ellipsen mit dem Anfangswert 50 zeichnest. Wenn du nun ständig 0.75 abziehst, hast du irgendwann am Ende zu den Wert 1.25, davon dann nochmal 0.75 weg ergibt 0.5, davon nochmal 0.75 weg ergibt -0.25 -> HA, eine negative Zahl, und wie du weißt macht Processing daraus einfach eine positive. Du hast zwei Möglichkeiten. Und zwar musst du als Anfangswert eine Zahl wählen, die -wenn von ihr ja ständig 0.75 abgezogen werden- irgendwann dann genau 0.00 ergibt. Der Wert 50.25 würde beispielsweise funktionieren, wenn von diesem immer wieder 0.75 abgezogen werden, würde am Ende genau 0.00 herauskommen.
Die andere Möglichkeit ist, mit else abzufragen ob ts[i] kleiner(!) als 0 ist, also eine negative Zahl, und dann zu ts[i] einfach die Differenz hinzuzuaddieren. Dann ist es auch egal, was du als Anfangswert übergibst.

Ja, das wär’s für heute mal wieder, hoffe ich konnte dir einige interessante Dinge zeigen. Abschließend hier noch der komplette Code. Bei dem hier kannst du nun die Tasten 1, 2 oder 3 drücken, um zwischen Ellipse, Rechteck und Linie zu wechseln. Übrigens habe ich hier auch die else-Abfrage noch hinzugefügt, damit ts[i] am Ende immer 0.00 ist ;-)

/**
 * Verschwindende Formen
 *
 * Dies soll anhand eines coolen Beispiels zeigen, was
 * man mit Arrays alles anstellen kann.
 *
 */

void setup()
{
  //Das Übliche, schwarzer Hintergrund, Größe und smooth
  size(300, 300);
  background(255);
  smooth();
}

//Variablen für temporäre (!) Koordinaten und Größe der Formen
int tpx[] = new int[1];
int tpy[] = new int[1];
float ts[] = new float[1];
//Count wird in void draw() kontinuierlich inkrementiert
int count = 0;
//Eine Variable um die Ansicht zwischen Ellipse und Rechteck zu wechseln
int form = 1;

void draw()
{
  //Hintergrund neu zeichnen und aussehen der Objekte angeben
  background(255);
  noStroke();
  fill(0, 127);
  //Die Koordinaten des aktuellen (neuesten) Objekts
  //werden festgelegt
  tpx[count] = mouseX;
  tpy[count] = mouseY;
  //Ausgangsgröße der Form (Ellipse, etc..)
  ts[count] = 50;

  //In der Schleife werden nun alle Objekte bis zum aktuellen
  //Höchstwert durchlaufen (count wird je um 1 erhöht, siehe
  //letzte Zeile in void draw()
  for (int i = 0; i < count; i++)
  {
    noStroke();
    //Je nachdem welchen Wert "form" hat zeichnen wir ...
    switch(form)
    {
    case 1:
      //..eine Ellipse oder..
      ellipse(tpx[i], tpy[i], ts[i], ts[i]);
      break;
    case 2:
      //..ein Rechteck oder..
      rectMode(CENTER);
      rect(tpx[i], tpy[i], ts[i], ts[i]);
      break;
    case 3:
      //..eine Linie. Und eine Linie nur, wenn Variable "ts" mit diesem
      //Index noch größer ist als Null. Ansonsten würde die Linie nicht
      //verschwinden
      if (i > 1 && ts[i] > 0)
      {
        stroke(0);
        line(tpx[i], tpy[i], tpx[i-1], tpy[i-1]);
      }
      break;
    }
    //Solange die Größe des Objekts größer als Null
    //ist, kann das Objekt verkleinert werden, sobald es
    //kleiner ist als Null, passiert einfach nichts mehr
    if (ts[i] > 0)
    {
      //Faktor, um den das Objekt kleiner wird - bestimmt
      //auch Geschwindigkeit. Hier wird immer um 1 verkleinert
      ts[i] -= 0.75;
    }
    else
    {
      float tmp = 0 - ts[i];
      ts[i] += tmp;
    }
  }

  //Hier werden die Arrays erweitert, und zwar immer um 
  //jeweils 2 mehr als count
  tpx = expand(tpx, count+2);
  tpy = expand(tpy, count+2);
  ts = expand(ts, count+2);

  //Zum Schluss wird diese Variable noch um +1 inkrementiert
  count++;
}

void keyPressed()
{
  //Wir verändern die Variable "form", um zwischen Ellipse, Rechteck
  //und Linie zu wechseln. In void draw() wird abgefragt dass wenn
  //form == 1 eine Ellipse, wenn form == 2 ein Rechteck und wenn 
  //form == 3 eine Linie gezeichnet wird.
  switch(key)
  {
  case '1':
    form = 1;
    break;
  case '2':
    form = 2;
    break;
  case '3':
    form = 3;
    break;
  }
  //Arrayindex wird zurückgesetzt
  count = 0;
}

Du kannst als Anfangswerte auch mal Zufallszahlen übergeben, sieht auch nicht schlecht aus, ändere die Zeile einfach in:

  ts[count] = random(100);

Oder du änderst den Alphawert, oder machst zufällige Farben oder machst die Formen mit Rand …. experimentier’ einfach, wie gesagt, irgendwas wird schon dabei herauskommen ;-)

Bis dahin
Marius

Immer noch Angst vor Processing?

Hey,

wir sind inzwischen weit gekommen, behandelt wurden einfache Formen, Klassen, die translate()-Funktion, Farben, das Koordinatensystem, Rotationen und vieles, vieles mehr. Der ein oder andere hat trotzdem immer noch Angst davor, sich die Programmiersprache Processing anzueignen. Vielleicht weil es “zu kompliziert” ist oder du denkst “das bekomme ich nie hin”? Oder etwa weil das was du dir vornimmst einfach nicht klappen will? Dann solltest du jetzt weiterlesen, dieser Artikel ist für alle die immer noch so ihre Zweifel mit Processing haben – völlig zu unrecht, wie sich im weiteren Verlauf herausstellen wird…

Wieso gerade Processing, was bringt es mir?
Zuerst stellt sich (dir?) natürlich die Frage, wieso du gerade Processing lernen solltest. Nun, da gibt es -abgesehen davon dass man mit Processing richtig geile visuelle Effekte zaubern kann- schon ein paar Gründe. Processing ist in erster Linie kostenlos, und was nichts kostet kann man immer zumindest mal ausprobieren. Weiterhin ist Processing keine exotische Programmiersprache sondern lediglich eine vereinfachte Java-Version, welche sich per Definition dieser Sprache auf das wesentliche beschränkt. Daraus folgt, dass du zwar eine überschaubare Menge an Befehlen, allerdings dadurch aber auch weniger zu schreiben hast. Die Kunst, das besondere an dieser Programmiersprache ist nicht, mit unmengen an Befehlen und tausenden von Möglichkeiten irgendetwas zu realisieren.. nein, das besondere an Processing ist die enorme Vielfalt an Möglichkeiten die sich gerade mit diesen paar Hand voll Funktionen umsetzen lassen. Außerdem kann man mit Processing nichts falsch machen. Egal wie du an welcher Stelle im Code was schreibst, es kommt immer was dabei raus. Und um ein anderes Ergebnis zu erreichen musst du meist nicht einmal den passenden Befehl suchen sondern die Stellen im Code einfach nur etwas umstellen. Desweiteren läuft Processing unter Windows, Linux und MAC, und die Sketche die du mit Processing erstellst lassen sich in Webbrowsern als Applet einbinden.

Aber ist das alles? Was gehört denn dazu, Processing überhaupt erst zu erlernen? Außerdem könnte Ich ja was falsch machen…
Processing ist eine Sprache die man nur durch Selbst-ausprobieren erlernt. Und Processing ist auch nicht nur irgendeine Programmiersprache, Processing zu beherrschen ist eine Kunst. Gut, Ich sage ja generell, dass Programmierung nicht nur eine Fähigkeit, sondern auch eine Kunst ist. Andererseits geht es ja hier aber hauptsächlich um Visualisierung, unter dem Aspekt kann so der ein oder andere mit Processing erzeugte Sketch doch als Kunstwerk angesehen werden, schaue dir nur mal an was die Leute (und auch ich ;-) ) so auf OpenProcessing.org reinstellen.
Wo ich gerade auf OpenProcessing zu sprechen komme … falls du auf der Seite mal ein wenig gestöbert hast, wirst du du dir vielleicht doch hier und da mal gedacht haben “das bekomm ich so nie hin”. Die meisten Leute scheuen sich davor, weil sie Angst haben, etwas falsch zu machen. Aber mal realistisch betrachtet, was willst du falsch machen? Nimm dir doch von der Seite einfach mal einen Code der dir gefällt, und mach ihn kaputt. Scheißegal, einfach nur um zu sehen was passiert wenn man hier was weglässt, dort was hinzufügt oder umstellt oder verändert …. dabei findest du raus, wie der Code funktioniert, welche Stelle was tut, und das ganz nebenbei, ohne großartig zu lernen. Lernen kannst du eh vergessen, wie gesagt, Processing lernst du nur durch machen. Du willst dir gar nicht vorstellen wieviele Processing-Projekte auf meinem PC abgespeichert sind, und davon sind die meisten beinahe dieselben, die ich nur mehrmals abgespeichert hab’, weil Ich an irgendeiner Stelle im Code was klitzekleines verändert hab und das Ergebnis einfach so geil aussah dass Ich es als eigenständiges Projekt abspeichern wollte. Viele Processing-Nutzer wissen wovon ich rede ;-) Aber genau das ist es ja, was diese Programmiersprache ausmacht, was sie so besonders macht.
Vielleicht hast du den Code von einem Sketch (von OpenProcessing oder von den Beispielen die das Programm von sich aus mit dabei hat) und hast keine Ahnung was dort drin steht, aber das beste was man in diesem Fall machen kann, ist einfach mal hier und dort eine Zeile zu entfernen um zu sehen, wie sich das im Sketch bemerkbar macht. So hast du eigentlich sofort im Kopf drin “ah, die Zeile raus und dann haben die Formen keinen grünen Rand mehr” und merkst es dir dadurch quasi automatisch und ganz nebenbei.

Aber wie fang’ ich an, ich kann doch nicht einfach irgendwas da reinschreiben
Und genau das unterscheidet Processing von anderen Programmiersprachen – es ist scheißegal was du dort in das Codefenster reinhackst, irgendwas kommt immer dabei raus. Zu Anfangs wirst du ohnehin keine großartigen Pläne machen, was genau du mit Processing umsetzen möchtest. Zum einen fehlt dir -logischerweise- jedes Wissen. Zum anderen: bei Processing musst du dich nicht auf die Befehle selbst konzentrieren, es sind schon einige, aber doch noch gerade so wenig, dass du sie mit der Zeit locker alle drauf hast. Dauert auch nicht lange, und manche Befehle wirst du möglicherweise nie brauchen weil du schon mit ein paar wenigen so viele Möglichkeiten hast, die verschiedensten Sketche zu programmieren. Weniger auf die Befehle selbst kommt es bei Processing nämlich vielmehr darauf an, wie du die Befehle einsetzt. Am Anfang bekommst du durch deine Codes sicherlich das ein oder andere mal ein anderes Ergebnis als du eigentlich erwartet hast. Manchmal “überrascht” dich Processing einfach mit dem Ergebnis. Wenn du bevor du den Sketch ausführst schon sagen kannst, wie das Ergebnis aussehen wird, dann bist du auf dem besten Weg. Und das ist manchmal gar nicht so einfach, deswegen braucht dich das am Anfang auch nicht interessieren, das kommt mit der Zeit.

Ich bin noch nicht so ganz überzeugt. Du hast leicht reden, du kannst Processing ja bereits…
Ja, ich kann Processing bereits. Allerdings hab auch ich einmal klein angefangen, und von einem Profi bin ich auch noch ein gutes Stück weit entfernt. Bei mir war es so, dass ich in einer Zeitschrift (soweit ich mich erinnere war es die “c`t Programmieren”) einen Artikel über Processing gelesen habe, darin war unter anderem folgender Beispielcode abgedruckt:

// Stern interaktiv
// Den Mittelpunkt der Strahlen bestimmt der Mauszeiger,
// ein Mausklick speichert eine Momentaufnahme als Bitmap.

float winkel; 
float laenge; 
float dx; 
float dy;
int breite;

// Die Funktion setup() ruft Processing beim Programmstart einmal auf
void setup(){
  size(600, 600);
  background(15, 15, 20);
  // Mauscursor wird als Hand dargestellt
  cursor(HAND);
  smooth();
  // Bei Programmstart sollen die Strahlen vom Mittelpunkt des Fensters ausgehen
  mouseX = width/2;
  mouseY = height/2;
}

// Die Funktion draw() ruft Processing nach setup() immer wieder neu auf
void draw (){
  // zufaellige Linienbreite
  breite = int(random(1,7));
  strokeWeight(breite);
  // zufaellige Farbe (innerhalb gewisser Grenzen)
  stroke (random (25, 150), random (5, 255), random(100));  
  // zufaelliger Winkel
  winkel = random(0, 2*PI); 
  // je breiter sie sind, umso kuerzer sollen die Linien sein
  laenge = random((min(width/2, height/2))*(7-breite)/6);
  dx = cos(winkel)*laenge;
  dy = sin(winkel)* laenge;
  line (mouseX, mouseY,  mouseX+dx, mouseY-dy); 
}

// Die Funktion mousePressed() ruft Processing automatisch auf, 
// sobald eine Maustaste gedrueckt wird
void mousePressed(){
  // aktueller Inhalt des Programmfensters wird als Pixelbild gespeichert
  save("Stern.png");
}

Ich fand das ziemlich cool, also hab’ ich mir Processing kurzerhand runtergeladen und das Teil abgetippt. Hinterher hab Ich den Code auseinandergenommen um zu sehen was passiert wenn hier und da was fehlt oder ich Codezeilen einfach vertausche. Und von da an war ich ein Fan dieser Programmiersprache – bis heute. Und ich sage jeder kann sich Processing aneignen. Du tippst etwas, führst es aus und siehst was du gemacht hast. Sofort und auf der Stelle. Natürlich gibt es gewisse Regeln die zu beachten sind wie beispielsweise die Notation, hinter jede Zeile ein Semikolon etc.. aber Processing unterstützt dich dabei. Wenn du im Code einen Fehler hast, weist dich Processing darauf hin, hebt die betreffende Zeile farblich hervor und gibt unten an, was du falsch gemacht hast. Zum Beispiel ein Argument zuviel an eine Funktion übergeben oder versucht, eine Kommazahl einer int-Variable zuzuweisen. Processing führt dich zu der Zeile und schreibt dazu, was der Fehler ist, du korrigierst es und schon klappt es wieder. Processing lässt gar nicht erst zu, dass dein Programm ausgeführt wird und dann erst im Nachhinein mit einem Fehler wieder abbricht. Ausnahmen sind sogenannte Laufzeitfehler, zum Beispiel wenn du mit mouseX oder mouseY herumspielst und versehentlich versucht wird, durch Null zu dividieren oder wenn Processing feststellt, dass eine Schleife unendlich läuft.

Okay, ich will mir Processing zumindest mal anschauen. Aber was, wenn ich nicht weiterkomme? Wer hilft mir, gibt es gute Anlaufstellen?
Klar gibt es Anlaufstellen. Es gibt die Learning-Section, ein Wiki und das wichtigste, die Referenz (alles auf Englisch, aber das stellt sicher kein Problem dar). Zudem sind in der Processing IDE (also dem Programm selbst) über das Menü “File->Examples” noch etliche Beispielsketche zu finden. Es gibt ein Forum (auf Englisch) und im Internet auch noch einige Tutorials, jedoch nicht ganz so viele auf Deutsch. Und zu guter Letzt gibt’s ja immer noch meine Seite hier, auf der du Schritt für Schritt von Anfang an an Processing herangeführt wirst :-) Ganz hilflos bist du also nicht. Mit meinen Tutorials bist du jedoch an meinen Wissensstand gebunden, du wächst sozusagen mit mir.

Okay, hast du zum Schluss noch einen Tipp für mich, wie ich jetzt am besten loslege?
Sicher =) Zuerst musst du dir Processing natürlich runterladen, das kannst du hier machen. Wie du Processing installierst habe Ich in diesem Artikel beschrieben. Danach geht’s dann los mit der Programmierung, auch dazu gibt’s hier einen Artikel von mir, in dem du alles nachlesen kannst.
Und wenn du das hast, geht es daran dir die wichtigsten Befehle in der Processing Referenz zusammenzusuchen. Begleitend dazu findest du in meinen Artikeln jeweils Links und Verweise für bestimmte Befehle, mit denen du direkt zur Referenz für die jeweilige Funktion gelangst. Zuerst -und das ist das wichtigste- solltest du das Koordinatensystem verstehen, danach dann die einfachen Standard-Befehle für Fenstergröße, Anti-Aliasing (smooth()), Strichfarbe, Füllfarbe, Hintergrundfarbe, Formen und vor allem wie void setup() und void draw() arbeiten. Direkt im Anschluss lernst du Variablen kennen, und spätestens dann bist du ohnehin schon mittendrin in Processing und wirst bis dahin bereits mehr als überzeugt, ja ich denke geradezu begeistert sein von dieser Programmiersprache.

Aber jetzt lad’ dir Processing erstmal runter, wühl’ dich durch meine Artikel und lass dich davon faszinieren wie überraschend schnell du zu tollen Ergebnissen kommst :-)

Bis dahin
Marius

Rotation mit Processing – Teil 1 :: Der Radiant (radians())

Hi,

heute zu einem sehr spannenden Thema, der Rotation, wie bereits kurz angesprochen ist dieses Thema die Basis für solche Spielereien. Bisher konnten wir beliebige Formen (ellipse(), line(), point(), rect(), etc…) von links nach rechts, rechts nach links, oben nach unten usw.. bewegen, linear eben, immer in eine Richtung. Viel cooler ist es aber, Formen im Kreis zu bewegen. Hier haben wir die Möglichkeit, die Objekte kontinuierlich zu rotieren, beispielsweise im Kreis immer nach links oder immer nach rechts. Mit Sinus ( sin() ) und Kosinus ( cos() ) gibt es darüber hinaus die Möglichkeit, Objekte pendeln zu lassen, beispielsweise ein Pendel wie bei älteren Standuhren, die in einem ca. 45° Winkel von links nach rechts pendeln. Rotation eben, und das ist das Thema, mit dem wir uns heute und in den kommenden Artikeln beschäftigen werden – ein sehr umfangreiches Thema also.
Ich gehe davon aus dass deine Mathematikkenntnisse -sagen wir mal- recht passabel sind und du das nötige Wissen für Kreisberechnungen, Sinus, Kosinus, PI etc.. bereits mitbringst. Im Zusammenhang mit Processing sehen wir uns jetzt zuerst einmal die Funktion rotate() an. In der Referenz ist recht schön beschrieben, was diese Funktion tut:

Rotates a shape the amount specified by the angle parameter. Angles should be specified in radians (values from 0 to TWO_PI) or converted to radians with the radians() function.

Übersetzen wir das einmal ins Deutsche:

Rotiert eine Form zu dem Wert eines Winkels. Winkel werden über radians (Radiant) angegeben (gültig sind Werte von 0 is TWO_PI, also 2xPI) bzw. über die radians() Funktion in einen Radianten konvertiert.

radians() konvertiert eine Zahl die in Grad (°) angegeben ist in eben diesen sogenannten Radiant. 2xPI entspricht 360°, aus der Schule wissen wir, 360° bedeutet immer genau einen vollständigen Kreis. PI entspricht somit 360° / 2, also 180°. Stell dir eine Uhr vor mit Sekunden-Zeiger. Der Zeiger startet bei 0 (oder bei 12, wie auch immer) und fängt an zu wandern, wenn der Zeiger auf 6 Uhr steht, haben wir 180° geschafft. 180° sind 3,14159…, also PI. Der Zeiger wandert weiter, wenn er wieder auf 12 Uhr steht hat er genau eine Runde gemacht, 360° also, und somit 2xPI (6.2831855…). Du wirst feststellen, dass 0° und 360° sich überschneiden, der Zeiger steht in beiden Fällen an derselben Stelle. Soweit eigentlich klar. Und was hat das nun mit dem Radianten zu tun? radians() konvertiert einen in Grad angegebenen Wert in eine natürliche Zahl, und diese Zahl ist der Radiant.

Im Zusammenhang mit der rotate()-Funktion kann so eine Grad-Angabe (mit der wir Menschen in der Regel besser zurecht kommen) übergeben werden, um eine Rotation darzustellen. Wir brauchen nicht überlegen um zu wissen 180° ist ein halber Kreis, 90° ist ein Viertel und 360° ist ein Ganzes. Somit bleibt es uns erspart, diese ganzen Zahlen als Radiant zu berechnen, das macht die radians() Funktion für uns.

Ich möchte, dass ein Objekt (eine Form, z.B. ein Rechteck) um 90° rotiert wird. Kein Problem, radians() macht das für uns. Durch folgende Angabe übergeben wir einfach unsere Anzahl in Grad (90°) an die radians()-Funktion, die rotate()-Funktion wiederum arbeitet dann mit dem an die radians()-Funktion übergebenen Wert, intern ist es für die Rotate-Funktion ja dann kein Grad-Wert mehr sondern der Radiant. Die Schreibweise sieht wie folgt aus:

  rotate(radians(90));

BAM! Ganz simpel und saumäßig praktisch. Wir übergeben 90 und radians macht daraus 1.5707964, das ist der Wert mit dem die rotate()-Funktion dann arbeitet, aber das braucht uns dann nicht mehr interessieren, wir bleiben entspannt bei unserer Grad-Angabe. Jetzt wo du das weißt, sehen wir uns an wie die rotate()-Funktion arbeitet. Die Rotate-Funktion kann an beliebiger Stelle im Code eingefügt werden. Alle nachfolgenden Formen (alles was nach dem rotate()-Befehl geschrieben wird), wird rotiert. Du musst dann für z.B. eine Ellipse keinen Code hinterlegen, der diese Bewegt, denn das macht die rotate()-Funktion. So könntest du beispielsweise ein Rechteck nach links rotieren lassen, und ein darüberliegendes nach rechts. Aber Ich würde sagen genug von dem ganzen theoretischen Kram, schaun wir uns lieber an wie das mit der Rotation in der Praxis funktioniert. Darstellen möchte Ich ein Rechteck, welches sich kontinuierlich dreht.

void setup()
{
  size(300, 300);
  smooth();
  background(0);
  frameRate(60);
}

int grad = 0;

void draw()
{
  background(0);
  rotate(radians(grad));
  grad++;
  println(grad + "°");
  fill(255);
  noStroke();
  rect(0, 0, 50, 50);
  if (grad >360) {
    grad = 0;
  }
}

So, schaut doch schon ganz gut aus. Nur das Rechteck, dass das in der linken oberen Ecke ist, schaut hässlich aus. Verlegen wir den Nullpunkt in die Mitte, dann macht das schon mehr her:


void setup()
{
  size(300, 300);
  smooth();
  background(0);
  frameRate(60);
}

int grad = 0;

void draw()
{
  background(0);
  translate(width / 2, height / 2);
  rotate(radians(grad));
  grad++;
  println(grad + "°");
  fill(255);
  noStroke();
  rect(0, 0, 50, 50);
  if (grad >360) {
    grad = 0;
  }
}

Ich deklariere eine Variable “grad” mit dem Wert 0. Dieser Wert wird je um 1 erhöht. Diese Variable übergebe ich an radians, diese macht aus dem Grad-Wert den Radiant, die rotate()-Funktion arbeitet mit diesem konvertierten Wert und rotiert entsprechend. Wie du siehst ist es ganz einfach. Interessant wäre nun auch, wenn sich das Rechteck anstatt von der oberen linken Ecke aus um den Mittelpunkt des Rechtecks rotiert. Hierfür stehen dir zwei Möglichkeiten zur Verfügung: Entweder du passt den rectMode() entsprechend an mit rectMode(CENTER); (dafür musst du bevor das Rechteck gezeichnet wird eine Zeile mit eben genanntem Code einfügen) oder aber du zeichnest das Rechteck in der Positionsangabe jeweils minus die Hälfte der Breite / Höhe.

Beide Möglichkeiten einmal zum testen:

  rectMode(CENTER);
  rect(0, 0, 50, 50);

oder so:

  rect(-25, -25, 50, 50);

Versuche, die Stelle mit dem Rechteck im Code jeweils mit der einen und der anderen Möglichkeit zu zeichnen, das Ergebnis ist dasselbe. Falls Ich in meinen Artikeln noch gar nicht erklärt habe, was der rectMode() überhaupt ist, will Ich es dir noch ganz kurz erklären: Der rectMode() gibt an, wo der quasi-Ausgangspunkt des Rechtecks ist. Die ersten beiden Parameter für rect() geben ja an, ab welcher X- / Y-Position angefangen soll zu zeichnen, die letzten beiden Parameter bestimmen Breite und Höhe des Rechtecks. Der Punkt von dem ab das Rechteck dann gezeichnet wird, ist immer der obere linke (das wäre dann standardmäßig rectMode(CORNER);). Wenn du nun aber rectMode(CENTER) angibst bevor du das Rechteck zeichnest, ist dieser Punkt nicht mehr die obere linke Ecke der Form sondern genau die Mitte. Es gibt noch weitere Modi, insgesamt stehen CORNER, CORNERS, CENTER und RADIUS zur Verfügung, dasselbe gibt es noch für ellipseMode().
Bevor ich aber jetzt zu weit abschweife, komme Ich lieber auf das wesentliche zurück. Rotation.
Wie gesagt, du siehst es ist ziemlich einfach. Die Abfrage ob grad > 360 ist könntest du auch weglassen, das ganze würde trotzdem ganz normal weiterlaufen, allerdings wollte Ich das mit den Grad im Ausgabefenster nochmal verdeutlichen.

Transparente Rechtecke mit Rotation

Transparente Rechtecke mit Rotation

Ich denke es ist an der Zeit, mit dieser tollen Funktion endlich etwas sinnvolles anzufangen. Ich schlage vor wir fügen in einer Schleife einfach mehrere Rechtecke (natürlich transparant ;-) ) mit unterschiedlicher Rotation hinzu. Den Wert der Rotation müssen wir nicht selbst anpassen, da jede rotate()-Anweisung von der zuvor geschriebenen abhängig ist. Außerdem bleibt so nichts komplett dem Zufall überlassen, das heißt unsere Bewegungen lassen im Laufe der Zeit ein Muster wiedererkennen. Wo war ich … achja genau, und rectMode() stellen wir wieder auf CENTER. Du kannst übrigens in deinen Tests das rectMode(CENTER); einmal rausnehmen und gucken wie es dann aussieht.
Ich zeig’ dir mal was Ich mir da ausgedacht hab’, auf der linken Seite ein Screenshot, unten der Code:

void setup()
{
  size(300, 300);
  background(0);
  smooth();
  frameRate(60);
}

float angle;

void draw()
{
  background(0);
  translate(width/2, height/2);
  rectMode(CENTER);
  fill(255);
  for (int i = 255; i >10; i-=10)
  {
    rotate(radians(angle)/PI);
    strokeWeight(0.1);
    stroke(0);
    fill(i, 25);
    rect(0, 0, i, i);
  }
  angle += 1;
}

Ergebnis:

Ja, ich würde sagen ich bin recht zufrieden mit dem Ergebnis, es schaut ziemlich gut aus. Auf OpenProcessing kannst du dir den Sketch auch nochmal live ansehen oder hier die rotierenden Rechtecke als Download direkt herunterladen. Ich denke das Prinzip hast du verstanden, und wie Ich dir schon vorausprophezeit habe, ist es nicht wirklich schwierig. Fassen wir dennoch die wichtigsten Punkte erneut zusammen:

- Jede rotate()-Anweisung ist abhängig von der zuvor geschriebenen, wenn wir zwei Rechtecke rotieren wird das zweite (darüberliegende) sich in jedem Fall schneller bewegen.
- Tipp: Um eine Form in die andere Richtung zu rotieren kannst du vor die Variable (ich nenne sie meist “angle”) ein Minuszeichen setzen, den Wert also negativ machen. Beispiel: rotate(radians(-angle));. Doch aufgepasst, wenn du zuvor bereits eine rotate-Anweisung hast ohne das Minuszeichen aber mit demselben Wert (“angle” eben dann) hört die Rotation auf, damit hebst du für alle weiteren Objekte oder Formen die du hinzufügst die Rotation auf. Ich weiß, etwas schwierig vorzustellen, unten folgt noch ein Beispiel.
- Für 90° kannst du statt rotate(radians(90)); auch rotate(HALF_PI); schreiben

Ich erkläre dir noch was mit Punkt 2 und dem Aufheben der Rotation gemeint ist. Wenn du eine rotation() von sagen wir 45° hast, ein Rechteck zeichnest, dann noch eine rotation() hinzufügst wieder mit 45° und erneut ein Rechteck darüberlegst, dreht sich das erste Rechteck um 45°, das zweite um 90°, weil es durch die erste rotate()-Anweisung 45° rotiert und durch die zweite Anweisung nochmal. Ich zeige es dir anhand eines Screenshots, zuerst wurde das weiße, dann das schwarze Rechteck hinzugefügt:

Zwei um 45° rotierende Rechtecke

Zwei um 45° rotierende Rechtecke

Um also eine Rotation für alle nachfolgenden Objekte aufzuheben, schreibst du denselben Code wie den in der vorangehenden Rotate-Anweisung, nur mit Minus-Zeichen vor der Winkel-Variable:

Rotation aufheben

Rotation aufheben

Mit dieser rotate()-Funktion lässt sich, wie du nun siehst, so allerhand anstellen. Nun möchte Ich einmal etwas neues versuchen, und zwar einen Punkt (oder eine Ellipse) die sich zwar im Kreis dreht, dessen Radius dabei jedoch immer größer wird. Dafür musst du den X-/Y-Koordinaten der Form lediglich einen dynamischen, sich inkrementierenden Wert zuweisen, also eine Variable deren Wert immer größer wird. In der einfachsten Form könnte dies so aussehen:

void setup()
{
  size(300, 300);
  background(0);
  smooth();
}

float angle;
float speed = 5;
float ball_radius = 0;
float ball_size = 5;

void draw()
{
  translate(width / 2, height / 2);
  rotate(radians(angle));
  noStroke();
  fill(255);
  ellipse(ball_radius, ball_radius, ball_size, ball_size);
   ball_radius += 0.25;
  angle += speed;
}

Und wenn man nun noch mit Füllfarbe, Strichfarbe und -dicke, Schnelligkeit, Größe und so weiter rumspielt und hier und da anpasst, könnte das nach wenigen Änderungen so aussehen:

void setup()
{
  size(300, 300);
  background(0);
  smooth();
}

float angle;
float speed = 77;
float ball_radius = 1;
float ball_size = 15;

void draw()
{
  translate(width / 2, height / 2);
  rotate(radians(angle));
  fill(255, 10);
  stroke(0);
  strokeWeight(0.1);
  ellipse(ball_radius, ball_radius, ball_size, ball_size);
  ball_radius += 0.25;
  ball_size += 0.1;
  angle += speed;
}

Rotierende Linien

Rotierende Linien


Damit kannst du vielerlei Zeugs anstellen, es gibt beinahe endlos viele Möglichkeiten, die du einbauen könntest. Strichdicke, Strichfarbe, Füllfarbe, Transparenz (Alpha), Größe, Geschwindigkeit, Rechtecke, Linien, Ellipsen und dann noch Zufallswerte für eine der genannten Funktionen, Radius ändern blablablablabla … So einiges also =) In dem Screenshot den du links siehst habe Ich denselben Code wie eben, nur statt einer ellipse Linien, eine andere Strichfarbe, andere Geschwindigkeit und … ja, völlig anderes Ergebnis:

void setup()
{
  size(300, 300);
  background(0);
  smooth();
}

float angle;
float speed = 20;
float ball_radius = 0;
float ball_size = 5;

void draw()
{
  translate(width / 2, height / 2);
  rotate(radians(angle));
  fill(255, 10);
  strokeWeight(0.1);
  stroke(0, random(200), random(255), random(255));
  line(random(ball_radius), random(ball_radius), random(ball_size), random(ball_size));
  ball_radius += 0.25;
  ball_size += 0.1;
  angle += speed;
}

Damit bist du nun eine Weile beschäftigt, es gibt viel auszuprobieren ;-) Auch in den kommenden Artikeln wird die Rotation immer wieder mal das Thema sein, spätestens wenn wir dann sin() und cos() hinzufügen. Außerdem gibt’s ja noch rotateX, rotateY und rotateZ für 3-Dimensionale Spielereien … wir haben viel vor :-)

Bis dahin
Marius

Processing: Translate – Koordinatensystem verschieben

Hi,

in diesem Artikel möchte Ich dir die translate()-Funktion zeigen.

Wie du weißt, ist der Null-Punkt im Koordinatensystem von Processing immer in der oberen linken Ecke. Veranschaulichend dazu folgende Grafik:

Koordinatensystem

Koordinatensystem

Die Translate-Funktion nun ist dazu da, um diesen Nullpunkt zu verschieben. Stell dir vor du verschiebst den Nullpunkt an Position X = 20 und Y = 20. Wenn du nun ein Rechteck an Position 0, 0 zeichnen würdest mit einer Größe von 80×40, sieht es im fertigen Bild aus als wäre das Rechteck an 20, 20. Folgende Grafik soll dir zeigen, wie translate() arbeitet (Auch hier wieder eine Größe für das Rechteck von 80×40 an Position X=50 und Y=90):

Koordinatensystem

Koordinatensystem mit verschobenem Nullpunkt

Dasselbe Gebilde, nur dass Ich, bevor Ich den ganzen Kram dort draufgezeichnet hab, den Nullpunkt verschoben habe auf 20, 20. Hier bisschen schlecht zu sehen, da das komplette Raster mitverschoben wurde.

Sehen wir uns das nochmals an. Ein simples Rechteck an 0, 0. Einmal ganz normal und einmal mit verschobenem Nullpunkt genau in der Mitte des Fensters (width / 2, height / 2) – auf Bild klicken um es in Originalgröße anzusehen:

Ohne Nullpunkt-Verschiebung (translate())

Ohne Nullpunkt-Verschiebung (translate())

Mit Nullpunkt-Verschiebung (translate())

Mit Nullpunkt-Verschiebung (translate())

Du siehst, derselbe Code, nur dass beim zweiten Bild der NullPunkt verschoben wurde. Hier auch gleicht ersichtlich, wie translate funktioniert. Du übergibst als Parameter einfach nur die X- / Y-Koordinaten für den neuen Nullpunkt.
Spannend wird die translate() Funktion im Zusammenhang mit Rotationen, die ich im nächsten und in einigen weiteren Artikeln behandeln möchte.
Zum herumexperimentieren mit translate() hab’ Ich dir auf OpenProcessing etwas schönes zusammengebastelt, einfach mal ausprobieren ;-) Lies’ die Beschreibung unter dem Sketch um zu wissen was du anstellen kannst.

Ein wichtiger Hinweis sei noch zu beachten: Es ist möglich, translate zu verschachteln. Schreibe translate(50, 50), um den Nullpunkt nach X=50 und Y=50 zu verschieben. Wenn du danach erneut translate aufrufst, beispielsweise mit Wert 20, wird der Nullpunkt nicht erneut von 0, 0 verschoben sondern von 50, 50. Sobald draw() beendet ist und wieder an den Anfang springt, hast du wieder 0, 0. Alles andere wäre auch schwachsinnig, da sich der Nullpunkt ansonsten ja mit der Zeit ins unendliche verschiebt. Schau mal:

void draw() und translate()

void draw() und translate()

Klick das Bild an, damit du’s in Originalgröße anschauen kannst.

So, Ich denke die Translate-Funktion können wir damit abschließen, viel muss dazu auch nicht gesagt werden. Im nächsten Artikel wird es um Rotationen gehen, eine echt prickelnde Sache die dir Spaß machen wird =)

Bis dahin
Marius