Xu Xu & Xiaoyu Kang – Final Project

sketch

// Xiaoyu Kang & Xu (Claire) Xu
// Section B
// xkang@andrew.cmu.edu & xux1@andrew.cmu.edu
// Final Project
var hatShapeX = 130; //BY BOTH XIAOYU AND XU
var hatShapeY = 128;
var heartShapeX = 205;
var heartShapeY = 128;
var moneyShapeX = 270;
var moneyShapeY = 140;
var textboxShapeX = 330;
var textboxShapeY = 128;
var backgroundColor = 0;
var gameStart = false;
var badEnd = false;
var goodEnd = false;
var img1 = [];
var imageCount = 0;
var testLinks = ["https://i.imgur.com/VWoGtbO.jpg", 
             "https://i.imgur.com/OpLGpha.jpg",
             "https://i.imgur.com/1Ik4bPx.jpg",
             "https://i.imgur.com/vM6ZK9c.jpg",
             "https://i.imgur.com/8J6Gxdo.jpg",
             "https://i.imgur.com/yk3tV27.jpg",
             "https://i.imgur.com/FH9qhm4.jpg",
             "https://i.imgur.com/E7a5TDu.jpg",
             "https://i.imgur.com/9vRGrKE.jpg",
             "https://i.imgur.com/C4XhQaI.jpg",
             "https://i.imgur.com/NgIAvpS.jpg",
             "https://i.imgur.com/QRXsh9S.jpg",
             "https://i.imgur.com/04EkVKf.jpg",
             "https://i.imgur.com/0dOYwZv.jpg",
             "https://i.imgur.com/xc56D6n.jpg",
             "https://i.imgur.com/0sk94O3.jpg"];
var questionCount = 0;
let testQuestions = ["I can't code for life,", " but do you want to collaborate on this 15104 project?",
                  "Did you hear about the history exam tomorrow?", "I can’t believe it’s on EVERYTHING!",
                  "I heard Vivian got a 104/100", " on the recent physics test!",
                  "I really need to get some sleep,", "will you sign me in for lecture today?",
                  "There’s a frat party tonight,", "do you want to go and hang out?",
                  "OMG I heard there’s a new pho place downtown,", "are you interested??",
                  "There’s a library part time job on Handshake", "let’s apply together!",
                  "Let’s play","League of Legends tonight!",
                  "<Introduction to Javascript> is a required textbook,", "please get it by next class.",
                  "Re: Please see the HW attached,", "submit all to autolab by tonight at midnight.",
                  "I noticed that you have not paid attention in class.", "Is there something wrong?",
                  "Class, this project", "will be due in a week’s time.",
                  "Re: Would you like to be a generous supporter", "of the CMU community by becoming a donor?",
                  "The total amount of your food will be $15.76.", "Paid in card or cash?",
                  "New: Pittsburgh popcorn & smokey barbeque", "flavored mac and cheese",
                  "It’s 2am in the mornin’,","why are y’all still workin’?"]

var imageposX = 115;
var imageposY = 80;
var questionposY = 380;
var answerCount = 0;
let answerX = ["Um… Sure?",
               "What exam?",
               "Ha, I can do better",
               "Sure, go sleep",
               "Sure, I’ll go!",
               "YES LET’S GO",
               "Sure I’ll join",
               "I'll grab my laptop",
               "I’ll buy it",
               "Grinds through HW",
               "It won’t happen again",
               "Complete the task",
               "Fine I’ll donate",
               "Takes out debit card",
               "Gives it a try",
               "We have a deadline"];
let answerY = ["I prefer someone better",
               "Ya I studied all night",
               "She must’ve worked hard",
               "I’m also not going",
               "Nah, I’ll pass",
               "No I’m broke",
               "I’m too lazy",
               "My heart is in the work",
               "I’ll find a fake one",
               "Ignores this email",
               "Your class is boring",
               "Request for extension",
               "I’m not generous",
               "Gets something cheaper",
               "Gets something normal",
               "Cries hysterically"];
var answerposX = 90;
var answerposY = 430;
var timeTracker = 0;
var choices = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var choices_A = [];
var academicsHP = 50;
var sanityHP = 50;
var financeHP = 50;
var socialHP = 50;
var HPposX = 35;
var HPposY = 40;
var logoPosX = 15;
var logoPosY = 30;
var subtract = true;
var monthCount = 0;
var star = [];
var cloud = [];
var crow = [];

function preload(){ //BY XU
    for (var i = 0; i < testLinks.length; i++){
        img1[i] = loadImage(testLinks[i]);
    }
}
function setup(){ //BY XIAOYU
    createCanvas(480,480);
    frameRate(10);
    //setup stars that will display at night
    for (var i = 0; i < 50; i ++) {
        var starX = random(width);
        var starY = random (0, height/2);
        star[i] = makeStar(starX, starY);
    }
    //setup clouds that will display at morning
    for (var i = 0; i < 10; i ++) {
        var cloudX = random(width);
        var cloudY = random (0, height/2);
        cloud[i] = makeCloud(cloudX, cloudY);
    }
    //setup crows that will display at afternoon
    for (var i = 0; i < 20; i ++) {
        var crowX = random(width);
        var crowY = random (0, height/2);
        crow[i] = makeCrow(crowX, crowY);
    }
}
function draw(){ //BY XU
    //starting page text
    background(0);
    fill("yellow");
    textSize(70);
    textFont('Courier');
    textAlign(CENTER);
    text('REIGNS', width/2, height/2);
    fill("white");
    textSize(20);
    text('- CMU EDITION -', width/2, height/2 + 50);
    textSize(15);
    text('Press Mouse To Start', width/2, height - 70); 
    //starting page logo
    fill("yellow");
    rectMode(CENTER);
    rect(width/2, 130, 250, 60);
    //academics logo
    noStroke();
    fill(0);
    beginShape();
    vertex(hatShapeX, hatShapeY);
    vertex(hatShapeX + 20, hatShapeY - 5);
    vertex(hatShapeX + 40, hatShapeY);
    vertex(hatShapeX + 20, hatShapeY + 5);
    vertex(hatShapeX, hatShapeY);
    endShape();
    rectMode(CORNER);
    rect(hatShapeX, hatShapeY, 1, 10);
    rect(hatShapeX + 10, hatShapeY, 20, 10);
    //sanity logo
    circle(heartShapeX, heartShapeY, 15);
    circle(heartShapeX + 10, heartShapeY, 15);
    triangle(heartShapeX - 8, heartShapeY, heartShapeX + 18, heartShapeY, heartShapeX + 6, heartShapeY + 15);
    //finance logo
    textSize(33);
    text('S', moneyShapeX, moneyShapeY);
    rect(moneyShapeX - 1.5, moneyShapeY - 22, 3, 25);
    //social life logo
    ellipse(textboxShapeX, textboxShapeY, 30, 20);
    triangle(textboxShapeX, textboxShapeY, textboxShapeX + 10, textboxShapeY, textboxShapeX + 10, textboxShapeY + 15);
    if(gameStart){ 
        backgroundChange();
        fill(backgroundColor);
        rectMode(CENTER);
        rect(width/2, height/2, 480, 480); 
        //display clouds when background is light gray
        if (timeTracker == 0) {
            displayCloud();
        }
        //display crows when background is dark gray
        if (timeTracker == 1) {
            displayCrow();
            addCrow();
            removeCrow();
        }
        //display stars when background is black
        if (timeTracker == 2) {
            displayStars();
        }        
        gameInterface();
    }
    //check if the game has ended
    checkStatus();
    //bad end
    if (badEnd){
        gameStart = false;
        background(0);
        fill("yellow");
        textSize(70);
        textFont('Courier');
        textAlign(CENTER);
        text('GAME OVER', width/2, height/2);
        fill("white");
        textSize(20);
        text('- SADLY YOU DIDNT GRADUATE -', width/2, height/2 + 50);
        textSize(15);
        text('Refresh Page to Start Over', width/2, height - 70); 
    }
    //goodEnd
    if (goodEnd){
        gameStart = false;
        background(0);
        fill("yellow");
        textSize(50);
        textFont('Courier');
        textAlign(CENTER);
        text('CONGRATULATIONS', width/2, height/2);
        fill("white");
        textSize(20);
        text('- YOU SUCCESFULLY GRADUATED CMU -', width/2, height/2 + 50);
        textSize(15);
        text('Refresh Page to Play Again', width/2, height - 70); 
    }
}
function mouseClicked(){ //BY XU
    gameStart = true;
}
function gameInterface(){ //BY XU
    //frame
    fill("yellow");
    rectMode(CENTER);
    rect(width/2, height/2 - 35, 280, 280);
    //implement images
    putImage();
    //implement question
    putQuestion();
    //implement answers
    putAnswers();
    putDate();
    hpTracker();

}
function putImage(){ //BY XIAOYU
    image(img1[imageCount], imageposX, imageposY);
}
function putQuestion(){ //BY XIAOYU
    fill("white");
    textFont('Courier');
    textAlign(CENTER);
    textSize(12.5);
    text(testQuestions[questionCount], width/2, questionposY);
    text(testQuestions[questionCount + 1], width/2, questionposY + 15);
}
function putAnswers(){ //BY XIAOYU
    //left side
    fill("yellow");
    textFont('Courier');
    textSize(12.5);
    text("A. " + answerX[answerCount], answerposX, answerposY);
    text("B. " + answerY[answerCount], answerposX + 280, answerposY);
}
function putDate(){ //BY XIAOYU
    fill("yellow");
    textFont('Courier');
    textAlign(CENTER);
    textSize(12.5);
    text(monthCount*2 + " months survived", width/2, 460);
}
function keyTyped(){ //BY XU
    if (key === 'a'){
        //time passes
        timeTracker ++;
        imageCount = floor(random(choices));
        questionCount = imageCount *2;
        answerCount = imageCount;
        subtractHP();
        monthCount ++;
    } else if (key === 'b'){
        //time passes
        timeTracker ++;
        imageCount = floor(random(choices));
        questionCount = imageCount *2;
        answerCount = imageCount;
        subtractHP();
        monthCount ++;
    }
    if (timeTracker >= 3){
        timeTracker = 0;
    }
}
function notRepeat(){ //BY XU
    while (choices_A.includes(imageCount)){
        imageCount = floor(random(choices));
    }
    if(choices_A.length < 6){
        choices_A.push(imageCount);
    }else {
        choices_A.shift();
        choices_A.push(imageCount);
    }
}
function hpTracker(){ //BY XIAOYU
    //academics logo
    noStroke();
    fill("yellow");
    beginShape();
    vertex(logoPosX, logoPosY);
    vertex(logoPosX + 20, logoPosY - 5);
    vertex(logoPosX + 40, logoPosY);
    vertex(logoPosX + 20, logoPosY + 5);
    vertex(logoPosX, logoPosY);
    endShape();
    rectMode(CORNER);
    rect(logoPosX, logoPosY, 1, 10);
    rect(logoPosX + 10, logoPosY, 20, 10);
    //academics hp
    fill("white");
    textFont('Courier');
    textAlign(CENTER);
    textSize(12.5);
    text(academicsHP + "/100", HPposX + 50, HPposY);
    //sanity logo
    fill("yellow");
    circle(logoPosX + 130, logoPosY, 15);
    circle(logoPosX + 130+ 10, logoPosY, 15);
    triangle(logoPosX + 130 - 8, logoPosY, logoPosX + 130 + 18, logoPosY, logoPosX + 130 + 6, logoPosY + 15);
    //sanity hp
    fill("white");
    text(sanityHP + "/100", HPposX + 130 + 30, HPposY);
    //finance logo
    fill("yellow");
    textSize(33);
    text('S', logoPosX + 250, logoPosY + 10);
    rect(logoPosX - 1.5 + 250, logoPosY + 10 - 22, 3, 25);
    //finance hp
    fill("white");
    textSize(12.5);
    text(financeHP + "/100", HPposX + 250 + 25, HPposY);
    //social life logo
    fill("yellow");
    ellipse(logoPosX + 370, logoPosY, 30, 20);
    triangle(logoPosX + 370, logoPosY, logoPosX + 370 + 10, logoPosY, logoPosX + 370 + 10, logoPosY + 15);
    //social hp
    fill("white");
    text(socialHP + "/100", HPposX + 400, HPposY);
}
function subtractHP(){ //BY XU
    //subtract hp
    if (imageCount <= 3){
        var randomNum = random(0, 1);
        if (randomNum < 0.5){
            academicsHP -= 10;
            sanityHP += 10;
        }else{
            academicsHP += 10;
            sanityHP -= 10;     
        }
    }
    if (imageCount >= 4 || imageCount <= 7){
        var randomNum = random(0, 1);
        if (randomNum < 0.5){
            financeHP -= 10;
            socialHP += 10;
        }else{
            financeHP += 10;
            socialHP -= 10;     
        }
    }
    if (imageCount >= 8 || imageCount <= 11){
        var randomNum = random(0, 1);
        if (randomNum < 0.5){
                academicsHP += 10;
            sanityHP -= 10;
        }else{
            academicsHP -= 10;
            sanityHP += 10;     
            }
    }
    if (imageCount >= 12 || imageCount <= 15){
        var randomNum = random(0, 1);
            if (randomNum < 0.5){
            financeHP += 10;
            socialHP -= 10;
        }else{
            financeHP -= 10;
            socialHP += 10;     
        }
    }
}
function checkStatus(){ //BY XU
    if (academicsHP == 100 || sanityHP == 100 || financeHP == 100 || socialHP == 100){
        badEnd = true;
    }
    if (academicsHP == 0 || sanityHP == 0 || financeHP == 0 || socialHP == 0){
        badEnd = true;
    }
    if (monthCount >= 24){
        goodEnd = true;
    }
}
function backgroundChange(){ //BY XIAOYU
    if (timeTracker == 0) {
        backgroundColor = 130;
    }
    if (timeTracker == 1) {
        backgroundColor = 95;
    }
    if (timeTracker == 2) {
        backgroundColor = 0;
    }
}
function drawStar(){ //BY XIAOYU
    noStroke();
    fill("yellow");
    push();
    translate(this.x, this.y);
    ellipse(20, 20, random(1,5), random(1,5));
    pop();
}
function makeStar(starX, starY){ //BY XIAOYU
    var makeStar = {x: starX,
                y: starY,
                draw: drawStar}
    return makeStar;
}
function displayStars(){ //BY XIAOYU
    for (i = 0; i < star.length; i++){
        star[i].draw();
    }
}
function drawCloud(){ //BY XU
    noStroke();
    fill(185);
    push();
    translate(this.x2, this.y2);
    ellipse(15, 26, 34, 20);
    ellipse(45, 30, 22, 25);
    ellipse(15, 35, 15, 16);
    ellipse(30, 28, 28, 26);
    pop();
}
function makeCloud(cloudX, cloudY){ //BY XU
    var makeCloud = {x2: cloudX,
                y2: cloudY,
                speed: -6,
                move: moveCloud,
                draw: drawCloud}
    return makeCloud;
}
function moveCloud(){ //BY XU
    this.x2 += this.speed;
    if(this.x2 <= -10){
        this.x2 += width;
    }
}
function displayCloud(){ //BY XU
    for (i = 0; i < cloud.length; i++){
        cloud[i].move();
        cloud[i].draw();
    }
}
function drawCrow(){ //BY XIAOYU
    strokeWeight(1);
    stroke(0);
    noFill();
    arc(this.x3, this.y3, this.size, this.size/2, PI, TWO_PI);
    arc(this.x3 + this.size, this.y3, this.size, this.size/2, PI, TWO_PI);
}
function makeCrow(crowX, crowY){ //BY XIAOYU
    var makeCrow = {x3: crowX,
                y3: crowY,
                speed2: random(3, 10),
                size: random(5, 10),
                move2: moveCrow,
                draw2: drawCrow}
    return makeCrow;
}
function moveCrow(){ //BY XIAOYU
    this.x3 -= this.speed2;
    this.y3 -= this.speed2 / random(5, 10);
}
function displayCrow(){ //BY XIAOYU
    for (i = 0; i < crow.length; i++){
        crow[i].move2();
        crow[i].draw2();
    }
}
function addCrow(){ //BY XU
    if (random(0,1) < 0.1) {
        var crowX = width;
        var crowY = random(0, height/2);
        crow.push(makeCrow(crowX, crowY));
    }
}
function removeCrow() { //BY XU
    var keep = [];
    for (i = 0; i < crow.length; i++) {
        if (crow[i].x3 + crow[i].size > 0) {
            keep.push(crow[i]);
        }
    }
    crow = keep;
}

For this final project, Xiaoyu and I collaborated to use p5js to create a CMU version of Reigns (a phone game). The game starts by pressing the mouse, then a series of questions will be presented, and the player uses ‘a’ key and ‘b’ key to make choices. There are four HP counters at the top of the screen, and they will fluctuate based on the choices the player makes. Once any of the four HPs reach 0/100 or 100/100, the game will present the bad end. If the player survives until 48 months (4 years), the game presents the good end.

We used things we learned in the past semester to give the game some particular features, such as the background changes, making sure the characters don’t repeat themselves, etc. We drew the characters ourselves in illustrator, and created the gamestart/end pages with p5js.

Leave a Reply