Aquarium

From Robert-Depot
Jump to: navigation, search

Title

Super Mario Slaughter

Motivation

This piece was motivated by my interest in video games and idea that art doesn't need to be serious all the time (because you know, "art" is serious business). This piece is essentially a role reversal of the classic mario video game franchise. Here, the user assumes the role of bowser and indulges in a nonstop slaughter of his mortal enemy.

Paradigm thing or whatever

Instead of using a traditional video game controller, the user swings his/her arms to kill the torrential downpour of marios. 100 mario kills equal 1 peach kill. I wanted to make something with a more intuitive interface (reflective of dreams?) ionno. hah.

Technical Description

This piece utilizes OpenCV and processing to create a non-controller based user interface to immerse the user in a video game dreamscape (in respect to bowser). I created some graphic elements in illustrator while editing existing nintendo sprites for use in the game.

Visualization

screenshot

Mario.png

intended balloon that was supposed to appear under the users face

Balloon.png

bowser hat mock (for a more immersive experience)

Hat.png

Game code

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 poppedBubbles; // Creates a variable to hold the total number of popped bubbles ArrayList bubbles; // Creates an ArrayList to hold the Bubble objects PImage mariodead; // Creates a PImage that will hold the image of the bubble PImage mario; PImage balloon; PImage peachcount; PImage castle; PFont font; // Creates a new font object int p; PImage dude1; PImage dude2; int c1 = 0; int c2 = 600; int h1 = 395; int h2 = 395;


import ddf.minim.*; //sound stuff

AudioPlayer player; Minim minim; AudioSample pain; AudioSample peach;

//------------------------------------------------------------------------------------------------------------------------------ void setup() {

 size ( 635, 480,P2D );                      //  Window size of 640 x 480
 minim = new Minim(this);               // sound stuff
 opencv = new OpenCV( this );            //  Initialises the OpenCV library
 opencv.capture( width, height );             //  Sets the capture size to 640 x 480
 movementImg = new PImage( 635, 480 );   //  Initialises the PImage that holds the movement image
 poppedBubbles = 0;   

p = 0;

 bubbles = new ArrayList();              //  Initialises the ArrayList
 mario= loadImage("mario counter.png");
 castle= loadImage("castle.png");
 peachcount= loadImage("peachcount.png");
 dude1 = loadImage("dude1.png");
 dude2 = loadImage("dude2.png");
 balloon=loadImage("balloon.png");
 mariodead = loadImage("mariodead.png");    //  Load the bubble image into memory
 font = loadFont("ComicSansMS-Bold-48.vlw");        //  Load the font file into memory
 textFont(font, 32);     
 opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT );

player = minim.loadFile("Bowsers_Castle.mp3", 2048); player.play();

pain = minim.loadSample("mario_pain.mp3", 2048);
peach = minim.loadSample("peach.mp3", 2048);

} //------------------------------------------------------------------------------------------------------------------------------ void draw() {

 bubbles.add(new Bubble( (int)random( 0, width - 40), -mariodead.height, mariodead.width, mariodead.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


 Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 100, 100 ); // balloon stuff
noFill();
noStroke();
   for( int i=0; i<faces.length; i++ ) {
       rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height );
       image (balloon, faces[i].x, faces[i].y+(faces[i].height), faces[i].width, faces[i].height);
   } 
   
   
 for ( int i = 0; i < bubbles.size(); i++ ){    //  For every bubble in the bubbles array
   Bubble _bubble = (Bubble) bubbles.get(i);    //  Copies the current bubble into a temporary object
   
   if(_bubble.update() == 1){                  //  If the bubble's update function returns '1'
     bubbles.remove(i);                        //  then remove the bubble from the array
     _bubble = 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
    pain.trigger();
   
 }else{                                        //  If the bubble's update function doesn't return '1'
     bubbles.set(i, _bubble);                  //  Copys the updated temporary bubble object back into the array
     _bubble = 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
                                                            //  flipped the image earlier, we need to flip it here too.
 image(mario, 10, 5);
 text(":" + poppedBubbles, 160, 70);          //  Displays some text showing how many bubbles have been popped
 
 image(peachcount, 480, 20);
 text(p + ":", 480, 70);
 
  if (c1 < 630) {
    c1++;
  }
  else {
    c1 = 0;
    h1 = 395;
  }
  if (c2 > 0) {
    c2--;
  }
  else {
    c2 = 660;
    h2 = 395;
  }
  //drawing the clouds on the screen with moving variables
  image(dude2, c1, h1);
  image(dude1, c2, h2);
  image(castle, 0, 420); 
 

 

} //------------------------------------------------------------------------------------------------------------------------------ class Bubble {

 int bubbleX, bubbleY, bubbleWidth, bubbleHeight;    //  Some variables to hold information about the bubble
 
 Bubble ( int bX, int bY, int bW, int bH )           //  The class constructor- sets the values when a new bubble object is made
 {
   bubbleX = bX;
   bubbleY = bY;
   bubbleWidth = bW;
   bubbleHeight = bH;
 }
 
 int update()      //   The Bubble 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;
   
   for( int y = bubbleY; y < (bubbleY + (bubbleHeight-1)); y++ ){    //  For loop that cycles through all of the pixels in the area the bubble occupies
     for( int x = bubbleX; x < (bubbleX + (bubbleWidth-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
   {
     poppedBubbles++;                    //  Add 1 to the variable that holds the number of popped bubbles
     if (poppedBubbles > 100)
     {
       poppedBubbles = 0;
       peach.trigger();
       p++;
      
   }
     return 1;                           //  Return 1 so that the bubble object is destroyed
  
  }else{                                 //  If less than 5 pixels of movement are detected,
     bubbleY += 10;                      //  increase the y position of the bubble so that it falls down
     
     if (bubbleY > height)               //  If the bubble has dropped off of the bottom of the screen
     {  return 1; }                      //  Return '1' so that the bubble object is destroyed
     
     image(mariodead, bubbleX, bubbleY);    //  Draws the bubble to the screen
     return 0;                              //  Returns '0' so that the bubble isn't destroyed
   }
 }
 

}

void stop() {

 // always close Minim audio classes when you are done with them
 player.close();
 opencv.stop();
 minim.stop();
 
 super.stop();

}


balloon code

import hypermedia.video.*;

OpenCV opencv;

PImage balloon;

void setup() {

   size( 640, 480 );
   balloon=loadImage("balloon.png");

   opencv = new OpenCV( this );
   opencv.capture( width, height );                   // open video stream
   opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT );  // load detection description, here-> front face detection : "haarcascade_frontalface_alt.xml"

}




void draw() {

   opencv.read();
   Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 40, 40 );

   image( opencv.image(), 0, 0 );

   // draw face area(s)
   noFill();
   noStroke();
   for( int i=0; i<faces.length; i++ ) {
       rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height );
       image (balloon, faces[i].x, faces[i].y+(faces[i].height), faces[i].width, faces[i].height);
   }

}