-
-
Save fadookie/2496899 to your computer and use it in GitHub Desktop.
snowfight.pde
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hypermedia.video.*; // Imports the OpenCV library | |
OpenCV opencv; // Creates a new OpenCV object | |
PImage movementImg; // Creates a new PImage to hold the movement image | |
int caughtSnow; // Creates a variable to hold the total number of popped SF | |
ArrayList SF; // Creates an ArrayList to hold the Flake objects | |
PImage snowPNG; // Creates a PImage that will hold the image of the bubble | |
boolean moveOK; | |
boolean debugDraw = false; //Draw some debugging info | |
//-----------------------------------------SETUP | |
void setup() | |
{ | |
size ( 720, 480 ); // Window size of 720 x 480 | |
frameRate(30); | |
opencv = new OpenCV( this ); // Initialises the OpenCV library | |
opencv.capture( 720, 480 ); // Sets the capture size to 720 x 480 | |
movementImg = new PImage( 720, 480 ); // Initialises the PImage that holds the movement image | |
caughtSnow = 1; | |
SF = new ArrayList(); // Initialises the ArrayList | |
snowPNG = loadImage("snow.png"); // Load the bubble image into memory | |
} | |
//---------------------------------------------DRAW | |
void draw() | |
{ | |
SF.add(new Flake( (int)random( 0, width - 40), -snowPNG.height, snowPNG.width, snowPNG.height)); // Adds a new bubble to the array with a random x position | |
opencv.read(); // Captures a frame from the camera | |
opencv.flip(OpenCV.FLIP_HORIZONTAL); // Flips the image horizontally | |
image( opencv.image(), 0, 0 ); // Draws the camera image to the screen | |
opencv.absDiff(); // Creates a difference image | |
opencv.convert(OpenCV.GRAY); // Converts to greyscale | |
opencv.blur(OpenCV.BLUR, 3); // Blur to remove camera noise | |
opencv.threshold(20); // Thresholds to convert to black and white | |
movementImg = opencv.image(); // Puts the OpenCV buffer into an image object | |
if (debugDraw) { | |
image(movementImg, 0, 0); //Draw what the computer is seeing for debug purposes if debugDraw is active | |
} | |
for ( int i = 0; i < SF.size(); i++ ) { // For every bubble in the SF array | |
Flake _flake = (Flake) SF.get(i); // Copies the current bubble into a temporary object | |
if (_flake.update() == true) { // If the bubble's update function returns true | |
SF.remove(i); // then remove the bubble from the array | |
_flake = null; // and make the temporary bubble object null | |
i--; // since we've removed a bubble from the array, we need to subtract 1 from i, or we'll skip the next bubble | |
// if( _flake. | |
} | |
else { // If the bubble's update function doesn't return '1' | |
_flake.drawFlake(); // Draws the flake | |
SF.set(i, _flake); // Copys the updated temporary bubble object back into the array | |
_flake = null; // Makes the temporary bubble object null. | |
} | |
} | |
opencv.remember(OpenCV.SOURCE, OpenCV.FLIP_HORIZONTAL); // Remembers the camera image so we can generate a difference image next frame. Since we've | |
fill(0); // flipped the image earlier, we need to flip it here too. | |
} | |
void keyPressed() { | |
if (key == 'd') { | |
debugDraw = !debugDraw; //Toggle debug drawing if d key is pressed | |
} | |
} | |
//----------------------------------------------CLASS | |
class Flake | |
{ | |
int flakeWidth, flakeHeight; // Some variables to hold information about the bubble | |
float flakeX, flakeY, velocityX, velocityY, accelX, accelY; | |
Flake ( int bX, int bY, int bW, int bH ) // The class constructor- sets the values when a new bubble object is made | |
{ | |
flakeX = bX; | |
flakeY = bY; | |
flakeWidth = bW; | |
flakeHeight = bH; | |
accelY = -10; | |
} | |
boolean update() // The Flake update function | |
{ | |
int movementAmount; // Create and set a variable to hold the amount of white pixels detected in the area where the bubble is | |
movementAmount = 0; | |
boolean destroyFlake = false; | |
for ( int y = floor(flakeY); y < (flakeY + (flakeHeight-1)); y++ ) { // For loop that cycles through all of the pixels in the area the bubble occupies. We're using decimals to store position now so we have to round to nearest integer using floor(). | |
for ( int x = floor(flakeX); x < (flakeX + (flakeWidth-1)); x++ ) { | |
if ( x < width && x > 0 && y < height && y > 0 ) { // If the current pixel is within the screen bondaries | |
if (brightness(movementImg.pixels[x + (y * width)]) > 127) // and if the brightness is above 127 (in this case, if it is white) | |
{ | |
movementAmount++; // Add 1 to the movementAmount variable. | |
} | |
} | |
} | |
} | |
if (movementAmount > 5) // If more than 5 pixels of movement are detected in the bubble area | |
{ | |
accelY = movementAmount * 0.001; // Toss the flake higher based on how much movement was detected near it! We only need 0.1% of the original magnitude. | |
//I don't really know which way to throw it horizontally, so let's just throw it towards the other side of the screen based on its current position. | |
float distanceFromCenterX = flakeX - (width / 2); | |
accelX = distanceFromCenterX / (width / 3); //Scale the movement down so it's not shooting around too fast | |
//caughtSnow++; // Add 1 to the variable that holds the number of popped SFSF | |
//destroyFlake = true; // Return true so that the bubble object is destroyed | |
} | |
else { // If less than 5 pixels of movement are detected, | |
accelY = -1; // decrease the y acceleration of the bubble so that it falls down | |
if (flakeY > height) // If the bubble has dropped off of the bottom of the screen | |
{ | |
destroyFlake = true; | |
} // Return '1' so that the bubble object is destroyed | |
} | |
//Apply acceleration to velocity | |
velocityX += accelX; | |
velocityY += accelY; | |
//Constrain falling speed to -10 units per cycle so it doesn't fall too fast | |
velocityY = constrain(velocityY, -10, 99999999); | |
//Constrain horizontal speed to +/-10 units per cycle so it doesn't move too fast | |
velocityX = constrain(velocityX, -10, 10); | |
//Apply velocity to position to move the flake | |
flakeX += velocityX; | |
flakeY += -velocityY; //Since 0,0 is the upper left hand corner of the screen, we'll invert the velocity here to make it easier to think about it "falling" when we set the velocityY above. We're actually adding to its Y value, not subtracting from it. | |
return destroyFlake; // Returns whether or not to destroy the flake | |
} | |
void drawFlake() { | |
println("drawFlake " + flakeX + ", " + flakeY); | |
image(snowPNG, flakeX, flakeY); // Draws the bubble to the screen | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment