everything comes to an end…

05 Feb

Nun ist es soweit,┬á mein kleines Programm ist fertig und es doch eine Art Spiel geworden. Der Code ist auskommentiert und alles funktioniert so, wie ich es angedacht habe. Und dass alles sogar noch 2 Tage vor Abgabe. ­čÖé

An dieser Stelle ein gro├čes Dankesch├Ân an Markus, der meine verzweifelten Emails geduldig beantwortet und mir damit oftmals sehr weitergeholfen hat. Und nat├╝rlich auch an alle, die mir bei diesem Projekt geholfen und mich mental unterst├╝tzt haben. Ich werde Processing jedenfalls nicht vergessen und, wenn sich ein Projekt anbietet, auch mal wieder darauf zur├╝ckgreifen.

F├╝r alle, die die eigene Stimme gern mal auf die Probe stellen m├Âchten, sind hier die Dateien:

Version f├╝r Windows

Version f├╝r Mac OS X

Version f├╝r Linux

Und zu guter Letzt noch ein paar Screenshots:

Bubbles

Ausgangsbild

Bubbles platzen

Bubbles platzen

press any key to try again…

05 Feb

Nun ist es vollbracht. Auch das letzte Problem ist nun beseitigt. Mithilfe von meinen Kommilitonen Annabel und Manuel, die mir erkl├Ąren konnten, warum ich diese letzte Fehlermeldung gekriegt habe, funktioniert nun das Neustarten des Sketches ├╝ber Tastatur. An dieser Stelle nochmal danke f├╝r eure Hilfe ­čÖé

Das Problem war, dass ich meine Variablen au├čerhalb von dem setup()-Teil gesetzt und mit Werten versehen habe. Damit ich aber den Sketch neustarten kann, m├╝ssen die Variablen in dem setup()-Teil selbst mit Werten versehen werden. Nur so k├Ânnen diese Variable am Ende wieder auf Anfang gesetzt werden. Es ist eigentlich ein sehr simples Problem, jedoch w├Ąre ich nicht alleine darauf gekommen, dass ich einfach nur die Variablen im setup() mit Werten bef├╝llen muss, um es zu l├Âsen.

Nun funktioniert es folgenderma├čen: Solange noch Bubbles auf dem Screen zusehen sind, kann der Sketch nicht neugestartet werden. Sobald alle Bubbles von Screen weg sind, erscheint Text in dem steht, wie lange man daf├╝r gebraucht hat, um den kompletten Screen frei zu kriegen. Hinterher steht noch der Hinweis, dass man mit beliebiger Taste den Sketch neu starten kann.

Hier ein Bild dazu:

Endscreen

Endscreen

the small things count too…

27 Jan

Nun, da es f├╝r die gro├čen Kreise funktionierte, machte ich mich an die kleinen Kreise und die Partikel f├╝r die kleinen Kreise. Meine Idee war es, einfach die Klasse f├╝r die Partikel und alles damit verbundene zu kopieren und umzubenennen. Es ist vielelicht nicht die eleganteste L├Âsung, aber mit Blick auf den Pr├Ąsentationstermin ist es f├╝r mich die attraktivste. ­čÖé

Ich erstellte also die eine zweite Partikelklasse und dazugeh├Ârige Funktionen┬á und Variablen. Nachdem ich dann auch endlich alle meine Copy+Paste-Fehler beseitigt habe, funktionierte es tats├Ąchlich! Nun musste ich nur noch die richtigen Schwellenwerte f├╝r die Frequenzb├Ąnder finden. Nach einigem Summen, Kreischen und Singen hatte ich dir richtigen Schwellenwerte sowohl f├╝r die hohen als auch f├╝r die tiefen T├Âne gefunden. Zudem passte ich noch die frameRate() an. Ich habe gemerkt, dass bei der Default-Einstellung von 60 Frames/Sekunde die Kreise viel zu schnell platzen. Deswegen drosselte ich den Audioinput auf 10 Frames/Sekunde.

Am Ende f├╝gte ich noch eine if-Bedingung an, in der ich abfragte, ob der beide Arrays, die der gro├čen und die der kleinen Kreise, gleich null sind. Falls ja, dann wird ein Text ausgegeben, in dem unter anderem die Zeit angezeigt wird, die der Nutzer gebraucht hat, um die Kreise von dem Screen wegzul├Âschen. Das Anzeigen der Weit war jedoch gar nicht so einfach. Daf├╝r muss man die Funktion millis() verwenden. Doch bevor man es tut, muss man mithilfe einer if-Bedingung die Zeit in eine andere Variable reinspeichern und „stoppen“. Am Ende sieht es so aus:

/////////////////////////ALL CLEARED
 if (bigKreiseArray.length == 0 &&  smallKreiseArray.length == 0 && endReached == false) {
   millisek = millis();
   sekunden = (int) millisek / 1000;
   endReached = true;
 }
 if (endReached == true){
   textFont (f,20);
   textAlign (CENTER);
   fill (200);
   text ("Wow!", 320, 190);
   text ("You destroyed all bubbles in " + sekunden + " seconds.", 320, 250);
   text ("Press any key to try again!", 320, 310);
}

Was ich noch versucht aber bis jetzt noch nicht geschafft habe, ist, dass der Sketch neu startet, wenn der Nutzer am Ende eine Taste dr├╝ckt.

if(endReached == true && restart == true){
   setup();
   restart = false;
}

—-

void keyPressed(){
  restart = true;
}

Wenn ich den Code ausf├╝hre und dann am Ende eine Taste dr├╝cke, bekomme ich die Meldung:

==== JavaSound Minim Error ====
==== Error acquiring TargetDataLine: line with format PCM_SIGNED 44100.0 Hz, 16 bit,
stereo, 4 bytes/frame, little-endian not supported.

Ich werde mal schauen, dass ich die Fehlermeldung irgendwie wegkriege. Ich hoffe, dass es mir gelingt.

particles all over…

26 Jan

Ich habe nach l├Ąngerem Suchen im Internet eine Partikel-Klasse gefunden, die perfekt zu dem passt, das ich machen m├Âchte. Auf dieser Webseite befindet sich das Partikelsystem, dass ich benutzt habe. Ich habe den Code modifiziert, sodass die Partikel sich nicht mehr in einer Rechtecks-Form ausbreiten, sondern in einem Kreis. Aber noch bestand das Problem, dass alle alten Partikel verschwanden, sobald man mit der Maus geklickt hat. Ich wollte jedoch, dass die alten Partikel immernoch zu sehen sind, w├Ąhrend neue entstehen. Das Problem war, dass in meiner Partikel-Vorlage ein Array erstellt wird, in welches die Objekte reingeladen werden. Sobald man mit der Maus geklickt hat, wurde ein neues Array erstellt. Was ich aber gebraucht habe, war das Hinzuf├╝gen von Elementen zu einem bestehenden Array. Wenn immer neue Objekte hinzugef├╝gt werden w├╝rde, dann w├╝rden die alten nicht einfach verschwinden. Jedoch ist die L├Ąnge eines Array fest und l├Ąsst sich im nachhinein nicht mehr ver├Ąndern. Deswegen musste ich auf die ArrayList ausweichen. Diese l├Ąsst sich auch noch im Nachhinein leicht erweitern. Mein nochmals modifizierter Code f├╝r die Partikel sah folgenderma├čen aus:

int NUM_PARTICLES = 100;
ArrayList particles; 

void setup() {
 size(400, 400);
 stroke(255);
 fill(250,0,150);
 smooth();

 particles = new ArrayList(); //neue ArrayList wird erstellt

}

void draw() {
 background(0);
 for (int i = particles.size() - 1; i>= 0; i--) {   // alle Partikel, die sich in
   Particle particle = (Particle) particles.get(i); // der ArrayList befinden,
   particle.exist();                                // werden gezeichnet
 }  
}

void mousePressed() {
 for (int i = 0; i < NUM_PARTICLES; i++) {
   particles.add(new Particle()); //Partikel werden zur ArrayList hinzugef├╝gt
 }
}

public class Particle {
 float x, y;     
 float vx, vy;   
 float ax, ay;
 float degree = random (0,2*PI); //legt Richtung fest, in die sich Partikel ausbreiten float r = 1;

 public Particle() {
   x = mouseX;
   y = mouseY;    
   vx = vy = 0f;
   ax = random(r * cos(degree))/5; //diese beiden Zeilen legen fest,
┬á  ay = random(r * sin(degree))/5; //dass sich die Punkte kreisf├Ârmig ausbreiten
 }

 public void exist() {
   vx += ax;
   vy += ay;
   x += vx;               
   y += vy;  
   point(x, y);
 }

}

Diesen Code habe ich nun in mein Programm integriert. Nach und nach habe ich alles angepasst. So habe ich es erst einemal mit Mausklick ausprobiert und als alles mit Maus funktioniert hat, habe ich das Erscheinen der Partikel nun in meine if-Bedingung aufgenommen, in der festgelegt ist, dass nur dann etwas geschieht, sobald ein bestimmter Wert f├╝r einen Freuquenz-Balken ├╝berschritten ist. Das hat nach einigen Trial-and-Errors auch so geklappt. Jedoch erschienen die Partikel nun immer im Ursprung (0|0) und nicht da, wo gerade ein Kreis geplatzt ist. Um das zu ├Ąndern muss ich die Position des letzten Kreises im Array herausfinden. Ich habe versucht das durch das dirikte Zugreifen auf die Eigenschaften des jeweiligen Objektes zu machen.

bigKreiseArray[p_gross].position_x //position_x ist die Variable in der der random-x-Wert gespeichert ist
bigKreiseArray[p_gross].position_y//position_y ist die Variable in der der random-x-Wert gespeichert ist

Ich bekam jedoch immer, wenn der erste Kreis geplatzt ist folgende Fehlermeldung: NullPointerException.

Das lag daran, dass das Objekt aus dem ich die Werte herausgelesen habe ja nicht mehr exisitiert hat, sobald das Array, in dem es sich befand um 1 gek├╝rzt wurde. Deswegen musste ich die Werte in eine seperate Variable speichern.

/////////// Position der gro├čen Kreise festhalten ////////////////////////
for (zaehler = bigKreiseArray.length-1; zaehler >= 0; zaehler--) {
  x_pos_particle[zaehler] = bigKreiseArray[zaehler].position_x; // die Positionen in ein Array speichern
  y_pos_particle[zaehler] = bigKreiseArray[zaehler].position_y;
  x_particle = x_pos_particle[zaehler]; // den Wert f├╝r den jeweils aktuellen Kreis herauslesen
  y_particle = y_pos_particle[zaehler]; // Variable 'zaehler' ist global und wird auch sp├Ąter
                                        // f├╝r das K├╝rzen des Arrays vewendet
}

/////////// Partikel f├╝r gro├če Keise zeichnen ////////////////////////
 for (int i = particles.size()-1; i >= 0; i--) {
   Particle particle = (Particle) particles.get(i);
   particle.exist(); // Warum klappt das nicht?
 }

/////////// gro├če Kreise aus dem Array l├Âschen sobald Sound vorhanden ist ////////////////
 for (zaehler = bigKreiseArray.length-1; zaehler >= 0; zaehler--) {
   if (band8 == true && keinBand8 == false) {
 //shorten Array
   bigKreiseArray = (Kreis[]) shorten(bigKreiseArray);
   keinBand8 = true;
   ehemalsMousePressed(x_pos_particle[zaehler],y_pos_particle[zaehler]);
   }
 }

Damit hat es dann auch funktioniert. Nun wurden die Partikel immer da gezeichnet, wo gerade ein Kreis verschwunden ist. Hier ist der bisherige Stand der Datei:

Stand 26_01_2011

3.. 2.. 1.. next steps!

15 Jan

Die ganze Idee war ja am Anfang eigentlich als eine Art Spiel angedacht. Ich dachte da an Level mit ansteigendem Schwierigkeitsgrad. Heute ist mir jedoch klar geworden, dass das eingentlich nur sehr viel Programmierlogik bedeuten w├╝rde und nicht mehr das behandeln w├╝rde, worum es wirklich geht: Sound-Vizualisierung. Statt den verschiedenen Leveln habe ich nun entschieden, dass ich mich eher auf die Vizualisierung von den Verschwindungsprozessen der Kreise konzentrieren werde. Es gibt wirklich viele M├Âglichkeiten, wie man dieses „Platzen“ oder „Verschwinden“ der Kreise wirklich sch├Ân f├╝r das Auge gestalten k├Ânnte. Ich werde mich daf├╝r ein bisschen in die B├╝cher st├╝rzen und mal schauen, was es da zum Beispiel an Partikelvisualisierungen gibt. Vielleicht finde ich eine sch├Âne Library, die ich daf├╝r modifizieren k├Ânnte. Ich werde auch jeden Fall ein wenig herumexperimentieren. Auf gehts!

after the rain comes sun…

15 Jan

Nach einer l├Ąngeren Phase der Stagnation und Verzweiflung gab es heute endlich wieder Fortschritte. Nachdem es sich als sehr schwierig erwiesen hat, im Internet wirklich brauchbare Informationen zu meinem Problem zu finden, habe ich mir in der Bibliothek nun zwei Processing-B├╝cher ausgeliehen. Das hat auch gleich was gebracht, denn da habe ich die Methode gefunden, nach der ich gesucht habe. Das Zauberwort hei├čt „shorten()“. Mit dieser Methode kann man sehr einfach ein Array k├╝rzen. Dabei wird immer das letzte sich im Array befindliche Objekt gel├Âscht. Das ist genau das, wonach ich gesucht habe. Das Konstrukt zum l├Âschen einzelner Kreise durch Mausklick sieht folgenderma├čen aus:

boolean mausReleased = false;
[...]
void draw () {
[...]
  for (int i = bigKreiseArray.length-1; i >= 0; i--) {
      if (mousePressed == true && mausReleased == false){
      //shorten Array
      bigKreiseArray = (Kreis[]) shorten(bigKreiseArray);
      mausReleased = true;
      }
  }
}
[...]
void mouseReleased() {
      mausPressed = false;
}

Weiterhin habe ich mich an der Sound-Anbindung versucht. Die Grundidee ist, dass ich ein Frequenz-Band aus der minim_FFT_Normalize-Library ausw├Ąhle und dieses dazu benutze, um die Kreise in gleicher Weise wie mit der Maus zu l├Âschen. Dabei lege ich einen Wert fest, den das Band mindestens annehmen muss, damit sichergestellt werden kann, dass dieser Ton nicht zuf├Ąllig, sondern gewollt getroffen wurde. Klingt kompliziert, sollte aber eigentlich ganz einfach gehen. Und zwar in etwa so:

boolean band8 = false;
boolean keinBand8 = false;
[...]
void draw() {
[...]
//erstmaliger Funktionsaufruf
  checkBand();
  checkKeinBand();
[...]
  for (int i = bigKreiseArray.length-1; i >= 0; i--) {
      if (band8 == true && keinBand8 == false){
        //shorten Array
        bigKreiseArray = (Kreis[]) shorten(bigKreiseArray);
        keinBand8 = true;
      }
  }
}

void checkBand () {
  if (fftLog.getAvg(8) > 4){
    band8 = true;  
  }
} 

void checkKeinBand () {
  if (fftLog.getAvg(8) <= 4){
    keinBand8 = true;
  }
}

Hier habe ich zum Beispiel das achte Band von links ausgew├Ąhlt. Wenn dieses den Wert 4 ├╝berschreitet, dann wird die Variable band8 auf true gesetzt. Wenn diese Variable true ist und die Variable keinBand8 false, dann sollte ein Kreisobjekt aus dem Array gel├Âscht werden.

Leider funktioniert das noch nicht so wie gewollt, ich werde mich in den n├Ąchsten Tagen damit auseinander setzen und versuchen den Fehler zu finden. Leider kriege ich keine Fehlermeldung, das hei├čt, das der Fehler darin besteht, dass der Wert an irgendeiner Stelle nicht abgefangen werden kann. Bald wissen wir mehr ­čÖé

stagnation…

29 Dez

Heute wollte ich mal ausprobieren, wie ich einen Kreis aus dem Array erstmal per Maus-Klick wieder wegkriege. Ich habe ein wenig im Internet recherchiert und rausgekriegt, dass es da die folgende M├Âglichkeite gibt: das Objekt auf null setzen. Damit w├╝rde es praktisch aufh├Âren zu existieren. Jedoch will das bei mir nicht so richtig klappen. Ich habe ja ein aus einer Klasse ein Array generiert, in dem 20 identische Kreise drin sind. Hier ist die Klasse:

class Kreis {
 float position_x;
 float position_y;
 int diameter;
 Kreis(float tempX, float tempY, int tempDiameter) {
 position_x = tempX;
 position_y = tempY;
 diameter = tempDiameter;
 }

 void display_gross () {
 ellipse(position_x, position_y, diameter, diameter);
 strokeWeight(4);
 stroke(255,0,100);
 }

 void display_klein () {
 ellipse(position_x, position_y, diameter, diameter);
 strokeWeight(4);
 stroke(136);
 }
}

Hier ist das Array, das ich daraus generiere:

Kreis[] bigKreiseArray = new Kreis[20];

Jetzt m├Âchte ich gern programmieren, dass immer dann, wenn die Maus gedr├╝ckt wird, ein Objekt aus dem Array entfernt werden soll. Jedoch ist mir noch nicht ganz klar, wie ich das hinkriege. Ich kriege bei jedem Versuch lauter Fehlermeldungen. Wenn ich es z.B. auf diese Weise versuche

for (int i = 0; i < bigKreiseArray.length; i++) {
  bigKreiseArray[i].display_gross();
}

for (int i = bigKreiseArray.length-1; i >=0; i--) {
  if (mousePressed){
    bigKreiseArray[i] = null;
  }
}

dann bekomme ich folgende Fehlermeldung, sobald ich mit der Maus auf den Ausgabe-Screen klicke:

processing.app.debug.RunnerException: NullPointerException
  at processing.app.Sketch.placeException(Sketch.java:1543)
  at processing.app.debug.Runner.findException(Runner.java:582)
  at processing.app.debug.Runner.reportException(Runner.java:558)
  at processing.app.debug.Runner.exception(Runner.java:498)
  at processing.app.debug.EventThread.exceptionEvent(EventThread.java:367)
  at processing.app.debug.EventThread.handleEvent(EventThread.java:255)
  at processing.app.debug.EventThread.run(EventThread.java:89)
Exception in thread "Animation Thread" java.lang.NullPointerException
  at Array_grosse_kleine_Kreise_remove_per_mouse.draw(Array_grosse_kleine_Kreise_remove_per_mouse.java:54)
  at processing.core.PApplet.handleDraw(Unknown Source)
  at processing.core.PApplet.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:619)

Irgendwie komme ich nicht weiter… Stagnation.

first steps done…

28 Dez

Das einfachste ist nun erledigt: Ich habe zwei Arrays erstellt, mit Hilfe derer meine Kreise erstellt werden. Grafisch ist das Ganze noch nicht wirklich ausgereift, aber mir gings in erster Linie darum, dass es ├╝berhaupt funktioniert. Was mich grad auch noch ein wenig st├Ârt ist, dass ein kleiner Kreis immer in der Farbe der gro├čen Kreise ist. Ich wei├č aber grad noch nicht, wie ich Processing da austricksen k├Ânnte. So sieht es bislang aus:

Array_kleine_grosse_Kreise

Um die Kreise zu zeichnen habe ich eine Klasse „Kreis“ angelegt. Dieser Klasse habe ich zwei Methoden zugeordnet:

void display_gross () {
 ellipse(position_x, position_y, diameter, diameter);
 strokeWeight(4);
 stroke(255,0,100);
 }

void display_klein () {
 ellipse(position_x, position_y, diameter, diameter);
 strokeWeight(4);
 stroke(136);
 }

Damit werden einmal graue und das andere mal pinkfarbene Kreise gezeichnet. Dabei habe ich das so beschr├Ąnkt, dass die Kreise nie ├╝ber der Rand des Anzeigebildschirms hinausragen.

int diameter_big = 100;
float position_X = random(diameter_big/2, width - diameter_big/2);
float position_Y = random(diameter_big/2, height - diameter_big/2);

Auf die Klasse greife ich beim Erstellen des Arrays wieder zu:

Kreis[] bigKreiseArray = new Kreis[20];
Kreis[] smallKreiseArray = new Kreis[20];

Zuerst hab ich versucht, die Kreise einfach nur mit einer for-Schleife zu erstellen. Das hat auch geklappt und visuell gab es keinen Unterschied zu dem Bild jetzt. Das Problem war nur, dass ich ja auf jeden einzelnen Kreis wieder zugreifen k├Ânnen muss. Ich will sp├Ąter ja jeden Kreis einzeln und nacheinander mit der Eingabe einer bestimmten Frequenz wieder l├Âschen. Die M├Âglichkeit habe ich allein mit der for-Schleife aber nicht. Jedenfalls kenne ich keine M├Âglichkeit, wie es dar├╝ber gemacht werden kann. Deswegen musste ich an dieser Stelle auf das Array zur├╝ckgreifen. Damit sollte ich die M├Âglichkeit haben, jedes Element ├╝ber den Index anzusprechen. So ist es jedenfalls in PHP und ich hoffe, dass ich mit der Taktik auch in Processing durchkomme ­čÖé

Noch bin ich mir nicht sicher, ob das alles so klappt wie ich es angedacht habe, aber ich werde flei├čig weiter herumexperimentieren.

finally the idea appeared…

28 Dez

Alles k├Ânnte so einfach sein…

Doch dann w├Ąrs wahrscheinlich langweilig. Nachdem mir wirklich lange keine Ideen zum Thema Soundvisualisierung in Processing eingefallen sind, kam heute morgen noch ich ganz verschlafenen Zustand DIE Idee.

the idea

Es handelt sich um ein Spiel. In einem 640 x 480 px gro├čen Fenster werden viele Kreise dargestellt. Im ersten Level gibt es zwei verschieden Kreisgr├Â├čen. Das Ziel des Spieles ist es, den Screen komplett von Kreisen zu befreien. Das schafft man in dem man verschiedene T├Âne ins Mikrofon summt/singt/von sich gibt. Hohe T├Âne l├Âschen nacheinander die kleinen Kreise, tiefe T├Âne die gro├čen. Wenn alle Kreise gel├Âscht sind, geht man ├╝ber ins n├Ąchste Level.

So ungef├Ąhr wird es aussehen:

Level 1

Level 1

Bei der Soundeingabe werde ich mit der minim_FFT_Normalize-Library arbeiten. Ich muss mir noch ├╝berlegen, ob ich bestimmte Frequenzen nehme, um die Kreise zu l├Âschen oder ob ich das ganze Frequenzspektrum in zwei Teile teile. Dann w├╝rde alles bis zu einer bestimmten Frequenz „tiefer Ton“ sein, alles andere dr├╝ber dann „hoher Ton“. Mir gefallen eignetlich beide Optionen. Jedoch denke ich dass es schwieriger und interessanter ist, wenn man eine bestimmte Frequenz treffen muss.

Wenn alles mit dem ersten Level klappt, dann k├Ânnte man sich noch ├╝berlegen, ob man nicht ein zweites Level hinzuf├╝gt. In diesem k├Ânnte man z.B. 3 verschiedene Kreisgr├Â├čen einbauen, sodass man 3 verschiedene Frequenzen treffen muss.

So viel zu der Idee…

blackbox

28 Dez

Mein Name ist Julia Borger und ich studiere Informationsdesign an der Hochschule der Medien in Stuttgart. Dieser Blog entsteht im Rahmen der Wahlpflicht-Lehrveranstaltung „Visuelles Programmieren“. Ziel der Veranstaltung ist es mithilfe von Processing, einer auf Java besierenden Programmiersprache und -umgebung, Sound zu visualisieren. Es gibt keine Vorgaben, wie das aussehen muss, von Sound-Vizualizer ├╝ber hin zum Spiel ist alles erlaubt. Dieser Weblog ist Teil der sp├Ąteren Pr├╝fungsleistung und wird alles enthalten und erkl├Ąren, was ich im Rahmen dieser Veranstaltung gemacht habe, was geklappt hat, was misslungen ist und wie das tats├Ąchliche Endergebniss aussieht.

blackbox

ÔÖą Processing ÔÖą