// Joanne Lee
// Section C
// joannele@andrew.cmu.edu
// Term Project
// Visual Quadrant Map:
// Q1 Q2 Q3
// Q4 Q5 Q6
// Q7 Q8 Q9
// logistics
var game = "inactive"
var fCount = 150;
var playBoardW = 270;
// playing board variables
var boardWeight = 10;
var playBoxW = 270;
var effectCounter = 6;
// white, orange, gray box variables
var boxW = playBoardW / 4;
var boxX = [165.625, 250, 334.375];
var boxY = [240.625, 325, 409.375];
var grayBoxes = [];
var newOrange = false;
var whiteX = 0;
var whiteY = 2;
var orangeX = 2;
var orangeY = 0;
// score keeper
var score = 0;
var bestScore = 0;
// sound variables
var coin;
var boing;
function preload() {
coin = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/coin.wav");
coin.setVolume(0.5);
boing = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/boing.wav");
boing.setVolume(0.5);
}
function setup() {
createCanvas(500,650);
frameRate(100);
}
function draw() {
background(255,211,222);
// "growth" effect seen when white + gray boxes collide
if (effectCounter < 2) { // staggered growth effect
playBoxW = 280;
}
if (effectCounter > 2 & effectCounter < 4) { // staggered growth effect
playBoxW = 290;
}
if (effectCounter > 4 & effectCounter < 6) { // staggered growth effect
playBoxW = 280;
}
if (effectCounter > 6) { // staggered growth effect
playBoxW = 270;
}
effectCounter += 1;
drawPlayingBoard();
drawPlayerBox();
drawGoalBox();
displayScore();
if (game == "inactive") {
displayStarterText();
}
if (game == "active") {
drawGrayBox();
// control speed that new boxes are generated
if (frameCount % fCount == 0 & frameCount != 0) {
generateGrayBox();
}
updateGrayBox();
checkCollision();
}
}
function displayScore() {
fill(255,80); // display current score
textSize(200);
textStyle(BOLD);
textFont('Helvetica');
if (score < 10) {
text(score, width - 120, height - 10);
}
else if (score < 100) { // shift over one spot for 2 digit score
text(score, width - 225, height - 10);
}
else if (score < 999) {
text(score, width - 330, height - 10 );
}
if (score >= bestScore) { // record the best score
bestScore = score
}
fill(255); // display the best score
textSize(20);
textStyle(BOLD);
textFont('Helvetica');
text("High Score " + bestScore, 110, height-160);
}
function displayStarterText() {
fill(40,99);
textSize(20);
textStyle(BOLD);
textFont('Helvetica');
text("Press enter to begin", 155, height/2);
}
function drawPlayingBoard() { // light pink w/ thick white border
fill(255,211,222);
stroke(255);
strokeWeight(boardWeight);
rectMode(CENTER);
rect(width / 2, height / 2, playBoxW, playBoxW);
}
function drawPlayerBox() { // white box, starts in Q7
strokeWeight(0);
fill(255);
rect(boxX[whiteX], boxY[whiteY], boxW, boxW);
}
function drawGoalBox() { // orange box, starts in Q3
fill(255,170,107);
rect(boxX[orangeX], boxY[orangeY], boxW*0.7, boxW*0.7);
}
function randomOrangeXY() { // generate random position for orange box
var randX = int(random(0,3));
var randY = int(random(0,3));
// make sure orange x & y are in same line or column as previous position
while (randX == whiteX || randY == whiteY) {
randX = int(random(0,3));
randY = int(random(0,3));
}
orangeX = randX;
orangeY = randY;
}
function checkBoard() {
// if white box position = orange box, you need a new orange box
if (whiteX == orangeX & whiteY == orangeY) {
coin.play();
newOrange = true; // indicate need for new orange box
score += 1; // increment score
// increase speed at which new boxes spawn, cap at 90 frame count
if (score % 10 == 0 & score != 0 && fCount > 90) {
fCount -= 20;
}
}
// if board needs new orange box, randomly generate
if (newOrange == true) {
randomOrangeXY();
newOrange = false;
}
}
function generateGrayBox() { // will create a box with random attributes
if (int(random(0,2)) == 0) { // create a box going left or right
if (int(random(0,2)) == 0) { // create box going right
createBox(-23.625, boxY[int(random(0,3))], 1, 0);
}
else { // create box going left
createBox(523.625, boxY[int(random(0,3))], -1, 0);
}
}
else { // create a box going up or down
if (int(random(0,2)) == 0) { // create box going down
createBox(boxX[int(random(0,3))], -23.625, 0, 1);
}
else { // create box going up
createBox(boxX[int(random(0,3))], 673.625, 0, -1);
}
}
}
function createBox(tx, ty, dx, dy) { // store as an object in the array
var grayBox = { x: tx, y: ty,
dx: dx, dy: dy,
speed: 2.5, state: 'active'
}
grayBoxes.push(grayBox);
}
function updateGrayBox() { // moves the box along
for (var a = 0; a < grayBoxes.length; a ++) {
grayBoxes[a].x += grayBoxes[a].dx * grayBoxes[a].speed;
grayBoxes[a].y += grayBoxes[a].dy * grayBoxes[a].speed;
}
}
function drawGrayBox() {
for (var b = 0; b < grayBoxes.length; b ++) {
fill(107,105,107);
rect(grayBoxes[b].x, grayBoxes[b].y, boxW*0.7, boxW*0.7);
}
}
function checkGrayBox() {
for (var c = 0; c < grayBoxes.length; c ++) {
// delete box from array once it is off the screen
if (grayBoxes[c].x < -24 || (grayBoxes[c].x > 524) ||
(grayBoxes[c].y < -24) || (grayBoxes[c].y > 674)) {
count += 1;
grayBoxes.splice(c,1);
}
}
}
function checkCollision() {
for (var d = 0; d < grayBoxes.length; d ++) {
if ((grayBoxes[d].x + boxW * 0.35) > (boxX[whiteX] - boxW * 0.5) &
(grayBoxes[d].x - boxW * 0.35) < (boxX[whiteX] + boxW * 0.5) &&
(grayBoxes[d].y - boxW * 0.35) < (boxY[whiteY] + boxW * 0.5) &&
(grayBoxes[d].y + boxW * 0.35) > (boxY[whiteY] - boxW * 0.5)) {
gameReset();
break;
}
}
}
function gameReset() {
boing.play();
score = 0;
grayBoxes = [];
fCount = 150;
effectCounter = 0;
game = "inactive";
}
function keyPressed() {
if (game == "active") {
if (keyCode == UP_ARROW & whiteY > 0) {
whiteY -= 1;
}
if (keyCode == DOWN_ARROW & whiteY < 2) {
whiteY += 1;
}
if (keyCode == LEFT_ARROW & whiteX > 0) {
whiteX -= 1;
}
if (keyCode == RIGHT_ARROW & whiteX < 2) {
whiteX += 1;
}
}
if (game == "inactive" & keyCode == ENTER) {
game = "active"
generateGrayBox();
}
// CHECK BOARD: to see if white box "ate" orange box
checkBoard();
}
The objective of the game is quite simple: collect the orange box by using your arrow keys to move the white box while avoiding the incoming gray boxes!
As the game progresses, you’ll find that the gray boxes will appear quicker, creating more obstacles to dodge. The game was based off of a game I saw a while ago, but was unable to find again on the internet — so the idea is not original, however, the interface is!
Although seemingly simple, there were a lot of technical obstacles I had to overcome with the main one being having to make sure that too many gray boxes did not appear at once. I ran into some bugs along the way, but I believe that my current code is clean and efficient!
Something I also tried to focus on was simple, but meaningful UI. Attention to detail was put in to small things such as a visual (and audio) cue when you mess up or the placement of the score. Hopefully this is a soothing yet addictive game that will get people through finals week! It was fun to create something of my own.