Final Project – Shan Wang – “Slime’s Christmas”

slime's christmas

screenshot from my game

sketch
For the final project, I mainly followed my initial design of the game similar to doodle jump, but with different features and user interface.

var platforms = [];
var allSplashes = [];
var newSplash;
var mode = "START";

var bgColor1;
var bgColor2;

var dropSpeed = 1;
const PF_THINKNESS = 7;
const GRAVITY = 1.5;
const FALLING_INTERV = 50;

var character;
var topPlatform;
var charCurrentPF;

var fallDistance = 0;
var initJump = true;

var aX;
var aY;
var xFactor = 0.3;
var yFactor = 0.15;
var timeFactor = 10;
var distance;
var numberHitted = 0;
var totalScore = 0;

//sound variables
var bgMusic;
var bellSound;

//graphic elements
var snowflakeLinks = [
    "http://imgur.com/2jZMsr7",
    "http://imgur.com/vKvkHSJ",
    "http://imgur.com/X3pNOx0"
]

var frameFilenames = [];

var snowflakes = [];
var snowflake0;
var snowflake1;
var snowGraphs = [];
var allSnowflakesObjects = [];

var wRuffles = [];

var scaleX;
var scaleY;
var snowPosX;
var snowPosY;



function preload() {
    //load sounds
    bgMusic = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/bgMusic.wav");
    bellSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/bellSound.wav");

    //load graphs for snowfaleks
    for (var i = 0; i < snowflakeLinks.length; i++){
        var snowLink = loadImage(snowflakeLinks[i]);
        snowGraphs.push(snowLink);
    }

    var slime = "frames/slime.gif";
    gifSlime = loadGif(slime);


}


function gradient(x,y,wid,hei,c1,c2){
    noFill();
    for (var i = y; i<y+hei; i++){
        var inter = map(i,y,y+hei,0,1);
        var col = lerpColor(c1,c2,inter);
        stroke(col);
        line(x,i,x+wid,i);
    }
}


function makeWaterRuffle(gx, gy, gr, color, alpha){
    var ruffle = {x: gx, y:gy, r:gr, c:color,
                  a: alpha, draw: drawRuffle}
    return ruffle;
}

function drawRuffle(){
    if (this.a >= 0){
        noStroke();
        fill(this.c, this.c, this.c, this.a);
        ellipse(this.x, this.y, this.r, this.r);
    }
}


function makeCharac(cx, cy, color, speedX, speedY){
    var character = {x: cx, y: cy, col: color, vx: speedX, vy: speedY,
                     g: GRAVITY, draw: drawCharac};
    return character;
}

function drawCharac(){
    fill(this.col);
    image(gifSlime, this.x, this.y);
    //ellipse(this.x, this.y, this.r, this.r);
    // idx = frameCount%3;
    // img = frames[idx];
}

function makePlatform(px, py, pw, pc, pt, type) {
    var platform = {x: px, y:py,
                    wid:pw, color:pc,
                    hei: pt, tp: type,
                    draw: drawPlatform};
    return platform;
}

function drawPlatform(){
    fill(this.color);
    noStroke();
    rect(this.x, this.y, this.wid, this.hei);
}

function isTooClose(y){
    for (var i=0; i<platforms.length; i++){
        if (Math.abs(platforms[i].y - y)<20 ){
            return true;
        }
    }
    return false;
}

// check for collision
function hitThePlatform(platform){
    if (collideRectRect(platform.x, platform.y, platform.wid, platform.hei,
        character.x+5, character.y+5, gifSlime.width-5, gifSlime.height-5)){
            return true;
        }
    return false;
}


function makeSplashes(sx, sy, number, bRadius,indiviRadius, initColor, alpha){
    var splash = {x: sx, y:sy, num: number,bigR: bRadius, r: indiviRadius,
                    color: initColor, a: alpha, draw: drawSplashes};
    return splash;
}

function drawSplashes(){
    push();
    translate(this.x, this.y);
    fill(this.color, this.color, this.color, this.a);
    for (var i = 0; i<this.num+1; i++){
        ellipse(0,-this.bigR, this.r, this.r);
        rotate(360/this.num);
    }
    pop();
}

function makeSnowflakes(image, sx, sy, scaleX, scaleY){
    var snowflake = {img: image, x: sx, y: sy, sX:scaleX, sY: scaleY,
                     draw: drawSnowflakes};
    return snowflake;
}

function drawSnowflakes(){
    image(this.img,this.x, this.y,this.img.width*this.sX,this.img.height*this.sY);
}

function setup() {
    //frameRate(50);
    //loop through background music
    bgColor1 = color(190,0,16);
    bgColor2 = color(83,0,0);
    bgMusic.loop();
    createCanvas(600, 800);
    //make water ruffle patter
    for (var i = 0; i < 8; i++){
        var ranX = random(width);
        var ranY = random(height);
        var rndRuffle = makeWaterRuffle(ranX, ranY, random(30,50),random(220,255), random(50, 150));
        wRuffles.push(rndRuffle);
    }

    //make 8 snowflakes with random selection for initial condition
    for (var i = 0; i < 15; i++){
        var rndSnowflake = random(snowGraphs);
        snowflakes.push(rndSnowflake);
    }

    //render snowflakes; make them into objects;
    for (var i = 0; i < snowflakes.length; i++){
        snowflakes[i].loadPixels();
        snowPosX = random(10, width - 10);
        snowPosY = random(10, height - 10);
        scaleX = random(0.1, 0.4);
        scaleY = scaleX;
        var newSnow = makeSnowflakes(snowflakes[i], snowPosX, snowPosY, scaleX, scaleY);
        allSnowflakesObjects.push(newSnow);
    }

    // make platforms
    var counter = 0;
    //make 8 platforms that do not collide with each other
    while (counter < 8){
        var ranPosX, ranPosY, ranWidth;
        do {
            ranPosX = random(80, width-80);
            ranPosY = random(0, height/2-40);
            ranWidth = random(20, 60);
        } while (isTooClose(ranPosY));
        var newPF = makePlatform(ranPosX, ranPosY,ranWidth, 255,PF_THINKNESS, counter);
        var newShadow = makePlatform(ranPosX + 10, ranPosX + 10, ranWidth, 255,PF_THINKNESS, counter);
        platforms.push(newPF);
        //shadows.push(newShadow);
        counter += 1;
    }
    character = makeCharac(width/2, height - gifSlime.height, 155, 0,0);
}



function draw() {
    if (mode == "START"){
        textAlign("CENTER");
        textSize(23);
        textFont("Andale Mono");
        text("Slime's Christmas", width/2-30, height/4);
        line(width/2, height/2, width/2 + 100, height/2);
        textSize(15);
        text("Start Now!", width/2, height/2);
    }

    else if (mode == "GAME" || mode == "christmasInit"){
        gradient(0,0,width,height,bgColor1,bgColor2);
        //image(gifBird, -150,0, gifBird.width*0.9, gifBird.height);
        for (var i = 0; i < wRuffles.length; i++){
            wRuffles[i].r += 1;
            wRuffles[i].a -= 1;
            if (wRuffles[i].a < 0){
                wRuffles.splice(i,1);
            }
        }
        if (wRuffles.length < 10){
            var ranX = random(width);
            var ranY = random(height);
            var rndRuffle = makeWaterRuffle(ranX, ranY, random(30,50),random(220,255), random(50, 150));
            wRuffles.push(rndRuffle);
        }
        for (var i = 0; i < wRuffles.length; i++){
            wRuffles[i].draw();
        }

        for (var i = 0; i < allSplashes.length; i++){
            allSplashes[i].bigR += 3;
            allSplashes[i].a -= 5;
            allSplashes[i].draw();
        }

        for (var i = 0; i < allSnowflakesObjects.length; i++){
            allSnowflakesObjects[i].y += random(dropSpeed*2, dropSpeed*2.5);
            allSnowflakesObjects[i].draw();
            if (allSnowflakesObjects[i].y > height){
                allSnowflakesObjects.splice(i,1);
            }
            if (character.y < height/2){
                allSnowflakesObjects[i].y += 1;
            }
        }

        // set limit of speed on y direction for the character
        fallDistance += dropSpeed;
        if (character.vy > 30){
            character.vy = 30;
        } else if (character.vy < -30){
            character.vy = -30;
        }

        // move platforms & remove those that fall out of canvas
        for (var i = 0; i < platforms.length; i++) {
            platforms[i].y += dropSpeed;
            platforms[i].draw();
            if (platforms[i].y > height){
                platforms.splice(i,1);
                }
        }

        // add new platforms when the old ones drop FALLING_INTERV pixels;
        if (fallDistance % FALLING_INTERV == 0){
            addNewPlatforms();
        }
        // add new snowflakes as needed
        if (allSnowflakesObjects.length < 15){
            addNewSnowFlakes();
        }

        // after first jump, control the velocity on both x and y direction with GRAVITY
        // to simulate the jumping and falling condition
        if (initJump == false){
            distance = mouseX - character.x;
            aY = GRAVITY;
            character.vy += aY*yFactor;
            character.x += distance/timeFactor;
            character.y += character.vy;
        }

        // check if the player hit the platform; keeping track of scores
        if (platforms.length != 0){
            for (var i = 0; i < platforms.length; i++){
                if (hitThePlatform(platforms[i])){
                    numberHitted += 1;
                    totalScore += numberHitted*10;
                    bellSound.play(0,1,1);
                    character.vy = -8;
                    // make splashes when the player hits the platform
                    newSplash = makeSplashes(platforms[i].x + platforms[i].wid/2,
                        platforms[i].y + platforms[i].hei, 10, 50, 6, 255, 100);
                    allSplashes.push(newSplash);
                    //remove platforms that have been hit by players
                    platforms.splice(i,1);
                }
            }
        }
        // adjust the positions of the platforms when the player jumps
        // higher than half of the canvas
        for (var i = 0; i < platforms.length; i++){
            if (character.y < height/2){
                platforms[i].y +=1;
            }
        }

        // bounce the player back to the canvas if the player goes off the side
        if (character.x > width & 0 < character.y < height){
            character.x = character.r;
        } else if(character.x < 0 & 0 < character.y < height){
            character.x = width - character.r;
        } else if (character.y > height){
            mode = "GAMEOVER"
            bgMusic.stop();
        }
        character.draw();

    }
    else if (mode == "GAMEOVER"){
        gradient(0,0,width,height,bgColor1,bgColor2);
        fill(255);
        textSize (30);
        textAlign(CENTER);
        textFont("Andale Mono");
        text("GAME OVER!", width/2, height/2);
        textSize (15);
        text("The Steps You Jumped: " + numberHitted, width/2, height*2/3);
        text ("Total Score: " + totalScore, width/2, height*3/4);
        textSize (10);
        text("Press R to restart the game", width/2, height*5/6);
    }
}

function addNewPlatforms(){
    var newX = random(40, width-40);
    var ranWid = random(40, 65);
    var newPlatForm = makePlatform(newX, 0, ranWid, 255, PF_THINKNESS);
    platforms.push(newPlatForm);
}


function addNewSnowFlakes(){
    var addedSnow = random(snowflakes);
    addedSnow.loadPixels();
    snowPosX = random(10, width - 10);
    scaleX = random(0.1, 0.4);
    scaleY = scaleX;
    var newSnow = makeSnowflakes(addedSnow, snowPosX, 0, scaleX, scaleY);
    allSnowflakesObjects.push(newSnow);
}

function mouseClicked(){
    if (mode == "START"){
        if (collidePointRect(mouseX, mouseY, width/2, height/2-10, 80, 30)){
            mode = "christmasInit";
        }
    }
    else if (mode == "christmasInit"){
        character.vy = -8;
        if (initJump == true){
            initJump = false;
            mode = "GAME";
        }
    }
}

function keyTyped(){
    // reset the game to the initial status
    if (key == "r"|| key == "R"){
        mode = "christmasInit";
        platforms = [];
        allSplashes = [];
        snowflakes = [];
        allSnowflakesObjects = [];
        wRuffles = [];
        numberHitted = 0;
        totalScore = 0;
        setup();
        initJump = true;
    }
}

Different from the existing game, the platforms in my “Slime’s Christmas” will disappear if hit by the character. And the “jumping” of the slime, which follows the mouse, is simulated with gravity to give a sense of physical reality.

With what we learned in object oriented programming, I also created effect of random water ruffle and splashes that are generated at the position of the hit platform.

 

 

All music downloaded from freesound.org

The slime gif credited to google image.

 

Leave a Reply