PFont schrift;
float textX, textY, linienDicke, altesTextX, altesTextY;
String wort = "";
color farbe = color(50, 200, 0);
void setup() {
size(640, 480);
schrift = loadFont("ArnoPro-Smbd-48.vlw");
textFont(schrift, 24);
background(255);
smooth();
textX = 320;
altesTextX = 320;
textY = 50;
altesTextY = 50;
}
void draw() {
noStroke();
// das wort zeichnen
fill(255);
rect(0, 430, width, 480);
fill(0);
textFont(schrift, 16);
text(wort, 10, 450);
}
void keyPressed() {
// den gedrücken buchstaben an das vorhandenene wort setzen
wort = wort + key;
// die linieneigenschaften ändern
if(key == 'a') {
textX = textX + 30;
textY = textY + 12;
}
else if ( key == 'r') {
textX = textX + 15;
textY = textY - 14;
}
else if ( key == 'c') {
linienDicke = linienDicke + 5;
}
else if ( key == 'e') {
if(linienDicke > 2) linienDicke = linienDicke - 2;
textX = textX + 5;
textY = textY + 10;
}
else if ( key == 't') {
farbe = color(200, 0, 0);
}
else if ( key == 'i') {
textX = textX - 28;
textY = textY + 28;
}
else if ( key == 'v') {
farbe = color(50, 200, 0);
textX = textX - 9;
textY = textY - 18;
}
else if ( key == 'o') {
farbe = color(200, 200, 120);
textX = textX - 9;
textY = textY + 18;
}
else if ( key == 'm') {
linienDicke = linienDicke + 10;
textX = textX - 19;
textY = textY - 18;
}
else if ( key == 'n') {
if(linienDicke > 10) linienDicke = linienDicke - 10;
textX = textX + 29;
textY = textY - 18;
ellipse(textX, textY, linienDicke*3, linienDicke*3);
}
else {
textX = textX + random(-15, 15);
textY = textY + random(-15, 15);
}
// die linie zeichnen
stroke(farbe);
strokeWeight(linienDicke);
line(altesTextX, altesTextY, textX, textY);
altesTextX = textX;
altesTextY = textY;
strokeWeight(.5);
line(0, textY, textX, textY);
textFont(schrift, 24);
text(key, textX, textY);
}
Category Archives: input
Beispiel Source
Schöne Processing Galerie
hier ein schönes Beispiel dafür, wie Ergebnisse von einem Semester Einstieg in Processing aussehen können:
www.processing.diana-lange.de
Starguitar video & »making-of«
»Starguitar« Chemical Brother by Michel Gondry
Making-of Starguitar – gutes Beispiel für »Rapid-Prototyping«
Audiobeispiele im Wiki

Für alle AudioInput-Projekte gibt es nun eine Lesson im Wiki mit allen und weiterführenden Beispielen zur Benutzung der minim Bibliothek. Sketch #5: Frequenz-Gruppen beschäftigt sich mit dem Zusammenfassen von Frequenzbereichen und ermöglicht damit das gezielte Auslesen von Höhen, Mitten und Bässen.
Login mit controlP5
Letzte Woche durchgesprochen und hier noch mal im Blog zum anschauen. Für alle Projekte die auf der Nutzereingabe von Name und Passwort basieren.

Wir nutzen dabei die von Andreas Schlegel geschriebene Bibliothek controlP5 – ideal für das Erstellen von simplen Benutzeroberflächen.
Nach dem Anlegen der beiden Textfelder im setup(), wird bei ENTER die Funktion controlEvent() aufgerufen. Innerhalb entscheidet die Länge der Text ob diese für die Verbindung zur API genutzt werden. In diesem Fall müssen beide Felder ausgefüllt sein.
Der letzte Schritt besteht im Ändern des ‘ready’ Wertes von false auf true. Dies veranlasst die Bedingung im draw() den eigentlichen Zeichenprozess (das Arbeiten mit den Daten) zu beginnen.
import utils.*;
import lastfm.*;
import controlP5.*;
ControlP5 c5;
Textfield tfName;
Textfield tfPass;
boolean ready = false;
Lastfm fm;
void setup () {
size (580, 240);
// Allgemeines ControlP5 Objekt
c5 = new ControlP5 (this);
// TextFelder für beide Werte Anlegen
tfName = c5.addTextfield ("username", 20, 100, 200, 18);
tfPass = c5.addTextfield ("userpass", 20, 140, 200, 18);
// Passwort wird im Sternchenmodus angezeigt
tfPass.setPasswordMode (true);
}
void draw () {
background (40);
if (ready) {
// MAGIC!
}
}
/**
* Diese Funktion wird bei jeder ControlP5-Eingabe aufgerufen.
* Das 'ControlEvent' gibt Aufschluss über den Auslöser und
* damit über dessen Wert bzw. Zustand. In diesem Fall der Text.
*/
void controlEvent (ControlEvent theEvent) {
String user = tfName.stringValue ();
String pass = tfPass.stringValue ();
// Wenn Textfeldinhalte jeweils länger als 0 sind
if (user.length () > 0 && pass.length () > 0) {
// GUI ausblenden
tfName.hide ();
tfPass.hide ();
// API INITIALISIEREN
fm = new Lastfm (user, pass, "xx", "xx");
// Startschuss für den draw-Block geben
ready = true;
}
}
Zufällige Positionen in Freiform ermitteln (bitmap trick)
Der folgende Sketch ermittelt zufällige Positionen innerhalb einer vorgegebenen Maske (Freiform), und stellt diese durch kleine Kreuze im Sketchfenster dar.

Die rein mathematische Lösung für einen zufälligen Punkt in einer Freiform ist für unser Anliegen zu aufwendig. Im Folgenden bedienen wir uns dem Trick einer Maskierung durch ein Pixelbild. Dieses besteht im Idealfall nur aus schwarzen und weißen Pixeln – wobei die schwarzen die Form bestimmen. Die get() Funktion, zum Auslesen von Farbwerten, wird in einer Funktion platziert, welche die zufällig ermittelte Position zurück gibt. Da sich eine Funktion auch selbst aufrufen kann (Rekursion), ist diese in der Lage so lange zu suchen, bis ein Punkt innerhalb der Form bestimmt wurde.
Weil eine Funktion nur eine Variable als Rückgabewert zur Verfügung hat, verwenden wir einen Vektor.
PVector imgPos; // Position der Maske im Sketch
PImage img; // Kontainer für die Masek
void setup () {
size (240, 160);
// Laden der Maske
img = loadImage ("cloud.png");
// Vektor für die Position der Maske im Sketch
imgPos = new PVector ();
// Maske im Fenster zentrieren
imgPos.x = (width - img.width) / 2;
imgPos.y = (height - img.height) / 2;
}
void draw () {
background (255);
for (int i=0; i < mouseX * 2; i++) {
// Ermittle eine zufällige Position in der Maske
PVector pos = randomPoint (img, imgPos);
// Zeichne ein kleines Kreuz an dieser
drawCross (pos);
}
}
/**
* Funktion ermittelt rekursiv die Position eines Pixels
* in einem gegebenen Bild, welches schwarz ist. Diese
* Koordinaten werden mit der Bildposition (Vektor)
* summiert und zurückgegeben.
*/
PVector randomPoint (PImage theImage, PVector thePos) {
// Zufallsposition im Bild
int x = (int) random (theImage.width);
int y = (int) random (theImage.height);
// Wenn Pixel an Position x,y schwarz ist
if (brightness (theImage.get (x, y)) == 0) {
// Gibt die Position als Vektor zurück
return new PVector (thePos.x + x, thePos.y + y);
}else{
// Sonst versuche es erneut
return randomPoint (theImage, thePos);
}
}
/**
* Funktion zeichnet ein Kreuz an dessen Mittelpunkt.
*/
void drawCross (PVector thePos) {
line (thePos.x-1, thePos.y-1, thePos.x+1, thePos.y+1);
line (thePos.x-1, thePos.y+1, thePos.x+1, thePos.y-1);
}
Arbeiten mit Zeitangaben
Hier ein kleines Beispiel für alle die mit chronologischer Reihung von Inhalten arbeiten. Es basiert auf dem Beitrag Twitter in Processing und stellt die letzten 200 Nachrichten eines Nutzers innerhalb der vorliegenden Zeitspanne dar.

Datumsangaben & Processing
Innerhalb von Processing nutzt man für Datumsangaben die Date-Klasse. Dabei dreht es sich (schrägerweise) um die verstrichenen Millisekunden seit dem 01.01.1970 (auch UNIX Time genannt). Durch diese abstrakte Repräsentation können Zeitpunkte einfach durch Operatoren verglichen bzw. Differenzen ermittelt werden. Der aktuelle Wert ist demnach ziemlich groß und passt nicht mehr in den Wertebereich eines Integers (int). Als nächst höhrerer Datentyp werden die Millisekunden deshalb in einer Variable vom Typ long gespeichert.
Axiale Verteilung
Um einen Datensatz chronologisch auf einer Achse zu verteilenen, benötigen wir drei Informationen:
- Startzeitpunkt, ältester Eintrag
- Endzeitpunkt, jüngster Eintrag
- die aus beiden Zeitpunkten resultierende Zeitspanne
Im setup() durchläuft eine for-Schleife alle Twitter-Nachrichten und ermittelt den Beginn und das Ende des Zeitraumes. Dieser wird direkt nach der Schleife festgelegt und in Zeile 45 berechnet. Am Ende des setup()-Blocks werden zum Überprüfen beide Grenzen als Datum formatiert in der Konsole ausgegeben.
Startzeitpunkt und Zeitspanne dienen als Grundlage zur Verortung der einzelnen Nachrichten auf der x-Achse im Sketch. Das Verhältnis einer jeden Nachricht (Zeitraum zwischen der Veröffentlichung zum Startzeitpunk) zur gesamten Zeitspanne ergibt einen Wert zwischen 0 und 1. Dabei ist 0 der Startzeitpunkt und 1 der Moment an dem der letzte Beitrag erschien. Dieser Wert mulipliziert mit der Länge der Zeitachse ergibt die Position auf ihr. Im unteren Beispiel wird die gesamte x-Achse als Zeitleiste angesehen. Folglich wird der Faktor auf die Breite des Fensters angewendet. Im letzten Schritt wird die Textlänge der Beiträge für die Lage der Linien genutzt.
Fazit
Knackpunkt bei der Verteilung ist die Berechnung in Zeile 68, durch das Mappen der relativen Position des Zeitpunktes in der Zeitspanne auf die Repräsentation mit der Länge der Zeitachse. Da die Twitter-Nachrichten chronologisch sortiert geladen werden, hätte man die erste Schleife im setup() enfallen lassen können. Zur Vollstänigkeit haben wir trotzdem die umständliche Version gewählt.
import twitter4j.org.json.*;
import twitter4j.*;
import twitter4j.http.*;
import twitter4j.examples.*;
import java.util.List;
import java.util.Date;
List stats; // Liste der Twitter-Einträge
long timeMax; // time-stamp aktuellster Eintrag
long timeMin; // time-stamp ältester Eintrag
long timeDur; // Zeit zwischen ältestem und aktuellstem
void setup () {
size (580, 150);
Twitter tw = new Twitter ("Benutzername", "Passwort");
// Startwerte der von min und max definieren.
// Diese Werte sind unrealistisch für beide Größen.
timeMax = 0;
timeMin = -1;
try {
// Die letzten 200 Twitter-Einträge des Benutzers.
// (muss nicht der bei 'new Twitter(' angegebene sein)
stats = tw.getUserTimeline ("Benutzername", 200);
// Für jeden Twitter-Eintrag ('Status')
for (int i=0; i < stats.size(); i++) {
Status stat = (Status) stats.get (i);
// Zeitpunkt der Veröffentlichung
long time = stat.getCreatedAt ().getTime ();
// Ist der Eintrag der erste?
if (time < timeMin || timeMin == -1) {
timeMin = time;
}
// oder der letzte?
if (time > timeMax) {
timeMax = time;
}
}
// Zeitspanne zwischen dem ersten
// und dem letzten Eintrag in der Liste
timeDur = timeMax - timeMin;
}catch (Exception e) {
println (e);
}
println ("start: " + new Date (timeMin));
println ("end: " + new Date (timeMax));
}
void draw () {
background (40);
stroke (255, 150);
Status stat; // Var. zum Ablegen eines Eintrages
double time; // Var. für die Zeitspannenberechnung
// Für jeden Twitter-Eintrag ('Status')
for (int i=0; i < stats.size (); i++) {
stat = (Status) stats.get (i);
// Zeitspanne im Vergleich zum ältesten Eintrag
time = stat.getCreatedAt ().getTime () - timeMin;
// Lage auf der x-Achse
float x = width * (float) (time / timeDur);
// y-Position der Linienenden, bestimmt durch Textlänge
float y1 = height / 2 - stat.getText ().length () / 2;
float y2 = height / 2 + stat.getText ().length () / 2;
line (x, y1, x, y2);
}
}
Twitter in Processing
Hier kurz ein paar Zeilen zum Auslesen von Twitter-Profilen mit Processing.
Installation
- Laded die Bibliothek twitter4j, aktueller Stand ‘twitter4j-2.0.7′.
- Entpackt die zip und benennt die Datei ‘twitter4j-2.0.7.jar’ in ‘twitter4j.jar’ um.
- Geht in euren Processing-libraries Ordner und erstellt dort zwei Ordner: ‘Processing/libraries/twitter4j/library/’.
- Kopiert die gerade in ‘twitter4j.jar’ umbenannte Datei in den angelegten Ordner library.
Mit diesem ‘Trick’ kann das toolkit, zur Kommunikation mit twitter, in Processing geladen werden. Im üblichen Menü ‘Sketch’ -> ‘Import Library…’ erscheint nun ‘twitter4j’ neben allen weiteren Processing libraries. Mit einem Klick werden euch alle verfügbaren Klassen importiert.
Umgang
Der Umgang mit der library bedarf ein paar neuer Befehle. Try-Catch ist zum Ausführen von Prozessen die auch gerne mal nicht funktionieren können. In diesem Fall das Laden der Daten via Internet. Um direkt einen Plan-B anzugeben, gibt es den Catch-Block. Weiterhin werden die Ergebnisse in sog. Listen (ähnlich den ArrayList(s)) gespeichert. Damit Processing damit umgehen kann, muss diese Klasse ebenfalls am Anfang importiert werden. Hier ein Beispiel:
UPDATE: 08/06/2009
import twitter4j.org.json.*;
import twitter4j.*;
import twitter4j.http.*;
import twitter4j.examples.*;
// Liste wird gebraucht um timeline-
// Einträge zu speichern
import java.util.List;
// Liste an Twitter-Stats wird global abgelegt
List stats;
void setup () {
// Erzeuge die 'Schnittstelle' zu twitter mit
// eigenem Benutzer/Passwort
Twitter tw = new Twitter ("Benutzername", "Passwort");
// try-catch Kombination zum Abfangen von Fehlern
try {
// Lade die letzten 200 Einträge aus der
// Twitter-timeline des users
stats = tw.getUserTimeline ();
// Für jede nachricht in der timeline
for (int i=0; i < stats.size(); i++) {
// Type-casten der Nachrichten als
// Instanzen der Klasse 'Status'
Status stat = (Status) stats.get (i);
println (stat.getText ());
}
}catch (Exception e) {
println (e);
}
}
void draw () {
// crazy stuff
}
Das JavaDoc enthält den kompletten Funktionsumfang (zum Start reicht aber erst mal die Twitter-Klasse der library).



