/* silhouettes by nick lally, with help from: Frame Differencing Example by Golan Levin. http://nicklally.com */ import processing.video.*; import krister.Ess.*; AudioChannel[] goodSound = new AudioChannel[5]; // five channels of audio playback AudioChannel[] badSound = new AudioChannel[5]; // five channels of audio playback int countGood = 1; int countBad = 1; int count = 0; int[] previousFrame; int[] previousFrame2; int score = 0; int gameTime = 90; //length of game in seconds int gameTimeStart = 0; //measure starting point of millis() for each round int highScore = 0; ArrayList balls = new ArrayList(); ArrayList ballsBad = new ArrayList(); ArrayList intersections = new ArrayList(); ArrayList scorings = new ArrayList(); int ballsNum = 2; int ballsBadNum = 2; PFont font; // colorSensor coords int backgroundCount = 0; int midiCount = 0; int numPixels; int[] backgroundPixels; int[] backgroundPixels2; Capture video; Capture video2; void setup() { balls.add(new ball()); ballsBad.add(new ballBad()); Ess.start(this); for (int i = 0; i < 5; i++) { goodSound[i] = new AudioChannel("good.wav"); } for (int i = 0; i < 5; i++) { badSound[i] = new AudioChannel("bad.wav"); } noLoop(); //start program paused // Change size to 320 x 240 if too slow at 640 x 480 size(640, 480, P2D); font = loadFont("Helvetica-Bold-20.vlw"); textFont(font); String[] devices = Capture.list(); println(devices); video = new Capture(this, width, height, devices[1], 24); video2 = new Capture(this, width, height, devices[2], 24); numPixels = video.width * video.height; //create arrays to store previous frames previousFrame = new int[numPixels]; previousFrame2 = new int[numPixels]; //initialize balls for (int i = 0; i < ballsNum; i++){ balls.add(new ball()); } for (int i = 0; i < ballsBadNum; i++){ ballsBad.add(new ballBad()); } // Make the pixels[] array available for direct manipulation loadPixels(); } void draw() { if (video.available()) { video.read(); // Read a new video frame video2.read(); // Read a new video frame // Difference between the current frame and the stored background int movementSum = 0; for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame... // Fetch the current color in that location, and also the color // of the background in that spot color currColor = video.pixels[i]; color currColor2 = video2.pixels[i]; color prevColor = previousFrame[i]; color prevColor2 = previousFrame2[i]; //color bkgdColor = backgroundPixels[i]; //color bkgdColor2 = backgroundPixels2[i]; // Extract the red, green, and blue components of the current pixel’s color int currR = (currColor >> 16) & 0xFF; int currG = (currColor >> 8) & 0xFF; int currB = currColor & 0xFF; int currR2 = (currColor2 >> 16) & 0xFF; int currG2 = (currColor2 >> 8) & 0xFF; int currB2 = currColor2 & 0xFF; // Extract the red, green, and blue components of the background pixel’s color int prevR = (prevColor >> 16) & 0xFF; int prevG = (prevColor >> 8) & 0xFF; int prevB = prevColor & 0xFF; int prevR2 = (prevColor2 >> 16) & 0xFF; int prevG2 = (prevColor2 >> 8) & 0xFF; int prevB2 = prevColor2 & 0xFF; // Compute the difference of the red, green, and blue values int diffR = abs(currR - prevR); int diffG = abs(currG - prevG); int diffB = abs(currB - prevB); int diffR2 = abs(currR2 - prevR2); int diffG2 = abs(currG2 - prevG2); int diffB2 = abs(currB2 - prevB2); //ignore the initial frames so differencing doesn't get confused if (count < 5){ diffR = 0; diffG = 0; diffB = 0; diffR2 = 0; diffG2 = 0; diffB2 = 0; } previousFrame[i] = currColor; previousFrame2[i] = currColor2; // Add these differences to the running tally //movementSum += diffR + diffG + diffB; //render difference to grey if(((diffR + diffG + diffB) > 100) || ((diffR2 + diffG2 + diffB2) > 100)){ pixels[i] = color(100); //if both are different, render red if(((diffR + diffG + diffB) > 100) && ((diffR2 + diffG2 + diffB2) > 100)) { pixels[i] = color(255, 0, 0); float redX = i / width; float redY = i % width; intersections.add(new intersection(redX,redY)); //add red coords to intersection arraylist } } else { pixels[i] = color(255); } } count++; updatePixels(); // Notify that the pixels[] array has changed } //display score fill(0,76,147); text("SCORE:", 495, 20); text(score, 580, 20); text("HIGH SCORE:", 200, 20); text(highScore, 340, 20); //display time int sec = int(millis() / 1000.0) - gameTimeStart; sec = gameTime - sec; text (sec, 20, 20); //end game after time is expired if (sec == 0){ //set highscore if beat if (score > highScore){ highScore = score; } fill(255,0,255); textAlign(CENTER); text("GAME OVER!", width/2, height/2); //erase balls noLoop(); } for (int i = 0; i < balls.size(); i++) { ball b = (ball) balls.get(i); b.move(); } for (int i = 0; i < ballsBad.size(); i++) { ballBad bBad = (ballBad) ballsBad.get(i); bBad.move(); } for (int i = 0; i < scorings.size(); i++) { scoring s = (scoring) scorings.get(i); s.move(); //check timers and remove if expired if (millis()/1000 - s.timer > s.duration){ scorings.remove(i); } } //erase intersection arraylist for(int i = 0; i < intersections.size(); i++){ intersections.remove(i); } } class ball { float x,y,r,speed,speedX; ball(){ speed = random(2,5); speedX = random(-2,2); x = random(width); y = -30; r = random(20,40); } void move(){ x += speedX; y += speed; fill(0,0,255); ellipse(x,y,r,r); //redraw offscreen balls if (y > height+100){ x = random(width); y = 0; speed = random(2,5); speedX = random(-2,2); r = random(20,40); } //check for collisions with red pixels for(int i = 0; i < intersections.size(); i++){ intersection isect = (intersection)intersections.get(i); //calculate distance between red and circle float distance = dist(x,y,isect.x,isect.y); //if collision, add to score and erase ball if (distance < r){ score++; goodSound[countGood].play(); countGood++; if (countGood > 4){ countGood = 0; } scorings.add(new scoring(x,y,1));//1 indicates positive score x = random(width); y = 0; speed = random(2,5); speedX = random(-2,2); r = random(20,40); } } } } class ballBad { float x,y,r,speed,speedX; ballBad(){ speed = random(2,5); speedX = random(-2,2); x = random(width); y = -30; r = random(20,40); } void move(){ x += speedX; y += speed; fill(255,0,0); ellipse(x,y,r,r); //redraw offscreen balls if (y > height+100){ x = random(width); y = 0; speed = random(2,5); speedX = random(-2,2); r = random(20,40); } //check for collisions with red pixels for(int i = 0; i < intersections.size(); i++){ intersection isect = (intersection)intersections.get(i); //calculate distance between red and circle float distance = dist(x,y,isect.x,isect.y); //if collision, add to score and erase ball if (distance < r){ score--; badSound[countBad].play(); countBad++; if (countBad > 4){ countBad = 0; } scorings.add(new scoring(x,y,-1));//-1 indicates negative score x = random(width); y = 0; speed = random(2,5); speedX = random(-2,2); r = random(20,40); } } } } class scoring { float x,y,s,duration; float timer = millis()/1000; float fillScore = 100; scoring(float xpos, float ypos, int scoreNum){ x = xpos; y = ypos; s = scoreNum; duration = 1; } void move(){ if (s == 1){ fill(0,255,0,fillScore); fillScore --; text("+1",x,y); //println(countGood); x++; y--; } else if (s == -1){ fill(255,0,0,fillScore); fillScore --; text("-1",x,y); x--; y++; } } } class intersection { float x,y; intersection(float xpos, float ypos){ x = xpos; y = ypos; } } void keyPressed(){ if (key == ' ') { //erase balls for(int i = 0; i < balls.size(); i++){ balls.remove(i); } for(int i = 0; i < ballsBad.size(); i++){ ballsBad.remove(i); } //initialize balls for (int i = 0; i < ballsNum; i++){ balls.add(new ball()); } for (int i = 0; i < ballsBadNum; i++){ ballsBad.add(new ballBad()); } loop(); score = 0; //reset gametime if game has ended gameTimeStart = millis()/1000; } } void stop() { Ess.stop(); // When program stops, stop Ess too super.stop(); }