Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/*

 INTERACTIVE MEDIA
 "INTERACTIVE TOY"
 MARINA PIMENTEL
 OCT. 05, 2015
 
 Two players; one player uses keyboard arrow keys (left/right) & spacebar to move & shoot respectively,
 the other uses the mouse to manoeuver the block around the screen and dodge the fired shots & laser bars.
 
 */

// VARIABLES ***************************************************************************************************************
// - - - - - others - - - - - - - - - - - - - - - - - - - - - - ->
int screenSize = 500;
color bg = 150; //grey
String[] startMsg = {"QUICK, DODGE THINGS!", "PLAYER 1: use the mouse", "PLAYER 2: use arrow keys & spacebar"}; //appears all game (behind bars)
String[] lColMsg = {"ow", "oh god stop", "it hurts", "dear god why", "pls", "goddamnit", "[muffled sobbing]", "there goes my good eye", "sweet baby jesus", "help"}; //for when square intersects a laser bar (or 8)
String[] shColMsg = {"NICE SHOT", "that square sucks at dodging"}; //when square intersects fired shot(s)
color strColour = 120; //darker grey
// - - - - - player 1 (square) - - - - - - - - - - - - - - - - - >
int sSize = 20;
color sColour = color(255); //white
// - - - - - player 2 (triangles & fired shots) - - - - - - - - ->
boolean tMove = false; //determines whether arrow keys have been pressed & when to draw movement for triangles
float[] tPosX = {0, 100, 50, 500, 500, 470, 500, 400, 450, 0, 0, 30}; //triangles starting X
float[] tPosY = {500, 500, 470, 500, 400, 450, 0, 0, 30, 0, 100, 50}; //triangles starting Y
color tColour = 255; //white
// - - - fired shots - - ->
boolean tFireShots = false; //determines whether spacebar has been pressed & when to draw fired shots 'animation'
boolean shSwitch = false; //determines whether to actually draw fired shots
int shSize = 30;
float[] shPosX = new float[4];
float[] shPosY = new float[4];
color shColour = color(250, 200, 30); //gold
// - - - - - moving lasers - - - - - - - - - - - - - - - - - - - >
int lNum = 9; //number of laser bars on screen at once
int lHeight = 20;
color[] lColour = {color(100, 50, 50), color(50, 100, 100)}; //red & teal
float[] lPosY = new float[lNum];
// - - - laser gaps - - - >
int gHeight = lHeight+2;
float[] gWidth = new float[lNum];
float[] gPosX = new float[lNum];
color gColour = bg; //fake transparency (grey; although screws with the background text, which is unfortunate!)

// SETUP *******************************************************************************************************************
void setup() {
  size(501, 501);
  //first, let's define some array values...
  for (int i=0; i<lNum; i++) {
    lPosY[i]=(screenSize/lNum)*i; //laser bar Y (topmost)
    gPosX[i]=random(0, 460); //gap X (leftmost)
    gWidth[i]=random(40, 100); //gap width
  }
}

// DRAW ********************************************************************************************************************
void draw() {
  background(bg);

  // - - - - - background message - - - - - - - - - - - - - - - - - - - - - - - - - - >
  fill(strColour);
  textSize(20);
  text(startMsg[0], screenSize/2-(textWidth(startMsg[0])/2), (screenSize/2)+10);
  textSize(10);
  text(startMsg[1], (screenSize/2-(textWidth(startMsg[1])/2)-30), (screenSize/2)+30);
  text(startMsg[2], (screenSize/2-(textWidth(startMsg[1])/2)-30), (screenSize/2)+40);

  // - - - - - laser bars - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >
  noStroke();
  lasers(0.5); //initiates laser bar movement loop

  // - - - - - square (player 1; controllable with mouse) - - - - - - - - - - - - - - >
  stroke(1);
  fill(sColour);
  if (mouseX-(sSize/2) < 0) { //if square hits bottom of screen...
    rect(0, mouseY-(sSize/2), sSize, sSize); //...keep it there until mouse moves away;
  } else if (mouseX+(sSize/2) >= 500) { //similarly, if it hits right of screen...
    rect(500-sSize, mouseY-(sSize/2), sSize, sSize); //...same thing;
  } else if (mouseY-(sSize/2) <= 0) { //or, if it hits top of screen;
    rect(mouseX-(sSize/2), 0, sSize, sSize);
  } else if (mouseY+(sSize/2) >= 500) { //...or even left side of screen;
    rect(mouseX-(sSize/2), 500-sSize, sSize, sSize);
  } else { //HOWEVER, if it's within screen bounds...
    detectCollision(mouseY-(sSize/2), mouseY+(sSize/2), mouseX-(sSize/2), mouseX+(sSize/2)); //find out whether square was hit with laser bar or fired shots & proceed in detectCollision()
    rect(mouseX-(sSize/2), mouseY-(sSize/2), sSize, sSize); //draw square in any case
  }

  // - - - - - triangles (player 2; controllable with arrow keys) - - - - - - - - - - >
  fill(tColour);
  triangle(tPosX[0], tPosY[0], tPosX[1], tPosY[1], tPosX[2], tPosY[2]); //bottom triangle
  triangle(tPosX[3], tPosY[3], tPosX[4], tPosY[4], tPosX[5], tPosY[5]); //right triangle
  triangle(tPosX[6], tPosY[6], tPosX[7], tPosY[7], tPosX[8], tPosY[8]); //left triangle
  triangle(tPosX[9], tPosY[9], tPosX[10], tPosY[10], tPosX[11], tPosY[11]); //top triangle
  if (tFireShots) {
    shotsFired(); //trigger firing shot x4 (aka. allows fire to rain down upon thine enemy)
  }

  // - - - - - triangle shots (spacebar) - - - - - - - - - - - - - - - - - - - - - - ->
  fill(shColour);
  noStroke();
  if (shSwitch==true && shPosY[0]>0-shSize) { //if player 2 hits spacebar, shSwitch will enable drawing the fired shots, then update coords (providing a shot isn't already animating):
    for (int i=0; i<4; i++) { //draw shots x4
      rect(shPosX[i], shPosY[i], shSize, shSize);
    }
    shPosY[0]=shPosY[0]-10; //update bottom shot (^)
    shPosX[1]=shPosX[1]-10; //update right shot (<--)
    shPosY[2]=shPosY[2]+10; //update top shot (v)
    shPosX[3]=shPosX[3]+10; //update left shot (-->)
  } else { //...THEN, when the master shot (the bottom one) exceeds the boundaries of the screen...
    shSwitch=false; //...stop animating & reset X & Y coordinates:
    shPosX[0]=tPosX[2]-(shSize/2); //reset bottom shot
    shPosY[0]=tPosY[2]-shSize;
    shPosX[1]=tPosX[5]-shSize; //reset right shot
    shPosY[1]=tPosY[5]-(shSize/2);
    shPosX[2]=tPosX[8]-(shSize/2); //reset top shot
    shPosY[2]=tPosY[8];
    shPosX[3]=tPosX[11]; //reset left shot
    shPosY[3]=tPosY[11]-(shSize/2);
  }
}

// KEYPRESSED (PLAYER 2) ***************************************************************************************************
void keyPressed() {
  if (key==CODED) {
    //tMove=true;
    if (keyCode==LEFT) { //if left arrow key is pressed...
      if (tPosX[0]<=1) { //...prevent bottom triangle exiting screen left (master collision for all triangles)...
      } else {
        tMove=true; //...otherwise, draw normally with updated coords:
        for (int i=0; i<=11; i++) {
          if (i<=2) { //bottom triangle
            tPosX[i]=tPosX[i]-5;
          } else if (i>=3 && i<=5) { //right triangle
            tPosY[i]=tPosY[i]+5;
          } else if (i>=6 && i<=8) { //top triangle
            tPosX[i]=tPosX[i]+5;
          } else if (i>=9) { //left triangle
            tPosY[i]=tPosY[i]-5;
          }
        }
      }
    } else if (keyCode==RIGHT) { //if right arrow key is pressed...
      if (tPosX[1]>=499) { //...prevent bottom triangle exiting screen right (master collision for all triangles)...
      } else {
        tMove=true; //...otherwise, draw normally with updated coords:
        for (int i=0; i<=11; i++) {
          if (i<=2) { //bottom triangle
            tPosX[i]=tPosX[i]+5;
          } else if (i>=3 && i<=5) { //right triangle
            tPosY[i]=tPosY[i]-5;
          } else if (i>=6 && i<=8) { //top triangle
            tPosX[i]=tPosX[i]-5;
          } else if (i>=9) { //left triangle
            tPosY[i]=tPosY[i]+5;
          }
        }
      }
    }
  } else {
    if (key==' ') { //when spacebar is pressed...
      if (shPosY[0]>=0-shSize) {
        tFireShots=true; //...trigger fired shots to be drawn with updated coords:
        shPosX[0]=tPosX[2]-(shSize/2);
      } else {
      }
    }
  }
}

void keyReleased() {
  if (key==' ') { //when player stops holding/pressing spacebar...
    tFireShots=false; //...end fired shots drawing phase
  } else if (key==LEFT || key==RIGHT) { //when player stops pressing LEFT/RIGHT arrows...
    tMove=false; //...end triangle movement drawing phase
  }
}

// FIRE SHOTS (PLAYER 2) ***************************************************************************************************
void shotsFired() {
  if (shSwitch==false) { //if shSwitch is off...
    shSwitch=true; //...turn it on (triggers the shots to draw in void draw() to preserve screen refresh)
  }
}

// LASER BAR MOVEMENTS *****************************************************************************************************
void lasers(float lSpeed) { 
  for (int i=0; i<lNum; i++) { //for every iteration of laser bar...
    if (lPosY[i]<=screenSize-lHeight) { //...if the bottom of the bar has not yet reached the bottom of the screen, move normally
      fill(lColour[int(random(0, 2))]);
      rect(0, lPosY[i], screenSize, lHeight); //laser bar
      fill(gColour);
      rect(gPosX[i], lPosY[i]-1, gWidth[i], gHeight); //fake gap
      lPosY[i]=lPosY[i]+lSpeed;
    } else if (lPosY[i]>screenSize-lHeight && lPosY[i]<=screenSize) { //HOWEVER, if it has, make it re-draw at the top as well
      fill(lColour[int(random(0, 2))]);
      rect(0, 0+lPosY[i]-screenSize, screenSize, lHeight); //laser bar (reappearing at top)
      fill(gColour);
      rect(gPosX[i], 0+lPosY[i]-screenSize-1, gWidth[i], gHeight); //fake gap (reappearing at top)
      fill(lColour[int(random(0, 2))]);
      rect(0, lPosY[i], screenSize, lHeight); //laser bar (disappearing at bottom)
      fill(gColour);
      rect(gPosX[i], lPosY[i]-1, gWidth[i], gHeight); //fake gap (disappearing at bottom)
      lPosY[i]=lPosY[i]+lSpeed;
    } else { //AND THEN, reset that laser's Y (top) so the 'animation' loops once it's completed a cycle
      lPosY[i]=0;
      fill(lColour[int(random(0, 2))]);
      rect(0, lPosY[i], screenSize, lHeight); //laser bar
      fill(gColour);
      rect(gPosX[i], lPosY[i]-1, gWidth[i], gHeight); //fake gap
    }
  }
}

// DETECT COLLISION ********************************************************************************************************
void detectCollision(float mouseTop, float mouseBot, float mouseLeft, float mouseRight) {
  // - - - - - laser - - - - - >
  for (int i=0; i<lNum; i++) { //for each laser bar...
    if (mouseTop <= lPosY[i]+lHeight && mouseBot >= lPosY[i]) { //...if square is within laser constraints (top & bottom)...
      if (mouseLeft >= gPosX[i] && mouseRight <= gPosX[i]+gWidth[i]) { ///...UNLESS there's a 'gap', square is safe...
      } else { //...BUT IF NOT, square collides with laser
        fill(0);
        textSize(10);
        text(lColMsg[i], mouseX-(textWidth(lColMsg[i])/2), mouseY-textAscent()-5);
      }
    }
  }
  // - - - - - shot - - - - - ->
  if (shSwitch) { //checks if collision detection for shots is turned on before proceeding (otherwise square can collide with shot 'placeholders')
    for (int i=0; i<4; i++) { //for each of the 4 shots...
      if (((mouseBot > shPosY[i] && mouseBot < (shPosY[i]+shSize)) || (mouseTop > shPosY[i] && mouseTop < shPosY[i]+shSize)) && ((mouseLeft > shPosX[i] && mouseLeft < (shPosX[i]+shSize)) || (mouseRight > shPosX[i]) && mouseRight < (shPosX[i]+shSize))) { //...check collision with square & proceed with screen message if hit
        background(155, 0, 0);
        fill(255, 0, 0);
        textSize(50);
        text(shColMsg[0], screenSize/2-(textWidth(shColMsg[0])/2), (screenSize/2)+textAscent()/3);
        textSize(20);
        text(shColMsg[1], screenSize/2-(textWidth(shColMsg[1])/2), (screenSize/2)+40);
      }
    }
  }
}