Idea
As you have read previously, I planned on creating a generative interactive art piece. However, with frequent feedback and suggestions, the idea is now more of a piano with art on screen. The distance sensor on Arduino helps to identify from where to drop balls from the top and bounce on screen and the potentiometer allows the user to select the color of the balls. As soon as the user moves hands away from the setup, the art form stops with the new production of balls. The sound to be played is dependent on where exactly on the bottom the balls hit.
To stick with a theme, the color palette is defined to be following:
One concern is that the colors on the screen are different from what was printed on the knob. I’m not sure how I can fix this but I hope it is not a big issue.
The tunes were collected as samples but still require some more work to have a better general music sound. The overall interaction design (that includes a bigger circuit wiring and piano theme cardboard layout) is still under process.
User Testing
Feedback
- add different shapes (will try and depending on better aesthetic will finalize)
- allow for faster response
- better positioning of distance sensor
- fun to play
Code
//Main Project Processing File //Serial connection and sound import processing.serial.*; import processing.sound.*; Serial myPort; //variables for color mapping int count = 400; float radToDeg = 180.0 / PI; float countToRad = TWO_PI / float(count); float currentcolor; float Xslider; boolean playing = false; boolean fade = false; //array list for balls ArrayList<Ball> balls; //sounds SoundFile[] files; int numsounds = 10; void setup() { fullScreen(); //size(800,600); noStroke(); frameRate(25); //port communication String portname=Serial.list()[0]; myPort = new Serial(this,portname,9600); // Create an empty ArrayList (will store Ball objects) balls = new ArrayList<Ball>(); //sounds files = new SoundFile[numsounds]; for (int i = 0; i < numsounds; i++) { files[i] = new SoundFile(this, (i) + ".wav"); }; colorMode(HSB,360,99,99); } void draw() { background(0,0,99); if(frameCount%30==0 && fade == false){ addBalls(7); } for (int i = balls.size()-1; i >= 0; i--) { Ball ball = balls.get(i); ball.move(); ball.display(); if(ball.x <= Xslider-width/5 || ball.x >= Xslider+width/5 || fade==true){ if(ball.life > 200){ ball.life = 150; } } if(ball.y >= height){ int numsound = int(map(ball.x,0,width,0,9)); playSounds(numsound); } if (ball.finished()) { balls.remove(i); } } } void playSounds(int numsound){ if(numsound>=0 && numsound<=9 && !files[numsound].isPlaying() ){ files[numsound].play(); } for(int i=0;i<10;i++){ if(files[i].isPlaying() && i!=numsound){ if(frameCount%20==0){ files[i].stop(); } } } } void addBalls(int count) { // A new set of x ball objects are added to the ArrayList for(int i=0; i<count; i++){ float randomS = random(3,10); float ballWidth = random(4,30); float xPos = random(Xslider-width/10, Xslider+width/10); float yPos = random(-100,0); float angle = currentcolor * countToRad; int hue = int(angle * radToDeg); balls.add(new Ball(xPos, yPos, ballWidth,randomS,hue)); } } //Serial Communication void serialEvent(Serial myPort){ String s=myPort.readStringUntil('\n'); s=trim(s); if (s!=null){ int values[]=int(split(s,',')); if (values.length==2){ currentcolor = map(values[0],0,1023,290,380); if(values[1]>150 && values[1]<1700){ fade= false; Xslider= map(values[1],150,1700,width, 0); } else{ fade = true; } } } }
// Simple bouncing ball class float noiseScale = 700; class Ball { float x; float y; float speed; float gravity; float w; float life = 370; int colorhue; boolean bounced= false; Ball(float tempX, float tempY, float tempW, float tempS, int hue) { x = tempX; y = tempY; w = tempW; speed = tempS; colorhue = hue; gravity = 0.1; } void move() { // Add gravity to speed speed = speed + gravity; // Add speed to y location y = y + speed; float noiseVal = noise(x*noiseScale); int sign; if(Xslider<width/2){ sign = -1; } else{ sign = 1; } noiseVal = sign * noiseVal; // If ball reaches the bottom // Reverse speed if (y > height) { // Dampening speed = speed * -0.9; y = height; bounced = true; } if(bounced==true){ x = (noiseVal+x); } if(bounced==true && y<=10){ // Dampening speed = speed * -0.9; y = 10; bounced = false; } } boolean finished() { // Balls fade out life--; if (life < 0) { return true; } else { return false; } } void display() { // Display the circle fill(color(colorhue,99,99),life); ellipse(x,y,w,w); } }
//Arduino Code int trigger_pin = 2; int echo_pin = 3; long pulse_duration; void setup() { Serial.begin(9600); pinMode(trigger_pin, OUTPUT); pinMode(echo_pin, INPUT); digitalWrite(trigger_pin, LOW); Serial.println("0,0"); } void loop() { int sensor = analogRead(A0); digitalWrite(trigger_pin, HIGH); digitalWrite(trigger_pin, LOW); pulse_duration = pulseIn(echo_pin, HIGH); Serial.print(sensor); Serial.print(','); Serial.println(pulse_duration); }