Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
////////////////////////////////////////////////////////////////////////////
//
//  Another One of Those Minimalistic Games
//  An Interactive Toy by Keana Almario
//
//  Inspired by Marty Daniels' Paddle Game (2014 Interactive Toy),
//  I decided to make a minimalistic game so I could get myself to
//  think about mechanics instead of focusing only on the aesthetics.
//  
//  WASD or Arrow Keys to move.
//    
////////////////////////////////////////////////////////////////////////////


//Declare color-related variables
float bgR = 10;
float bgG = 10;
float bgB = 10;
int colorCount = 0;

//Declare square-related variables (player)
float sqX;
float sqY;
float sqSize = 20;
float sqDirX = 0;
float sqDirY = 0;
float sqSpeed = 8;

//Declare wall-related variables
float wallX1;
float wallX2;
float wallYA;
float wallYB;
float wallInitialY;
float wallLengthA1;
float wallLengthA2;
float wallLengthB1;
float wallLengthB2;
float wallWidth = 35;
float wallInitialSpeed = 2.5;
float wallSpeed = wallInitialSpeed;
float wallSpeedChange = 0.2;

// Declare losing line and score-related variables
float lineX;
float lineY;
int score = 0;


////////////////////////////////////////////////////////////////////////////


void setup() {
  // Set screen size
  size(400, 600);

  // Set all shapes to no stroke
  noStroke();

  // Set rect mode to CENTER for convenience
  rectMode(CENTER);

  // Set initial position of square
  sqX = width/2;
  sqY = height/2;

  // Set initial positions of walls
  // Only two sets of walls will be on the screen at any one time (except for the start)
  wallInitialY = 0 - wallWidth;
  wallYA = wallInitialY;
  wallYB = wallYA - (height/2);
  wallX1 = 0;
  wallX2 = width;

  // Set randomly-generated gaps for wall sets
  // Each set of wall will have two walls (left and right)
  // The gaps will appear in random parts of the set but will always be the same size
  wallLengthA1 = random(width/32, width-(width/4)) * 1.8;
  wallLengthA2 = abs(width*1.5 - wallLengthA1);
  wallLengthB1 = random(width/32, width-(width/4)) * 1.8;
  wallLengthB2 = abs(width*1.5 - wallLengthB1);

  // Set position of the losing line
  lineX = width/2;
  lineY = height - (height/60);
}

void draw() {
  // Draw the background color
  background(bgR, bgG, bgB);

  // Move wall sets and squares
  updateWall();
  updateSq();

  // Reposition square so it stays inside screen and outside walls
  collideSqOnWall(wallX1, wallYA, wallLengthA1);
  collideSqOnWall(wallX2, wallYA, wallLengthA2);
  collideSqOnWall(wallX1, wallYB, wallLengthB1);
  collideSqOnWall(wallX2, wallYB, wallLengthB2);
  constrainSqToBounds();

  // Check if the square has passed a wall set, triggering the background color change
  checkIfSqPassedWall(wallYA);
  checkIfSqPassedWall(wallYB);

  // Check if the square has touched the losing line, triggering the YOU LOSE screen
  checkIfSqLost();

  // Check if the wall set has exited the screen, repositioning it above the screen so it enters again
  checkIfWallExited();

  // Draw losing line, score bar, walls, and square
  drawLosingLine();
  drawScore();
  drawWall(wallX1, wallYA, wallLengthA1);
  drawWall(wallX2, wallYA, wallLengthA2);
  drawWall(wallX1, wallYB, wallLengthB1);
  drawWall(wallX2, wallYB, wallLengthB2);
  drawSq();
}


////////////////////////////////////////////////////////////////////////////

// Move walls
void updateWall() {
  wallYA += wallSpeed;
  wallYB += wallSpeed;
}


// Draw walls
void drawWall(float wallX, float wallY, float wallLength) {
  fill(255, 50);
  rect(wallX, wallY, wallLength, wallWidth);
}


// Check if the wall set has exited the screen, repositioning it above the screen so it enters again
void checkIfWallExited() {
  
  if (wallYA - (wallWidth*0.5) > height) {
    wallYA = 0 - wallWidth;
    wallLengthA1 = random(width/32, width-(width/4)) * 2;
    wallLengthA2 = abs(width*1.5 - wallLengthA1);
  }
  
  if (wallYB - (wallWidth*0.5) > height) {
    wallYB = 0 - wallWidth;
    wallLengthB1 = random(width/32, width-(width/4)) * 2;
    wallLengthB2 = abs(width*1.5 - wallLengthB1);
  }
}

//////////////////////////////////////

//Move square
void updateSq() {
  // The new x/y position is a constant speed * a direction
  // To move the square, change direction to -1 (when x/y decreases) or 1 (when x/y increases)
  // To stop the square, change direction to 0
  sqX += sqSpeed * sqDirX;
  sqY += sqSpeed * sqDirY;
}


// Draw square
void drawSq() {
  fill(255);
  rect(sqX, sqY, sqSize, sqSize);
}


// Detemine the walls' collision area and reposition the square outside them
void collideSqOnWall(float wallX, float wallY, float wallLength) {
  
  // Collision of square with top/bottom side of the wall
  if (sqY - (sqSize*0.5) < wallY + (wallWidth*0.5) && sqY + (sqSize*0.5) > wallY - (wallWidth*0.5) && sqX - (sqSize*0.5) > wallX - (wallLength*0.50) && sqX + (sqSize*0.5) < wallX + (wallLength*0.50)) {
    // Stop the square
    sqDirY = 0;
    // Determine new location of square depending on whether it is below or above the wall
    if (sqY > wallY) {
      sqY = wallY + (wallWidth*0.75);
    } else if (sqY < wallY) {
      sqY = wallY - (wallWidth*0.75);
    }
  }
  
  // Collision of square with left/right side of the wall
  if (sqX + (sqSize*0.5) > wallX - (wallLength*0.50) && sqX - (sqSize*0.5) < wallX + (wallLength*0.50) && sqY - (sqSize*0.5) > wallY - (wallWidth*0.5) && sqY + (sqSize*0.5) < wallY + (wallWidth*0.5)) {
    // Stop the square
    sqDirX = 0;
    // Determine new location of square depending on whether it is left or right of the wall
    if (sqX < wallX) {
      sqX = wallX - (wallLength*0.55);
    } else if (sqX > wallX) {
      sqX = wallX + (wallLength*0.55);
    }
  }
}


// Keep square inside screen
void constrainSqToBounds() {
  
  // Square does not go past the top/bottom bounds of screen
  if (sqY - (sqSize*0.5) < 0) {
    sqDirY = 0;
    sqY = 0 + (sqSize*0.5);
  } else if (sqY + (sqSize*0.5) > height) {
    sqDirY = 0;
    sqY = height - (sqSize*0.5);
  }
  
  // Square does not go past the left/right bounds of screen
  if (sqX - (sqSize*0.5) < 0) {
    sqDirX = 0;
    sqX = 0 + (sqSize*0.5);
  } else if (sqX + (sqSize*0.5) > width) {
    sqDirX = 0;
    sqX = width - (sqSize*0.5);
  }
}


// Check if the square has passed a wall set
void checkIfSqPassedWall(float wallY_) {
  if (sqY == wallY_ || (sqY <= wallY_ && sqY >= wallY_ - (wallWidth*0.3))) {
    // Increase wall speed
    wallSpeed += wallSpeedChange;
    
    // Increase score
    score++;
    
    // Trigger the background color change
    colorCount++;
    changeColor();
  }
}


// Check if the square has touched the losing line
void checkIfSqLost() {
  if (sqY + (sqSize*0.5) > lineY) {
    // Trigger YOU LOSE screen
    drawYouLose();
    
    // Reset background color
    bgR = 10;
    bgG = 10;
    bgB = 10;
    colorCount = 0;
    
    // Reset score
    score = 0;
    
    // Reset wall speed
    wallSpeed = wallInitialSpeed;
  }
}


// Draw losing line
void drawLosingLine() {
  fill(0, 50);
  rect(lineX, lineY, width, (height-lineY) * 2);
  
  // Draw the diagonal line pattern in the losing line
  fill(255, 30);
  for (int i = 0; i <= width; i += 50) {
    quad(i, height, i+(width/13), height-(height/30), i+(width/8), height-(height/30), i+(width/20), height);
  }
}


// Draw YOU LOSE screen
void drawYouLose() {
  fill(255, 100);
  
  // Set rect mode to CORNERS for convenience
  rectMode(CORNERS);

  //Y
  rect(35, 110, 45, 140);
  rect(45, 140, 65, 150);
  rect(65, 110, 75, 160);
  rect(45, 160, 65, 170);
  //O
  rect(95, 110, 115, 120);
  rect(95, 160, 115, 170);
  rect(85, 120, 95, 160);
  rect(115, 120, 125, 160);
  //U
  rect(135, 110, 145, 160);
  rect(165, 110, 175, 160);
  rect(145, 160, 165, 170);
  //L
  rect(205, 110, 215, 160);
  rect(205, 160, 235, 170);
  //O
  rect(255, 110, 275, 120);
  rect(255, 160, 275, 170);
  rect(245, 120, 255, 160);
  rect(275, 120, 285, 160);
  //S
  rect(305, 110, 325, 120);
  rect(295, 120, 305, 130);
  rect(305, 130, 315, 140);
  rect(315, 140, 325, 160);
  rect(295, 160, 315, 170);
  //E
  rect(335, 110, 345, 170);
  rect(345, 110, 365, 120);
  rect(345, 130, 355, 140);
  rect(345, 160, 365, 170);
  
  // Set rect mode back to CENTER
  rectMode(CENTER);
}


// Draw score bar
void drawScore() {
  fill(255, 30);
  rect(width/2, height/10, (score*5) + width/40, width/40);
}


// Change background color when square passes a wall set
void changeColor() {
  if (colorCount == 0) {
    bgR = 10;
    bgG = 10;
    bgB = 10;
  }
  if (colorCount > 0 && colorCount <= 5) {
    bgR = 10;
    bgG = 10;
    bgB = random(40, 90);
  }
  if (colorCount > 5 && colorCount <= 10) {
    bgR = 10;
    bgG = random(40, 90);
    bgB = random(40, 90);
  }
  if (colorCount > 10 && colorCount <= 15) {
    bgR = 10;
    bgG = random(40, 90);
    bgB = 10;
  }
  if (colorCount > 15 && colorCount <= 20) {
    bgR = random(40, 90);
    bgG = random(40, 90);
    bgB = 10;
  }
  if (colorCount > 20 && colorCount <= 25) {
    bgR = random(40, 90);
    bgG = 10;
    bgB = 10;
  }
  if (colorCount > 25 && colorCount <= 30) {
    bgR = random(40, 90);
    bgG = 10;
    bgB = random(40, 90);
    
    // Reset color count to start of cycle
    colorCount = 0;
  }
}


// Set controls
void keyPressed() {
  // Get the square moving when WASD/arrow keys are pressed
  if (key == 'w' || key == 'W' || keyCode == UP) {
    sqDirY = -1;
  }
  if (key == 's' || key == 'S' || keyCode == DOWN) {
    sqDirY = 1;
  }
  if (key == 'a' || key == 'A' || keyCode == LEFT) {
    sqDirX = -1;
  }
  if (key == 'd' || key == 'D' || keyCode == RIGHT) {
    sqDirX = 1;
  }
}

void keyReleased() {
  // Stop the square from moving when the key pressed is released
  if (key == 'w' || key == 'W' || keyCode == UP) {
    sqDirY = 0;
  } else if (key == 's' || key == 'S' || keyCode == DOWN) {
    sqDirY = 0;
  } else if (key == 'a' || key == 'A' || keyCode == LEFT) {
    sqDirX = 0;
  } else if (key == 'd' || key == 'D' || keyCode == RIGHT) {
    sqDirX = 0;
  }
}