Joanne Lee – Term Project

Term Project

// 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.

Leave a Reply