Skip to content

Instantly share code, notes, and snippets.

@fadookie
Forked from anonymous/snowfight
Created April 26, 2012 06:51
Show Gist options
  • Save fadookie/2496899 to your computer and use it in GitHub Desktop.
Save fadookie/2496899 to your computer and use it in GitHub Desktop.
snowfight.pde
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