// helen tsui
// 15-104 section d
// hyt@andrew.cmu.edu
// final-project
// image gallery
var poke;
var hugWhite;
var heart;
// welcomePage() global var.
var startRadius = 100;
var lightOn = false;
var endWelcome = false;
// drawPerson() global var.
var headX;
var headY;
var headSize;
// array and other things for bubble and warmth functions
var bubbleX = [];
var bubbleY = [];
var heartArr = [];
var heartV = 0;
var heartPos = []; // heart position in warmUp()
// for setGradient() function
var Y_AXIS = 1;
var X_AXIS = 2;
// rgb values for figure
var r = 161;
var g = 190;
var b = 255;
var addColor = 10;
// check if button is hovered over
var isOverWarmth;
var isOverBubbles;
var clickedBubbleButton = false;
var clickedWarmthButton = false;
var happy = false; // happy face?
// for mouth movement
var endAngle;
var startAngle;
function preload() {
// first icon's courtesy of elon lastad from noun project
hugWhite = loadImage("https://i.imgur.com/LdCyCn9.png");
poke = loadImage("https://i.imgur.com/CV9mms1.png");
heart = loadImage("https://i.imgur.com/DK1JVMP.png");
}
function setup() {
createCanvas(480, 480);
frameRate(16);
}
function draw() {
welcomePage();
if (endWelcome == true) {
//making gradient background
var grad1 = color(42, 46, 127); // gradient color 1
var grad2 = color(156, 83, 156); // gradient color 2
var grad3 = color(78, 83, 107); // gradient color 3
background(0);
setGradient(0, 0, width, height * 0.75, grad1, grad2, Y_AXIS);
setGradient(0, height * 0.75, width, height, grad2, grad3, Y_AXIS);
fill(0, 40);
noStroke();
// land shape
arc(width / 2, height + 20, width * 1.3, height * 0.4, 180, 0, OPEN);
makeSnow();
buttonForBubble();
buttonForWarmth();
drawPerson();
}
}
function welcomePage() {
var bg = 0;
noStroke();
fill(0);
rect(0, 0, width, height);
fill(255, 226, 104, 200); // mustard yellow color
// yellow circle expands
ellipse(width - 20, height - 20, startRadius, startRadius);
var mouseDist = dist(mouseX, mouseY, width - 30, height - 30);
if (mouseDist < 50) {
lightOn = true;
}
if (lightOn == true) {
startRadius += 10;
}
textSize(15);
textFont("Courier New");
text("Will You Be My Friend ", 90, 100);
text("On a Cold Night? ", 90, 120);
textSize(12);
text("• Pat my head to keep me warm", 80, 250);
text("• Drag your mouse and draw bubbles with me", 80, 270);
text("• Click and send me some warm fuzzy hearts", 80, 290);
text("• Happy xmas :)", 80, 310);
// if whole screen yellow, go to second screen
if (startRadius >= 1500) {
endWelcome = true;
}
}
function makeSnow() {
this.x = random(width);
this.y = random(height);
for (var h = 0; h < 150; h++) {
fill(255, 50); // white alpha
ellipse(this.x, this.y, 10, 10, 50);
}
}
function buttonForBubble() {
// make button first
var posX = width - 100;
var posY = 100;
var dist2 = dist(mouseX, mouseY, posX, posY);
if (dist2 < 25) {
isOverBubbles = true;
} else {
isOverBubbles = false;
}
if (isOverBubbles == true) {
push();
fill(161, 190, 255);
text("Draw bubbles with me!", 50, 50);
cursor(HAND);
stroke(200); // ocean color
strokeWeight(4);
if (mouseIsPressed) {
clickedWarmthButton = false;
clickedBubbleButton = true;
}
pop();
}
if (isOverBubbles == false) {
fill(69, 103, 178);
cursor(ARROW);
}
ellipse(posX, posY, 50, 50); // draw button shape
// draw bubble icon on button
push();
fill(255);
ellipse(posX - 9, posY + 7, 10, 10);
ellipse(posX + 6, posY - 6, 16, 16);
ellipse(posX + 7, posY + 12, 8, 8);
pop();
// call function for drawing bubbles
drawBubbles();
}
function buttonForWarmth() {
// make button for hearts and hugs
var posX1 = width - 100;
var posY1 = 180;
var dist1 = dist(mouseX, mouseY, posX1, posY1);
if (dist1 < 25) {
isOverWarmth = true;
} else {
isOverWarmth = false;
}
if (isOverWarmth == true) {
push();
fill(255, 206, 216);
text("feeling loved <3", 50, 50);
cursor(HAND);
stroke(200);
strokeWeight(4);
if (mouseIsPressed) {
clickedBubbleButton = false;
clickedWarmthButton = true;
}
pop();
}
if (isOverWarmth == false) {
fill(173, 140, 147);
//noStroke();
cursor(ARROW);
}
// draw button
ellipse(posX1, posY1, 50, 50); // where the button is
// input icon image
push();
imageMode(CENTER);
scale(0.08, 0.08);
image(hugWhite, posX1 * 12.5, posY1 * 12.5);
pop();
// execute warmUp function
warmUp();
}
function drawBubbles() {
if(!clickedBubbleButton) {
return;
}
// limit bubbles array to 20 circles
if (bubbleX.length > 20) {
bubbleX.shift();
bubbleY.shift();
}
// draw bubble
for (var i = 0; i < bubbleX.length; i++) {
var bubbleInc = random(-10, 10); // bubble increments
var bubblePosX = bubbleX[i] + random(-10, 10); // random X or Y position
var bubblePosY = bubbleY[i] + random(-10, 10); // random X or Y position
var bubbleR = 10 + random(-2, 4);
noStroke();
fill(255, 160);
ellipse(bubblePosX, bubblePosY, bubbleR, bubbleR);
}
}
function warmUp() {
// if warmth button not clicked, warmUp will not be executed
if(!clickedWarmthButton) {
return;
}
// send heart falling rain
heartV += 5;
for (var x = 0; x < heartArr.length; x++) {
push();
scale(0.5, 0.5);
image(heart, heartArr[x], heartPos[x]+heartV);
pop();
}
if (heartPos[x] >= width + 5) {
heartPos = [];
}
}
function drawPerson() {
headX = width / 3;
headY = height / 3;
headSize = 85;
// change body temperature as time goes by
for (var i = 0; i < 1000; i++) {
r -= 0.001;
b += 0.001;
fill(r, g, b);
}
noStroke();
// head
ellipse(headX, headY, headSize, headSize);
image(poke, headX + 50, headY - 20);
// body
rect(headX - 25, headY + 35, 50, 120, 30);
// left arm
rect(headX - headSize * 0.58, headY + 50, 20, 50 * 2, 30);
// right arm
rect(headX + headSize * 0.33, headY + 50, 20, 50 * 2, 30);
// left leg
rect(headX - 25, headX + 120, 18, 130, 30);
// right leg
rect(headX + 7, headX + 120, 18, 130, 30);
// eyes
fill(0);
ellipse(headX - 30, headY, 10, 10);
ellipse(headX, headY, 10, 10);
// blush
fill(252, 204, 255, 150);
ellipse(headX - 35, headY + 21, 14, 12);
ellipse(headX + 4, headY + 21, 14, 12);
fill(0);
// mouth
push();
stroke(0);
strokeWeight(3);
noFill();
angleMode(DEGREES);
if (happy == false) {
startAngle = 180;
endAngle = 0;
}
if (happy == true) {
startAngle = 0;
endAngle = 180;
}
arc(headX - 18, headY + 20, 8, 3, startAngle, endAngle, OPEN);
pop();
}
function mousePressed() {
// when mouse is pressed, the array restarts (new drawing action on canvas)
bubbleX = [];
bubbleY = [];
// push new heart position into array
heartArr.push(mouseX * 2);
heartPos.push(mouseY * 0.5);
// finding distance between mouse and head
var distance = dist(mouseX, mouseY, width/2, height/3);
if (distance < 90) {
cursor(HAND);
r += addColor;
b -= addColor;
if (r >= 160) {
happy = true;
} else {
happy = false;
}
}
}
function mouseDragged() {
if (clickedBubbleButton) {
bubbleX.push(mouseX);
bubbleY.push(mouseY);
}
}
// ---- HELPER CODE REFERENCED FROM P5.JS WEBSITE ---- //
function setGradient(x, y, w, h, c1, c2, axis) {
noFill();
if (axis == Y_AXIS) { // Top to bottom gradient
for (var i = y; i <= y+h; i++) {
var inter = map(i, y, y+h, 0, 1);
var c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x+w, i);
}
}
else if (axis == X_AXIS) { // Left to right gradient
for (var i = x; i <= x+w; i++) {
var inter = map(i, x, x+w, 0, 1);
var c = lerpColor(c1, c2, inter);
stroke(c);
line(i, y, i, y+h);
}
}
}
For the final project, I wanted to create something that is warm and fuzzy to play for this winter, so I made a simple interactive mouse-moving game about a small person looking for company on a cold snowy night.
The game starts with a menu screen, showing the title and instructions for the game. There are three different interactions in the game: patting head for warmth, sending hearts, and drawing bubbles with the character. The user would activate the game by placing the cursor over the yellow circle (on the bottom right side), and then you would see the second screen. When the character reaches a certain temperature, it would have a smiley face showing its happiness; the other two buttons are also clicked on and have separate functions. Have fun exploring and happy holidays 🙂