var terrainSpeed = 0.0005; //set up terrain details for the water effects
var terrainDetail = 0.005;
var smallFishs; //group for food
var fish; //main character
var sharks;
var horses;
var smallRock;
var bigRock;
var deadImg;
var plant;
var img;
var fishImage; //set up for loading image
var sound;
var nE = 0; //number of fish eaten
var play = false;
var dead = false;
//set up coordinates for certain aspects in order to change them throughout code
var imgX = 0;
var imgY = 0;
var textX = 450;
function preload() {
//load up the images from assets
fishImage = loadImage("assets/fish.png");
img = loadImage("assets/titl.png");
deadImg = loadImage("assets/ded.png");
bigRock = loadImage("assets/bigrock.png");
smallRock = loadImage("assets/smallrock.png");
plant = loadImage("assets/plant.png");
sound = loadSound('assets/boop.wav');
}
function setup() {
createCanvas(1000 , 600);
fish = createSprite(width/2, height/2); //spawn goldfish in the middle
//set movement limits to goldfish
fish.maxSpeed = 6;
fish.friction = .9;
fish.setCollider();
//add the actual image into sprite variable
fish.addImage("normal", fishImage);
//set up groups
smallFishs = new Group();
sharks = new Group();
horses = new Group();
}
function draw() {
//set up background of the game
background(80, 80, 220);
fill(150, 150, 0);
noStroke();
rect(0, 570, 1000, 100);
image(smallRock, 1000, 490)
push();
scale(2);
image(plant, 90, 255);
pop();
image(bigRock, 600, 480);
image(smallRock, -250, 450);
//set up conditions for starting screen
if (play == false){
image(img, imgX, imgY);
} else {
drawWaves();
fish.overlap(smallFishs, eatFish); //set up overlap for goldfish and food fish
sharks.overlap(fish, sharkEat);
//set up rotation speed / movement speed for gold fish
if(keyDown(LEFT_ARROW)) {
fish.rotation -= 2;
}
if(keyDown(RIGHT_ARROW)) {
fish.rotation += 2;
}
if(keyDown(UP_ARROW)) {
fish.addSpeed(.45, fish.rotation);
}
//come over on the other side if fish goes too far left/right
if (fish.position.x > 1000) {
fish.position.x = 0;
} else if (fish.position.x < 0) {
fish.position.x = 1000;
}
//come over on the other side if fish goes too far top/bottom
if (fish.position.y > 600) {
fish.position.y = 0;
} else if(fish.position.y < 0){
fish.position.y = 600;
}
//constantly create small fish randomly around the canvas
if(random(0, 100) < 10) {
var pn = random(360);
var px = (width/2 + 1000) * cos(radians(pn));
var py = (height/2 + 1000) * sin(radians(pn));
createSmallFish(3, px, py);
}
//create sharks randomly but rarely
if(random(0, 100) < 1) {
var bn = random(300);
var bx = (width/2 + 1000) * cos(radians(bn));
var by = (height/2 + 1000) * sin(radians(bn));
createShark(3, bx, by);
}
//constantly spawn seahorses, but rarely
if(frameCount%70==0 & horses.length < 20) {
createHorses(random(0,width), random(0,height));
}
for(var i = 0; i < horses.length; i++) {
var sea = horses[i]; //create variable for seahorses
sea.scale = map(sea.life, 220, 0, 1, 0); //lives for limited frames, changes sizes according to time
sea.displace(fish); //push away and block goldfish's path
}
drawSprites();
text("Fishy Points: " + nE, textX, 50); //text showing current game points
}
}
function createSmallFish(x, y) { //function that builds small fish
var smol = createSprite(x, y);
var smolfish = loadImage("assets/smallfish.png");
smol.addImage(smolfish);
smol.setSpeed(1, random(360));
smol.rotationSpeed = .1;
smol.setCollider("rectangle", 0, 0, 0, 0);
smallFishs.add(smol);
return smol;
}
function createShark(x, y) { //function that builds sharks
var big = createSprite(-x, y);
var bigShark = loadImage("assets/shark.png");
big.addImage(bigShark);
big.setSpeed(.5, random(360));
big.rotationSpeed = .05
big.setCollider("rectangle", 0, 0, 100, 10);
sharks.add(big);
return big;
}
function createHorses(x, y) { //function that builds seahorses with an animation that shrinks size
var sea = createSprite(x, y);
sea.addAnimation("horses", "assets/seahor.png");
sea.life = 220;
sea.rotationSpeed = .08
sea.setCollider("rectangle", 0, 0, 0, 0);
horses.add(sea);
}
function eatFish(fish, smallFishs) { //function to remove the small fish when overlapping as well as
//adding on to fish eaten counter
sound.play();
nE += 1;
smallFishs.remove();
}
function sharkEat(sharks, fish) {
dead = true;
play = false;
if (dead == true) {
imgX += 1000;
imgY += 1000;
textX += 1000;
image(deadImg, 0, 0);
fill(186, 217, 180);
textSize(52.72);
text("" + nE, 550, 321);
noLoop();
}
}
function keyPressed(){
if (keyCode === 88){
play = true;
}
}
function drawWaves(){
//wave 1
fill(144,175,197, 60);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * 0.003) + (millis() * terrainSpeed * 2);
var y = map(noise(t), 0,1, 0, height * 0.1);
vertex(x, y+ 1);
}
vertex(width,height);
vertex(0,height);
endShape();
//wave 2
fill(51,107,135, 60);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * 0.003) + (millis() * terrainSpeed * 2);
var y = map(noise(t), 0,1, 0, height * 0.1);
vertex(x, y+50);
}
vertex(width,height);
vertex(0,height);
endShape();
//wave 3
fill(144,175,197, 60);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * 0.003) + (millis() * terrainSpeed * 2);
var y = map(noise(t), 0,1, 0, height * 0.1);
vertex(x, y+65);
if(noise(t) > 0.2){
fill(144, 175, 197, 80);
}
else {
fill(144,175,197,120);
}
}
vertex(width,height);
vertex(0,height);
endShape();
//wave 4
fill(51,107,135, 60);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * 0.003) + (millis() * terrainSpeed * 2);
var y = map(noise(t), 0,1, 0, height * 0.1);
vertex(x, y+100);
}
vertex(width,height);
vertex(0,height);
endShape();
}
The game is played by using the left / right arrow keys to change the rotation of the fish, and using the up arrow to move forward. Try to get as many points as possible by eating the smaller fish, while avoiding the angry sharks that will end the game if they touch you. The searhorses will stop your movement, so try to move around them.
Basing off how old styled games were formed, I wanted to make a game that has an unlimited ‘reward’ while having a losing condition. Using knowledge earned from the class, I was able to display and create the game I wanted to.
For my project, I decided to stay with the theme I had developed throughout the semester with plane-based projects.
The objective of the game is to fly the plane onto the runway while avoiding mountains and lightning. Instructions for running the game are included.
I had a really hard time with this project. My original concept was perhaps more interesting but I had an extremely hard time executing it, so I pivoted my project to this secondary concept at the last minute. However, I had a lot of fun creating it, as well as working on the styling and themes of the splash screens in particular. I hope you enjoy it!
//Jackie Chou
//jwchou@andrew.cmu.edu
//Section E
//Final Project
//stores image variables
var explosion;
var lost;
var crash;
var win;
var beginScreen;
var lightning;
var mountain;
var img;
//variable to determine if the game has started
var gameStarted = false;
//position and speed variables for the plane
var xPos = 240;
var yPos = 0;
var xSpeed = 0;
var ySpeed = 0;
//arrays to store the obstacles in
var mountains = [];
var lightnings = [];
function setup() {
createCanvas(480, 480);
//load background and obstacle images
img = loadImage("https://i.imgur.com/x3rvhGU.png");
lightning = loadImage("https://i.imgur.com/v6p1ANv.png");
mountain = loadImage("https://i.imgur.com/tLB1n6D.png");
explosion = loadImage("https://i.imgur.com/8J62X6Z.png");
//load splash screens
lost = loadImage("https://i.imgur.com/znFRmOW.png");
crash = loadImage("https://i.imgur.com/TXv7bto.png");
win = loadImage("https://i.imgur.com/T0qvSdh.png");
beginScreen = loadImage("https://i.imgur.com/J34UN7I.png");
//pushes random coordinates into the obstacle arrays
for (i = 0; i < 8; i++) {
lightnings.push(random(0, width));
lightnings.push(random(80, 350));
mountains.push(random(0, width));
mountains.push(random(80, 350))
}
}
function draw() {
imageMode(CENTER);
//draws background image
image(img, 240, 240);
//initializes plane if the game has begun
if (gameStarted == true){
ySpeed = 0.5;
}
//controls plane's direction
yPos += ySpeed;
xPos += xSpeed;
//calls function to draw obstacles
drawObstacles();
//displays splash screen before the game starts
if (gameStarted == false) {
image(beginScreen, width/2, height/2);
}
//drawing the airplane
fill(240);
strokeWeight(0.5);
//wings
ellipse(xPos, yPos, 70, 11);
ellipse(xPos, yPos - 20, 35, 8);
//horz stabilizer
fill(108, 190, 225);
ellipse(xPos, yPos, 17, 45);
//fuselage
ellipse(xPos + 17, yPos + 5, 6, 15);
//left engine
ellipse(xPos - 17, yPos + 5, 6, 15);
//right engine
fill(0);
ellipse(xPos - 17, yPos + 10, 10, 2);
//right propeler
ellipse(xPos + 17, yPos + 10, 10, 2);
//left propeller
fill(240);
ellipse(xPos, yPos - 25, 5, 17);
//tail
fill(0);
beginShape();
//cockpit
vertex(xPos - 5, yPos + 10);
vertex(xPos, yPos + 17);
vertex(xPos + 5, yPos + 10);
vertex(xPos + 5, yPos + 5);
vertex(xPos, yPos + 10);
vertex(xPos - 5, yPos + 5);
vertex(xPos - 5,yPos + 10);
endShape();
//checks to see if the plane has collided into lightning
for (i = 0; i < lightnings.length; i += 2) {
if (dist(xPos, yPos, lightnings[i], lightnings[i+1]) <= 35) {
gameOver();
}
}
//checks to see if the plane has collided in mountains
for (i = 0; i < mountains.length; i += 2) {
if (dist(xPos + 3, yPos, mountains[i], mountains[i+1]) <= 38) {
gameOver();
}
}
//calls landing function if plane crosses top edge of runway
if (dist(xPos, yPos, 235, 440) <= 15) {
xSpeed = 0;
ySpeed = 0;
landed();
}
//calls lost screen function if plane leaves canvas (x)
if (xPos <= 10 || xPos >= 470) {
gotLost();
}
//calls lost screen function if plane leaves canvas (y)
if (yPos >= 470) {
gotLost();
}
}
//draws the obstacles using randomized values from the arrays
function drawObstacles() {
for (i = 0; i < lightnings.length; i += 2) {
image(lightning, lightnings[i], lightnings[i+1]);
//image(mountain, random(0, width), random(80, 350));
}
for (i = 0; i < mountains.length; i += 2) {
image(mountain, mountains[i], mountains[i+1]);
}
}
//controls the direction of the plane via arrow keys
function keyPressed() {
if (keyCode === RIGHT_ARROW) {
xSpeed = 0.65;
}
if (keyCode === LEFT_ARROW) {
xSpeed = -0.65;
}
if (keyCode === DOWN_ARROW) {
xSpeed = 0;
}
}
//starts the game
function mousePressed() {
gameStarted = true;
}
//game over function, displays splash screen
function gameOver() {
image(explosion, xPos, yPos - 3);
image(crash, width/2, height/2);
noLoop();
}
//plane lost function
function gotLost() {
image(lost, width/2, height/2);
noLoop();
}
//plane landed function
function landed() {
image(win, width/2, height/2);
noLoop();
}
//Name: Max Stropkay
//Andrew ID: mstropka@andrew.cmu.edu
//Section: E
//Final Project
//decalare variables for font, and audio file
var avenir;
var littlewing;
//array to store vehicle objects
var vehicles = [];
//diameter of circles
var diameter;
//store the value of the amplitude of the audio file
var amplitude;
//array to store the strings that make up the lyrics
//of the song
var lyrics = ['little wing', 'well','shes','walking','through',
'the','clouds','with a', 'circus', 'mind', 'thats','running', 'round',
'butterflies', 'zebras', 'moonbeams', 'fairytales',
'thats all', 'she ever', 'thinks about', 'riding with', 'the', 'wind', 'when',
'Im sad', 'she comes', 'to me', 'with a', 'thousand', 'smiles', 'she',
'gives to', 'me', 'free','its alright', 'she said', 'its alright', 'take',
'anything', 'you', 'want', 'from me', 'anything'];
//array to store the times at which the lyrics
//should appear on screen
var times = [34000, 500, 500, 3000, 500, 500, 2000, 200, 300, 3000, 500,
500, 3000, 1500, 1500, 2000, 3000, 3000, 300, 300, 300, 2000, 4000,
500, 500, 3000, 500, 500, 2000, 200, 300, 3000, 500,
500, 3000, 1500, 1500, 2000, 3000, 3000, 300, 300, 2000, 300, 18000];
var word = -1;
//load soundfile and font
function preload() {
littlewing = loadSound('https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/Jimi-Hendrix-Little-Wing.mp3')
avenir = loadFont("https://s3.us-east-2.amazonaws.com/maxstropkayfinalproject/AvenirNextLTPro-Demi.otf");
}
function setup() {
createCanvas(1200, 480);
//play audio file,set volume
littlewing.play();
littlewing.setVolume(0.5);
//set value of amplitude to the amplitude of audio
amplitude = new p5.Amplitude(.04);
updateLyrics();
}
function draw() {
background(51);
//for every vehicle run behaviors, update, and show
for (var i = 0; i < vehicles.length; i++){
var v = vehicles[i];
v.behaviors();
v.update();
v.show();
}
//set diameter to be determined by the amplitude
var level = amplitude.getLevel();
var volume = map(level, 0, 1, 0, 200);
diameter = volume;
}
//define Vehicle object
function Vehicle(x, y) {
this.pos = createVector(random(0, width), random(0, height));
this.target = createVector(x, y);
this.vel = p5.Vector.random2D();
this.acc = createVector();
this.r = 10;
this.color = 255;
this.maxspeed = 10;
this.maxforce = 0.5;
}
Vehicle.prototype.behaviors = function(f) {
var arrive = this.arrive(this.target);
this.applyForce(arrive);
}
Vehicle.prototype.applyForce = function(f) {
this.acc.add(f);
}
//move vehicles based on attraction to the
//target location
Vehicle.prototype.update = function() {
this.pos.add(this.vel);
this.vel.add(this.acc);
this.acc.mult(0);
this.r = diameter + 10*(random(0,1));
this.color = color(diameter*random(0, 100), diameter*random(0, 5), diameter*random(0, 10));
}
//draw ellipses at x,y coordinates of objects
Vehicle.prototype.show = function() {
noStroke();
fill(this.color);
ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
//change speed of object as it gets closer to
//its target location
Vehicle.prototype.arrive = function(target) {
var desired = p5.Vector.sub(target, this.pos);
var d = desired.mag();
var speed = this.maxspeed;
if (d < 100){
var speed = map(d, 0, 100, 0, this.maxspeed);
}
desired.setMag(speed);
var steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxforce);
return steer;
}
//move object toward its desired position
Vehicle.prototype.seek = function(target) {
var desired = p5.Vector.sub(target, this.pos);
desired.setMag(this.maxspeed);
var steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxforce);
return steer;
}
//display the next word in the array lyrics
//at the time from the time array
function updateLyrics(){
vehicles = [];
word = (word + 1) /*% lyrics.length*/;
print(word);
textAlign(CENTER);
textFont("Avenir")
var points = avenir.textToPoints(lyrics[word], 70, 300, 192);
//console.log(points)
for (var i = 0; i < points.length; i++){
var pt = points[i];
var vehicle = new Vehicle(pt.x, pt.y);
vehicles.push(vehicle);
// stroke(0,255,0);
// strokeWeight(4);
// point(pt.x, pt.y);
}
print(times[word]);
setTimeout(updateLyrics,times[word]);
}
For my final project, I made a program that generates dots that change size and color based on the volume of the music thats being played in the background. The dots then fly to form the lyrics in the song. Syncing up the timing of the lyrics and the music was harder and more time consuming than I anticipated, so it only is synced for the first verse.
Attached is the zip file that contains the audio and the font that can be run on a local server.
//calls beginning function to start the game over
var scene = new beginning();
//holds background images
var bg = [];
var bgURL = [
//outside image
"https://i.imgur.com/NhThk6g.jpg",
//lake reflection image
"https://i.imgur.com/GA10Vet.jpg",
//image of both lake and forest
"https://i.imgur.com/c6C6zEC.jpg",
//cat image
"https://i.imgur.com/4zrzVTj.jpg",
//true ending image
"https://i.imgur.com/LADTQJI.jpg"];
function setup() {
createCanvas(480, 450);
}
function preload(){
// load images from URL
for (i = 0; i < bgURL.length; i++){
bg.push(loadImage(bgURL[i]));
}
}
//LIST OF SCENES
function beginning() {
this.sentence = "You wake up surrounded by complete darkness." +
" Your body aches and you hear the faint sound of growling behind you." +
" You pull your red hood around yourself to keep warm." +
" You feel around and find two doors." +
" One with a round knob and one of with a square knob.";
this.left = new sit1();
this.right = new sitA();
this.lefttext = "go through the round knobbed door";
this.righttext = "go through the square knobbed door";
this.fillcolor = "black";
}
//Round knobbed door
function sit1() {
this.sentence = "You immediately begin to sprint out the door." +
" The fresh air hits your face like cold knives. Outside." +
" You look behind you to hear the growling rumble louder." +
" She's waking up too.";
this.left = new sit2();
this.right = new death("You wait and see what happens." +
" The beast begins to wake up and it immediately sees you" +
" She's angry and you know exactly why." +
" She leaps towards you in a familiar fashion," +
" mouth wide open and ready to bite down...");
this.lefttext = "RUN!!!!";
this.righttext = "Wait and see what happens";
this.fillcolor = "";
this.b = "outside";
}
function sit2() {
this.sentence = "You run away before the beast could notice you leaving." +
" You see a forest and a lake in the distance";
this.left = new sitOne();
this.right = new sit3();
this.lefttext = "Run towards the forest";
this.righttext = "Run towards the lake";
this.fillcolor = "";
this.b = "treeAndLake"
}
function sit3() {
this.sentence = "As you run towards the lake," +
" you stop by the edge of the water," +
" mesmorized by your own unrecognizable reflection...";
this.left = new death("You can't help but continue staring at yourself." +
" Bright blue eyes and a long red cape embracing your frail body." +
" You hear growling beghind you... GIVE...IT...BACK.... ");
this.right = new sitThree();
this.lefttext = "Keep staring at your own reflection";
this.righttext = "Pull your eyes away and continue running";
this.fillcolor = "";
this.b = "reflection"
}
function sitOne(){
this.sentence = "Start running faster and faster through the forest," +
" trees flashing past you." +
" You hear the growling not too far behind...";
this.left = new death("You climbed up the tree as fast as you could." +
" Right as you grabbed a second branch," +
" you feel your hood getting tugged, pulling you down with it...");
this.right = new sitTwo();
this.lefttext = "Climb up a tree";
this.righttext = "Hide in the bushes";
this.fillcolor = "flashing green";
}
function sitTwo(){
this.sentence = "You jump into a nearby bush and wait..." +
" the sound of a frustrated growling felt close," +
" but it seems to have disappeared now.";
this.left = new sitThree();
this.right = new sit3();
this.lefttext = "Keep running!";
this.righttext = "Run back towards the lake";
this.fillcolor = "";
this.b = "outside";
}
function sitThree(){
this.sentence = "You decide to keep running." +
" As you run you trip over a soft rock." +
" Wait, that's a cat!";
this.left = new sitFour();
this.right = new sitFour();
this.lefttext = "Pet the cat";
this.righttext = "Scratch the cat's belly";
this.fillcolor = "";
this.b = "cat";
}
function sitFour(){
this.sentence = "The cat purrs and rolls around on the ground." +
" After a few minutes it gets up.";
this.left = new sitneutralending();
this.right = new sitneutralending();
this.lefttext = "Follow the cat";
this.righttext = "Why wouldn't you follow this cat?";
this.fillcolor = "";
this.b = "cat";
}
//Neutral ending
function sitneutralending(){
this.sentence = "(Neutral ending) You follow the cat into a small den." +
" I guess this is a nicer ending."
this.lefttext = "";
this.righttext = "";
this.fillcolor = "";
this.b = "outside";
}
//--------------------
//Square knobbed door
function sitA() {
this.sentence = "You open the door and find yourself looking into a closet." +
" You run in and shut the door as quietly as you can." +
" She's awake now too.";
this.left = new sitB();
this.right = new death("You decided to scream on the top of your lungs." +
" Immediately and without warning, the beast breaks through the closet" +
" door. Did you have a death wish?");
this.lefttext = "Stay quiet and hope she leaves";
this.righttext = "SCREAM!!!";
this.fillcolor = "black";
}
//Closet scene
function sitB() {
this.sentence = "You decide to sit quietly in the closet." +
" After what seemed like hours, the growling disappeared...";
this.left = new sitC();
this.right = new sit1A();
this.lefttext = "Stay in the closet";
this.righttext = "Walk out";
this.fillcolor = "black";
}
function sitC() {
this.sentence = "You felt uneasy and decided to stay in the closet." +
" You lean back onto the back of the closet and surprisingly," +
" you fell into a hole that leads outside!";
this.left = new sitD();
this.right = new sit1A();
this.lefttext = "Stay in the closet";
this.righttext = "Crawl outside";
this.fillcolor = "black";
}
function sitD(){
this.sentence = "You STILL decide to stay in the closet for some reason." +
" Maybe you're still feeling uneasy..." +
" Time continues to pass as it usually does."+
" Are you even going to continue on this journey?";
this.left = new sitE();
this.right = new sit1A();
this.lefttext = "Stay in the closet";
this.righttext = "CRAWL OUTSIDE";
this.fillcolor = "black";
}
function sitE(){
this.sentence = "You still stay in the closet. This is not like the narnia" +
" wardrobe. There is nothing special about this closet." +
" Why do you want to stay in here so badly?";
this.left = new sitF();
this.right = new sit1A();
this.lefttext = "Stay in the closet";
this.righttext = "Crawl. Outside. Now.";
this.fillcolor = "black";
}
function sitF(){
this.sentence = "Okay, you've committed, we'll stay in this dumb closet."+
" I even took away the 'crawl outside' button. I hope you're happy with yourself.";
this.left = new sitG();
this.right = new sitG();
this.lefttext = "Stay in the closet";
this.righttext = "Stay in the closet";
this.fillcolor = "black";
}
function sitG(){
this.sentence = "I bet you're happy about this endless loop,"+
" Even if you change your mind you won't get it back, you're gonna have to" +
" refresh this whole game manually.";
this.left = new sitH();
this.right = new sitH();
this.lefttext = "Stay in the closet";
this.righttext = "Stay in the closet";
this.fillcolor = "black";
}
function sitH(){
this.sentence = "...";
this.left = new sitI();
this.right = new sitI();
this.lefttext = "Stay in the closet";
this.righttext = "Stay in the closet";
this.fillcolor = "black";
}
function sitI(){
this.sentence = "..........";
this.left = new sitJ();
this.right = new sitJ();
this.lefttext = "Stay in the closet";
this.righttext = "Stay in the closet";
this.fillcolor = "black";
}
function sitJ(){
this.sentence = "..................";
this.left = new sitK();
this.right = new sitK();
this.lefttext = "Stay in the closet";
this.righttext = "Stay in the closet";
this.fillcolor = "black";
}
function sitK(){
this.sentence = "Okay, I'm just going to push you outside. Shoo!";
this.left = new sit1A();
this.right = new sit1A();
this.lefttext = "OUTSIDE";
this.righttext = "GO. OUTSIDE.";
this.fillcolor = "black";
}
//To grandmothers house we go!
function sit1A(){
this.sentence = "You walk outside to see the beast far off in the distance," +
" obviously looking for you. But you have other plans...";
this.left = new death("You dance(?) towards the beast flailing about,"+
" probably hoping to get eaten. (I bet you were the same person wanting to" +
" stay in that closet...)");
this.right = new sit1B();
this.lefttext = "Ignore your plans and dance towards the beast";
this.righttext = "Head towards the smoke in the nearby forest";
this.fillcolor = "";
this.b = "outside";
}
function sit1B(){
this.sentence = "You run through the forest, to grandmother's house." +
" She'll protect you from the beast. You hear the beast" +
" catching up to you, desperate to get what you've stolen back..." +
" You notice that there is a large pit nearby";
this.left = new sit1C();
this.right = new goodishending();
this.lefttext = "Continue running towards grandmother's house";
this.righttext = "Wait to push the wolf into the pit";
this.fillcolor = "flashing green";
}
function sit1C(){
this.sentence = "You finally reach the door of the house" +
" The beast is not far behing you. 'GRANDMOTHER' you scream, let me in!" +
" Hurry!!";
this.left = new trueending();
this.right = new death("You decide to keep running, but the beast gets to you." +
" And you were so close too!");
this.lefttext = "Wait for grandmother to open the door";
this.righttext = "Keep running!";
this.fillcolor = "";
this.b = "outside";
}
//True ending
function trueending(){
this.sentence = "(True Ending) Soon after, the door opens." +
" It's almost impossible to hide your grin..." +
" You look back at the girl in wolfs skin that was chasing you," +
" desperate to get her hood back." +
" 'My, what big teeth you have, little riding hood'!";
this.lefttext = "";
this.righttext = "";
this.fillcolor = "";
this.b = "trueEnd";
}
//Death scene when the beast gets you
function death(sentence) {
this.sentence = sentence;
this.lefttext = "";
this.righttext = "";
this.fillcolor = "red";
}
//Good ending where you kill the beast
function goodishending(){
this.sentence = "(Good Ending) You push the wolf into the pit. Hooray!" +
" Now nothing is in your way...";
this.lefttext = "";
this.righttext = "";
this.fillcolor = "";
this.b = "outside";
}
function draw() {
//Determining background color
if (scene.fillcolor == "red"){
background(171,6,11);
}
else if (scene.fillcolor == "blue"){
background(0, 6, 34);
}
else if (scene.fillcolor == "flashing green"){
frameRate(8);
var r = random(0, 8);
var g = random(0, 60);
var b = random(0, 5);
background(r, g, b);
}
else if (scene.fillcolor == "green"){
background(2, 26, 8);
}
else if (scene.fillcolor == "black"){
background(0);
}
else {
background(0);
}
//Creates background images
if (scene.b == "outside"){
image(bg[0], 0, 0, 480, 450);
}
if (scene.b == "reflection"){
image(bg[1], 0, 0, 480, 450);
}
if (scene.b == "treeAndLake"){
image(bg[2], 0, 0, 480, 450);
}
if (scene.b == "cat"){
image(bg[3], 0, 0, 480, 450);
}
if (scene.b == "trueEnd"){
image(bg[4], 0, 0, 480, 450);
}
//Story text details
fill(200);
textSize(12);
text(scene.sentence, 50, 270, 380, 80);
//left text decision
text(scene.lefttext, 50, 380, 100);
//right text decision
text(scene.righttext, 300, 380, 100);
//Reset button text
if (scene.lefttext == "") {
text("click here to start over", 180, 370);
}
}
//Creating "buttons" for choices and for reset
function mouseClicked(){
//Reset button
if (scene.lefttext == "") {
if (mouseX > 180 & mouseX < 300 && mouseY > 360 && mouseY < 380){
//resets game
scene = new beginning();
}
}
else{
//left button decision
if (mouseX > 50 & mouseX < 130 && mouseY > 370 && mouseY < 420){
scene = scene.left;
}
//right button decision
if (mouseX > 300 & mouseX < 440 && mouseY > 370 && mouseY < 420){
scene = scene.right;
}
}
}
I decided to create a choose-your-own-adventure game! My initial idea was to focus on having no visuals—using only text and sound to guide the user through the story—but ultimately ended up using both visuals and text together, and just text on its own.
The story was difficult to write in its own right and I don’t claim that it is that good, but the point of this game is that most of the endings the user runs into will build on the story of the game. I decided to focus mainly on using objects (since that was the most difficult part of this class for me and I wanted to make sure I ended this class with the knowledge of how to use them).
/*
* GyuEun Park
* 15-104 E
* gyueunp@andrew.cmu.edu
* Final Project
*/
var dots = []; //array of dots in beginning scene
var gravity;
var stars = []; //array of stars in ending scene
var speed;
var ismoving = true;
function setup() {
createCanvas(600, 600);
background(14, 94, 96);
//turtle for the center of the transition scene
var turtle = makeTurtle(width - 115, height - 455);
turtle.penDown();
turtle.setColor(0);
for (var i = 0; i < 1300; i++) {
turtle.forward(10);
turtle.right(141.5);
turtle.forward(420);
if (i % 20 === 0) {
turtle.forward(70);
}
}
if (ismoving){
//dots jump up relatively high due to gravity
gravity = createVector(0, 0.2);
fill(16, 198, 216, 100);
stroke(186, 198, 216, 200);
strokeWeight(4);
}
else {
//array of stars up to 2000
for (var i = 0; i < 2000; i++) {
stars[i] = new Star();
}
}
}
function draw() {
if (ismoving) {
//drawing jumping dots in the initial scene
background(1, 11, 28, 50);
if (random(1) < 0.2) {
dots.push(new Dots());
}
//push through the array of dots, update and show them
for (var i = 0; i < dots.length; i++) {
dots[i].update();
dots[i].show();
}
}
else {
background(1, 11, 28, 10);
//the lower the cursor, the slower the star movement
speed = map(mouseY, 10, width / 2, 0, 5);
//translate so that stars moving out from center, not top left
translate(width / 2, height / 2);
for (var i = 0; i < stars.length; i++) {
//update and show stars that are in motion
stars[i].update();
stars[i].show();
}
}
}
//dot constructor function
function Dots() {
this.dots = new Particle(random(width), height);
this.update = function() {
this.dots.applyForce(gravity);
this.dots.update();
}
this.show = function() {
this.dots.show();
}
}
//particle constructor function
function Particle(x,y) {
this.pos = createVector(x,y);
this.vel = createVector(0, random(-15, -5));
this.acc = createVector(0, 0);
this.applyForce = function(force){
//add force to acceleration, force accumulation
this.acc.add(force);
}
this.update = function() {
//take the acceleration and adds it to the velocity
this.vel.add(this.acc);
//take the velocity and adds it to the position
this.pos.add(this.vel);
//multiply acc to 0 so that acc starts with 0
this.acc.mult(0);
}
this.show = function() {
point(this.pos.x, this.pos.y);
}
}
//star details in the transitioned scene
function Star() {
this.x = random(-width, width);
this.y = random(-height, height);
this.z = random(width);
this.pz = this.z;
this.update = function() {
this.z = this.z - speed;
if (this.z < 1) {
this.z = width;
this.x = random(-width, width);
this.y = random(-height, height);
this.pz = this.z;
}
}
this.show = function() {
fill(16, 198, 216, random(200));
noStroke();
//the locations of the stars, dispersed across the canvas
var sx = map(this.x / this.z, 0, 4, 0, width);
var sy = map(this.y / this.z, 0, 3, 0, height);
//when closer bigger, when farther smaller in size
var r = map(this.z, 0, width, 16, 0);
ellipse(sx, sy, r, r);
}
}
function mousePressed(){
ismoving = !(ismoving);
setup();
}
function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}
Instructions: Click anywhere or move your cursor around to make alterations.
Brief summary: Jumping Dots, Turtle, and Turquoise Starfield.
For my final project, I took the advantage of making my canvas a space in which the viewers could momentarily be immersed in. As I believe that the strength of interactive artworks is their ability to allow the audiences to create unexpected changes, I allowed the environment of my work to be altered by the viewers. Despite the changeable environment, however, I also focused on achieving a sense of visual consistency through the usage of coherent colorations and forms.
Conflicting factors coexist in my work; the space is chaotic yet orderly, inviting yet daunting, random yet systematic. Coexistences such as these were merged in creating this single work. I hope you enjoy momentarily being immersed in this space I created!
I also filmed projections of my work to experience its amplified effects outside of my screen.
and here are screenshots of various possible outcomes:
Here is a video of a slight alteration of the piece. I liked how it looked (and reminded me of Christmas and our imminent winter break!), so I decided to include it.
//Anna Boyle and Thomas Wrabetz
//Main functions
//Thomas' code
function setup() {
createCanvas(480, 480);
rectMode( CENTER );
player = makePlayer( width / 2, height / 2 );
level = makeLevel();
var sec=second();
}
function draw() {
background(200);
player.draw();
player.step();
level.draw();
//Anna's code
fill(0);
txt=width/2
fill(255);
noStroke();
if (drawBubble==1){
//triangle for speech bubble
triangle(width/2-20, txtH+20, bubbleX, bubbleY, width/2+20, txtH+20)
//if the player is on the top half, make the bubble on the bottom half
if (player.y<height/2){
txtH=440;
rect(width/2, 470, width, bubbleHeight);
//adjust the line height when there is only one line
singleLineHeight=465;
//if the player is on the bottom half, make the bubble on the top half
}if (player.y>=height/2){
txtH=30;
rect(width/2, 20, width, bubbleHeight);
//adjust the line height when there is only one line
singleLineHeight=30;
}
fill(0);
//makes the quote
textSize(17);
textAlign(CENTER);
printQuote( whichQuote );
}
rectMode(CORNER);
//draws the inspiration meter red bar
fill(188, 64, 64);
rect(width-20, 0, 20, height);
//draws the inspiration meter's variable green bar
fill(64, 188, 64);
rect(width-20, height-inspiroMeter, 20, height);
rectMode(CENTER);
//if the player gets enough quotes, they will win and see this screen
if (inspiroMeter>480){
fill(255);
rect(width/2, height/2, width, height)
fill(0);
textSize(32)
text("CONGRATULATIONS!", width/2, height/2-25);
text("YOU ARE INSPIRED", width/2, height/2+25);
noLoop();
}
}
//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Player object
//-----PLAYER OBJECT-----//
var PSIZE = 30;
var PCOLOR = [ 25, 150, 25, 255 ];
var PSPEED = 3;
var keyArray = [];
//Updates the player's position based on keyboard input
function stepPlayer()
{
//Variables to track the player's movement in each direction
var yStep = 0;
var xStep = 0;
if( keyIsPressed )
{
for( var i = 0; i < keyArray.length; i++ )
{
switch( keyArray[i] )
{
case 'W':
yStep -= PSPEED;
break;
case 'S':
yStep += PSPEED;
break;
case 'A':
xStep -= PSPEED;
break;
case 'D':
xStep += PSPEED;
break;
}
}
//Adjust speed for diagonal movement
if( xStep != 0 & yStep != 0 )
{
xStep *= 0.7071
yStep *= 0.7071
}
//Check if the player will collide with a wall in the x-direction
//and move the player if not
if( !level.collisionSearch( this.x + xStep, this.y, PSIZE ) )
{
//If the player is too close to the edges of the screen,
//move the level instead of the player
if( ( this.x < width * 4/5 || xStep < 0 )
&& ( this.x > width * 1/5 || xStep > 0 ) ) this.x += xStep;
else level.xOffset -= xStep;
}
//Check if the player will collide with a wall in the y-direction
//and move the player if not
if( !level.collisionSearch( this.x, this.y + yStep, PSIZE ) )
{
//If the player is too close to the edges of the screen,
//move the level instead of the player
if( ( this.y < height * 4/5 || yStep < 0 )
& ( this.y > height * 1/5 || yStep > 0 ) ) this.y += yStep;
else level.yOffset -= yStep;
}
//If the player collides with a figure, update the bubble
var figure = level.figureCollisionSearch( this.x + xStep,
this.y + yStep, PSIZE );
if( figure != -1 )
{
if( !drawBubble )
{
drawBubble = true;
//Only update to a new quote if this is a different figure
if( bubbleID != level.figures[ figure ].ID )
{
bubbleID = level.figures[ figure ].ID;
updateBubble();
}
}
bubbleX = level.figures[ figure ].x + level.xOffset;
bubbleY = level.figures[ figure ].y + level.yOffset;
}
else if( drawBubble )
drawBubble = false;
level.step();
}
}
//Draw the player
function drawPlayer()
{
fill( PCOLOR );
rect( this.x, this.y, PSIZE, PSIZE );
}
function makePlayer( px, py )
{
player = { x: px, y: py, draw: drawPlayer, step: stepPlayer };
return player;
}
//-----KEY TRACKING-----//
//Each key pressed is stored in the key array
function keyPressed()
{
keyArray.push( key );
}
//Keys are removed from the key array when released
function keyReleased()
{
for( var i = 0; i < keyArray.length; i++ )
{
if( keyArray[i] == key ) keyArray.splice( i, 1 );
}
}
//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Walls and level and figures
//-----INSPIRATIONAL FIGURE OBJECT-----//
figureColorArray = [ "Red", "Blue", "Green", "Yellow",
"Purple", "Orange", "Brown" ];
//Counter to give the figures unique IDs
figureIDCounter = 0;
//Counter that keeps track of how many open spaces have been created
figureCounter = 0;
//Each time figureCounter reaches FIGUREFREQ, a new figure is created
FIGUREFREQ = 10;
//Size of a figure
FIGUREWIDTH = 30;
function makeFigure( xPos, yPos )
{
figure = { x: xPos, y: yPos, figureColor: random(figureColorArray),
ID: figureIDCounter };
figureIDCounter++;
return figure;
}
//-----WALL OBJECT-----//
//Size of a wall
var WALLWIDTH = 80;
var WALLCOLOR = [ 116, 18, 229, 255 ];
var WALLCOLORDARK = [ 39, 7, 76, 255 ];
function makeWall( wx, wy )
{
var wall = { x: wx, y: wy, pattern: makePattern() };
return wall;
}
//-----LEVEL OBJECT-----//
//Add a row to the level. The parameters indicate which side
function levelAddRow( xRef, yRef )
{
//Variables to track whether the new row is an empty row
//and whether it has intersected an existing corridor
var before = false;
var after = false;
var passed = false;
var justPassed = false;
//Left Side
if( xRef == 1 )
{
//Clear out old row on opposite side
this.walls.unshift( [] );
this.walls.splice( this.walls.length - 1, 1 );
//Decide whether the new row is empty or a turning corridor
if( random() < 0.17 ) before = true;
else if( random() < 0.204 ) after = true;
else if( random() < 0.2572 )
{
before = true;
after = true;
}
//There can't be two empty rows next to each other
for( var i = 0; i < this.walls[1].length-2; i++ )
{
if( this.walls[1][i] == 0 & this.walls[1][i+1] == 0 )
{
before = false;
after = false;
}
}
//Generate the row
for( var i = 0; i < this.walls[1].length; i++ )
{
//Check if the row intersects a corridor
if( this.walls[1][i] == 0 )
{
passed = true;
justPassed = true;
}
//Generate a wall unless this row is empty or blocking a corridor
if( ( this.walls[1][i] == 0 & i != 0 && this.walls[1][i-1] != 0 &&
i != this.walls[1].length - 1 && this.walls[1][i+1] != 0 ) ||
( before && ( !passed || justPassed ) ) || ( after && passed ))
{
this.walls[0][i] = 0;
if( figureCounter == FIGUREFREQ - 1 )
this.figures.push( makeFigure( -1 * WALLWIDTH,
(i - 1) * WALLWIDTH ) );
figureCounter = (figureCounter + 1) % FIGUREFREQ;
}
else this.walls[0][i] = makeWall( -1 * WALLWIDTH,
(i - 1) * WALLWIDTH );
justPassed = false;
}
}
//Right Side
if( xRef == -1 )
{
//Clear out old row on opposite side
this.walls.push( [] );
this.walls.shift( 1 );
//Decide whether the new row is empty or a turning corridor
if( random() < 0.17 ) before = true;
else if( random() < 0.204 ) after = true;
else if( random() < 0.2572 )
{
before = true;
after = true;
}
//There can't be two empty rows next to each other
for( var i = 0; i < this.walls[1].length-2; i++ )
{
if( this.walls[this.walls.length-2][i] == 0
& this.walls[this.walls.length-2][i+1] == 0 )
{
before = false;
after = false;
}
}
//Generate the row
for( var i = 0; i < this.walls[this.walls.length-2].length; i++ )
{
//Check if the row intersects a corridor
if( this.walls[this.walls.length-2][i] == 0 )
{
passed = true;
justPassed = true;
}
//Generate a wall unless this row is empty or blocking a corridor
if( ( this.walls[this.walls.length-2][i] == 0 & i != 0 &&
this.walls[this.walls.length-2][i-1] != 0 &&
i != this.walls[this.walls.length-2].length - 1 &&
this.walls[this.walls.length-2][i+1] != 0 ) ||
( before && (!passed || justPassed) ) || ( after && passed ) )
{
this.walls[this.walls.length-1][i] = 0;
if( figureCounter == FIGUREFREQ - 1 )
this.figures.push( makeFigure( (this.walls.length-2)
* WALLWIDTH,
(i-1) * WALLWIDTH ) );
figureCounter = (figureCounter + 1) % FIGUREFREQ;
}
else this.walls[this.walls.length-1][i] =
makeWall( (this.walls.length-2)
* WALLWIDTH, (i-1) * WALLWIDTH );
justPassed = false;
}
}
//Top
if( yRef == 1 )
{
//Clear out old row on opposite side
for( i = 0; i < this.walls.length; i++ )
{
this.walls[i].unshift( -1 );
this.walls[i].splice( this.walls[i].length - 1, 1 );
}
//Decide whether the new row is empty or a turning corridor
if( random() < 0.17 ) before = true;
else if( random() < 0.204 ) after = true;
else if( random() < 0.2572 )
{
before = true;
after = true;
}
//There can't be two empty rows next to each other
for( var i = 0; i < this.walls.length-2; i++ )
{
if( this.walls[i][1] == 0 & this.walls[i+1][1] == 0 )
{
before = false;
after = false;
}
}
//Generate the row
for( var i = 0; i < this.walls.length; i++ )
{
//Check if the row intersects a corridor
if( this.walls[i][1] == 0 )
{
passed = true;
justPassed = true;
}
//Generate a wall unless this row is empty or blocking a corridor
if( ( this.walls[i][1] == 0 & i != 0 && this.walls[i-1][1] != 0
&& i != this.walls.length - 1
&& this.walls[i+1][1] != 0 )
|| (before && (!passed || justPassed)) || (after && passed))
{
this.walls[i][0] = 0;
if( figureCounter == FIGUREFREQ - 1 )
this.figures.push( makeFigure( (i-1) * WALLWIDTH,
-1 * WALLWIDTH ) );
figureCounter = (figureCounter + 1) % FIGUREFREQ;
}
else
this.walls[i][0] = makeWall((i-1) * WALLWIDTH, -1 * WALLWIDTH);
justPassed = false;
}
}
//Bottom
if( yRef == -1 )
{
//Clear out old row on opposite side
for( i = 0; i < this.walls.length; i++ )
{
this.walls[i].push( -1 );
this.walls[i].shift( 1 );
}
//Decide whether the new row is empty or a turning corridor
if( random() < 0.17 ) before = true;
else if( random() < 0.204 ) after = true;
else if( random() < 0.2572 )
{
before = true;
after = true;
}
//There can't be two empty rows next to each other
for( var i = 0; i < this.walls.length-2; i++ )
{
if( this.walls[i][this.walls.length-2] == 0
& this.walls[i+1][this.walls.length-2] == 0 )
{
before = false;
after = false;
}
}
//Generate the row
for( var i = 0; i < this.walls.length; i++ )
{
//Check if the row intersects a corridor
if( this.walls[i][this.walls[0].length-2] == 0 )
{
passed = true;
justPassed = true;
}
//Generate a wall unless this row is empty or blocking a corridor
if( ( this.walls[i][this.walls[0].length-2] == 0 & i != 0
&& this.walls[i-1][this.walls[0].length-2] != 0
&& i != this.walls.length - 1
&& this.walls[i+1][this.walls[0].length-2] != 0 )
|| (before && (!passed || justPassed)) || (after && passed))
{
this.walls[i][this.walls[0].length-1] = 0;
if( figureCounter == FIGUREFREQ - 1 )
this.figures.push( makeFigure( (i-1) * WALLWIDTH,
(this.walls[0].length-2) * WALLWIDTH ) );
figureCounter = (figureCounter + 1) % FIGUREFREQ;
}
else
this.walls[i][this.walls[0].length-1] =
makeWall( (i-1) * WALLWIDTH,
(this.walls[0].length-2) * WALLWIDTH );
justPassed = false;
}
}
}
//Update the level, moving objects inside and adding new rows if needed
function levelStep()
{
//If the offset for the walls is greater than the width of a wall,
//Shift the array of walls and add a new row
if( abs( this.xOffset ) >= WALLWIDTH )
{
//Incorporate offset into walls' basic x-positions
for( var j = 0; j < this.walls.length; j++ )
{
for( var k = 0; k < this.walls[j].length; k++ )
{
if( this.xOffset > 0 )
{
this.walls[j][k].x += WALLWIDTH;
}
if( this.xOffset < 0 )
{
this.walls[j][k].x -= WALLWIDTH;
}
}
}
//Incorporate offset into figures' basic x-positions
for( var j = 0; j < this.figures.length; j++ )
{
if( this.xOffset > 0 )
{
this.figures[j].x += WALLWIDTH;
}
if( this.xOffset < 0 )
{
this.figures[j].x -= WALLWIDTH;
}
//Remove figures that are off the screen
if( this.figures[j].x > width + FIGUREWIDTH / 2
|| this.figures[j].x < 0 - FIGUREWIDTH / 2 )
{
this.figures.splice( j, 1 );
j--;
}
}
//Reset the offset and add a new row
if( this.xOffset > 0 )
{
this.xOffset -= WALLWIDTH;
this.addRow( 1, 0 );
}
if( this.xOffset < 0 )
{
this.xOffset += WALLWIDTH;
this.addRow( -1, 0 );
}
}
if( abs( this.yOffset ) >= WALLWIDTH )
{
//Incorporate offset into walls' basic y-positions
for( var j = 0; j < this.walls.length; j++ )
{
for( var k = 0; k < this.walls[j].length; k++ )
{
if( this.yOffset > 0 )
{
this.walls[j][k].y += WALLWIDTH;
}
if( this.yOffset < 0 )
{
this.walls[j][k].y -= WALLWIDTH;
}
}
}
//Incorporate offset into figures' basic y-positions
for( var j = 0; j < this.figures.length; j++ )
{
if( this.yOffset > 0 )
{
this.figures[j].y += WALLWIDTH;
}
if( this.yOffset < 0 )
{
this.figures[j].y -= WALLWIDTH;
}
//Remove figures that are off the screen
if( this.figures[j].y > height + FIGUREWIDTH / 2
|| this.figures[j].y < 0 - FIGUREWIDTH / 2 )
{
this.figures.splice( j, 1 );
j--;
}
}
//Reset the offset and add a new row
if( this.yOffset > 0 )
{
this.yOffset -= WALLWIDTH;
this.addRow( 0, 1 );
}
if( this.yOffset < 0 )
{
this.yOffset += WALLWIDTH;
this.addRow( 0, -1 );
}
}
}
//Checks if a square at x,y with size size would collide with the wall
//at index a,b of the array of walls
function levelWallCollision( x, y, size, a, b )
{
var wall = this.walls[a][b];
if( wall == 0 ) return false;
return abs( x - ( wall.x + this.xOffset ) ) < size / 2 + WALLWIDTH / 2
& abs( y - ( wall.y + this.yOffset ) ) < size / 2 + WALLWIDTH / 2;
}
//Check collision for all the walls
function levelCollisionSearch( x, y, size )
{
for( i = 0; i < this.walls.length; i++ )
{
for( j = 0; j < this.walls[i].length; j++ )
{
if( this.wallCollision( x, y, size, i, j ) ) return true;
}
}
return false;
}
//Draw the wall at index a,b of the wall array
function levelDrawWall( a, b )
{
var wall = this.walls[a][b];
if( wall == 0 ) return;
push();
stroke( WALLCOLORDARK );
fill( WALLCOLOR );
rect( wall.x + this.xOffset, wall.y + this.yOffset, WALLWIDTH, WALLWIDTH );
wall.pattern.draw( wall.x + this.xOffset, wall.y + this.yOffset );
pop();
}
//Checks if a square at x,y with size size would collide with a figure
//at index a of the figure array
function levelFigureCollision( x, y, size, a )
{
if( a >= this.figures.length ) return false;
var figure = this.figures[a];
return abs( x - ( figure.x + this.xOffset ) ) < size / 2 + FIGUREWIDTH / 2
& abs( y - ( figure.y + this.yOffset ) )
< size / 2 + FIGUREWIDTH / 2;
}
//Check collision for all the figures. If found, returns the index of
//the colliding figure in the figure array. If not, returns -1.
function levelFigureCollisionSearch( x, y, size )
{
for( i = 0; i < this.figures.length; i++ )
{
if( this.figureCollision( x, y, size, i ) ) return i;
}
return -1;
}
//Draw the figure at index a of the figure array
function levelDrawFigure( a )
{
var figure = this.figures[a];
if( figure == 0 ) return;
push();
stroke( 0 );
fill( figure.figureColor );
ellipse( figure.x + this.xOffset, figure.y + this.yOffset,
FIGUREWIDTH, FIGUREWIDTH );
pop();
}
//Draw all the walls and figures
function levelDraw()
{
for( i = 0; i < this.walls.length; i++ )
{
for( j = 0; j < this.walls[i].length; j++ )
{
this.drawWall( i, j );
}
}
for( i = 0; i < this.figures.length; i++ )
{
this.drawFigure( i );
}
}
//Make a level, which contains arrays of walls and figures as well as a shared
//x and y offet which applies to every object in the level
function makeLevel()
{
var wallsArray = [];
var figuresArray = [];
for( i = 0; (i - 1) * WALLWIDTH <= width + WALLWIDTH; i++ )
{
wallsArray.push( [] );
for( j = 0; (j - 1) * WALLWIDTH <= height + WALLWIDTH; j++ )
{
if( i == 4 || j == 4 ) wallsArray[i].push( 0 );
else
wallsArray[i].push( makeWall( (i - 1) * WALLWIDTH,
(j - 1) * WALLWIDTH ) );
}
}
level = { walls: wallsArray, figures: figuresArray, xOffset: 0, yOffset: 0,
draw: levelDraw, drawWall: levelDrawWall,
wallCollision: levelWallCollision,
collisionSearch: levelCollisionSearch,
step: levelStep, addRow: levelAddRow,
drawFigure: levelDrawFigure,
figureCollision: levelFigureCollision,
figureCollisionSearch: levelFigureCollisionSearch };
return level;
}
//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Pattern object for wall blocks
var DOTSIZE = 3;
var colors = [ [66,134,234,255], [23,216,213,255],
[23,216,236,255], [68,216,23,255], [228,242,42,255] ];
function makePattern() {
var angle;
var newPattern={c: random(colors), arms: int( random( 4 ) ) + 2,
a: random(2*PI), draw: drawPattern, dotPositionArray: [] };
for( var i = 0; i < newPattern.arms; i++ )
{
for( var j = 0; j < WALLWIDTH / 2 - 5; j+= DOTSIZE * 2 )
{
angle = newPattern.a + i * (2 * PI / newPattern.arms);
newPattern.dotPositionArray.push( j * cos( angle ) +
( sin( j ) * 20 * cos( angle + PI / 2 ) ) );
newPattern.dotPositionArray.push( j * sin( angle ) +
( sin( j ) * 20 * sin( angle + PI / 2 ) ) );
}
}
return newPattern;
}
function drawPattern( x, y ){
fill(this.c)
push();
noStroke();
var currentX;
var currentY;
for( var i = 0; i < this.dotPositionArray.length - 1; i+= 2 )
{
ellipse( x + this.dotPositionArray[i], y + this.dotPositionArray[i+1],
DOTSIZE, DOTSIZE );
}
pop();
}
//Anna Boyle
//Section D
//aboyle@andrew.cmu.edu
//Quote generator
var abstractNouns = ["Rebellion", "Curiosity", "Jealousy", "Friendship",
"Family", "Evil", "Life", "Hope", "Grace", "Love", "Faith", "Opportunity",
"Dedication", "Insanity", "Fortune", "Luck", "Hatred", "Knowledge", "Pain",
"Heaven"];
var inspireNouns = ["rainbow", "cloud", "light", "star", "candle", "child",
"dream", "building", "hero", "breeze", "eye", "moon", "snowflake", "apple",
"tree", "flower", "butterfly", "mirror", "door", "heart"];
var inspireNounsPlural = ["rainbows", "clouds", "lights", "stars", "candles",
"children", "kisses", "buildings", "hands", "brothers", "sisters",
"snowflakes", "dreams", "apples", "trees", "flowers", "butterflies", "mirrors",
"doors", "hearts"];
var strangeNouns=["peach cobbler", "deodorant", "used tissue", "conch shell",
"toaster", "pasta strainer", "blade of grass", "grandma's house", "unicycle",
"weed whacker", "shampoo bottle", "corpse", "snickerdoodle",
"ten gallon hat", "toupee", "colony of termites", "mother-in-law",
"sexy firemen calendar", "underground bunker", "angry baboon"];
var strangeNounsPlural = ["alien invasions", "clowns", "podiatrists",
"belly dancers", "cacti", "voodoo dolls", "raspberries", "dust bunnies",
"distant relatives", "kentucky fried chicken", "rotten eggs", "nudists",
"nunchuks", "toenail clippings", "rocket scientists", "green beans", "nuns",
"croissants", "drunk ballerinas", "shoelaces" ];
var inspireVerbs= ["flies", "moves", "shines", "waits", "stands", "goes",
"sleeps", "thinks", "cries", "laughs", "yells", "watches", "jumps"];
var inspireVerbsObj = ["hold", "hug", "love", "hate", "grab", "accept",
"support", "look at", "want", "sacrifice", "kiss", "pray for", "abandon"];
var inspireVerbsGerund= ["flying", "moving", "doing", "waiting", "standing",
"going", "saying", "thinking", "crying", "laughing", "yelling", "watching",
"jumping"];
var inspireVerbsObjGerund = ["holding", "hugging", "loving", "hating",
"grabbing", "accepting", "supporting", "seeing", "wanting", "finding",
"kissing", "praying for", "abandoning"];
var strangeVerbs=["dances", "dies", "melts", "yodels", "sneezes", "does yoga",
"crawls", "beatboxes", "undresses", "vomits", "whistles", "rollerblades",
"explodes"];
var strangeVerbsObj=["stab", "fight", "smack", "bury", "kick", "exorcise",
"kidnap", "high five", "sniff", "smuggle", "tickle", "cuddle", "nibble"];
var strangeVerbsGerund=["dancing", "dying", "melting", "yodeling", "sneezing",
"doing yoga","crawling", "sleeping", "undressing", "vomiting", "whistling",
"rollerblading", "exploding"];
var strangeVerbsObjGerund=["stabbing", "fighting", "smacking", "burying",
"kicking", "exorcising", "kidnapping", "high fiving", "sniffing", "smuggling",
"tickling", "cuddling", "nibbling"];
var locationWords=["behind", "in front of", "next to", "inside of", "below",
"on top of", "above", "under", "among", "beside", "over", "far away from",
"underneath"];
var comparison=["darker", "sadder", "bigger", "smaller", "harder", "softer",
"better", "worse", "faster", "slower", "stronger", "weaker", "happier",
"drunker", "older", "younger", "smarter", "dumber", "hotter", "colder"];
var personQuote=["Albert Einstein", "Mahatma Gandhi", "Oprah Winfrey",
"George Washington", "Nelson Mandela", "Jesus Christ", "Benjamin Franklin",
"Plato", "Mother Teresa", "My mom", "Beyonce", "Martin Luther King Jr.",
"Santa Claus"]
//variable for the quote templates
var whichQuote;
/*nCh=nineteen choices, tCh=twelve choices
There are multiple variables to prevent parts of speech with same amount of
choices don't get constantly paired with each other */
var nCh1;
var nCh2;
var nCh3;
var nCh4;
var tCh1;
var tCh2;
var tCh3;
var tCh4;
//Variables related to drawing the speech bubble
var txt;
var txtH;
var bubbleHeight;
var singleLineHeight;
var bubbleX = 0;
var bubbleY = 0;
var drawBubble = false;
var bubbleID = -1;
var inspiroMeter=0;
function updateBubble(){
//randomizes which number in the array will be chosen for the parts of speech
nCh1=int(random(20));
nCh2=int(random(20));
nCh3=int(random(20));
nCh4=int(random(20));
tCh1=int(random(13));
tCh2=int(random(13));
tCh3=int(random(13));
tCh4=int(random(13));
//randomzies which quote template will be chosen
whichQuote=int(random(14));
inspiroMeter=inspiroMeter+20;
}
//Chooses which quote template will be chosen based on the random number
//between 0 and 13
function printQuote( num )
{
switch(num)
{
case 0:
worthTwo();
break;
case 1:
tryToBe();
break;
case 2:
whenYouHave();
break;
case 3:
judgeEach();
break;
case 4:
ifYouMiss();
break;
case 5:
theBest();
break;
case 6:
duringOurMoments();
break;
case 7:
letUs();
break;
case 8:
palesInComparison();
break;
case 9:
haveSeen();
break;
case 10:
inSeason();
break;
case 11:
combination();
break;
case 12:
onlyICan();
break;
case 13:
jokeQuote();
break;
}
}
//Below are all the quote template functions
//bubbleHeight changes the size of bubble when there are different amounts of text
function tryToBe(){
text("Try to be a "+inspireNouns[nCh1]+" in someone's "
+strangeNouns[nCh2], txt, singleLineHeight);
bubbleHeight=75;
}
function worthTwo(){
text("One "+inspireNouns[nCh1]+" is worth two "+
strangeNounsPlural[nCh2], txt, singleLineHeight);
bubbleHeight=75;
}
function whenYouHave(){
text("When you have a "+strangeNouns[nCh1]+", you've got to ", txt, txtH);
text(inspireVerbsObj[tCh1]+" it and never "+strangeVerbsObj[tCh2]+
" it", txt, txtH+25);
bubbleHeight=130;
}
function judgeEach(){
text("Don't judge each day by the "+inspireNounsPlural[nCh1],
txt, txtH);
text(" you "+inspireVerbsObj[tCh1]+", but by the "+strangeNounsPlural[nCh1]
+" you "+strangeVerbsObj[tCh1], txt, txtH+25);
bubbleHeight=130;
}
function ifYouMiss(){
text("Shoot for the "+inspireNouns[nCh1]+", and if you miss", txt, txtH);
text(" you will still be "+locationWords[tCh1]+" the "
+strangeNounsPlural[nCh2], txt, txtH+25);
bubbleHeight=130;
}
function theBest(){
text("The best preparation for tomorrow is", txt, txtH);
text(strangeVerbsObjGerund[tCh1]+" your "+
strangeNouns[nCh1]+" today", txt, txtH+25);
bubbleHeight=130;
}
function duringOurMoments(){
text("It is during our "+comparison[nCh1]+" moments that we must", txt, txtH);
text("focus to "+strangeVerbsObj[tCh1]+" the "+
strangeNounsPlural[nCh2], txt, txtH+25);
bubbleHeight=130;
}
function letUs(){
text("Let us sacrifice our "+inspireNounsPlural[nCh1]
+" so that", txt, txtH);
text("our children can "+strangeVerbsObj[tCh1]+" a "+
comparison[nCh2]+" "+strangeNouns[nCh3], txt, txtH+25);
bubbleHeight=130;
}
function palesInComparison(){
text("What "+inspireVerbs[tCh1]+" behind you and what "+
inspireVerbs[tCh2]+" in front of you,", txt, txtH);
text("pales in comparison to what "+strangeVerbs[tCh3]+" "+
locationWords[tCh4]+" you", txt, txtH+25)
bubbleHeight=130;
}
function haveSeen(){
text("If I have seen further than others, it is", txt, txtH);
text("by "+strangeVerbsGerund[tCh1]+" "+locationWords[tCh2]+" "
+strangeNounsPlural[nCh1], txt, txtH+25)
bubbleHeight=130;
}
function inSeason(){
text(abstractNouns[nCh1]+" is a fruit in season at all times,", txt, txtH);
text("and within reach of every "+strangeNouns[nCh2], txt, txtH+25);
bubbleHeight=130;
}
function combination(){
text(abstractNouns[nCh1]+" and "+strangeNounsPlural[nCh2]+
" are a powerful combination", txt, singleLineHeight);
bubbleHeight=75;
}
function onlyICan(){
text("Only you can "+strangeVerbsObj[tCh1]+" your "+strangeNouns[nCh1]+".",
txt, txtH);
text("No one else can do it for you.", txt, txtH+25);
bubbleHeight=130;
}
function jokeQuote(){
text("This project definitely deserves an A", txt, txtH);
text("-- "+personQuote[tCh1], txt+15, txtH+25);
bubbleHeight=130;
}
For our final project, we made an Inspirational Quote Maze. The player moves a small square around in a randomly generated maze using the WASD keys. The dots in the maze tell the player inspirational quotes when they collide. For every quote the character receives, they gain a couple points in their “InspiroMeter.” Once they hear enough quotes, the game is over and they are congratulated for being inspired.
Thomas mainly worked in the wall, player, and patterns files. He made the player movements and randomly generated the maze and the dots found within. He made it so the player can’t receive a different quote from the same dot twice in a row. He also created patterns to make the blocks look more exciting.
Anna mainly worked in the main and quotes files. She decided on the quote templates, made arrays filled with parts of speech, and randomized both of them for unique quotes. She made the speech bubble that appears when a character is talking. She also made the “InspiroMeter” and made the game end after a certain number of quotes.
Overall, we think that our project turned out well and we are proud of our efforts!
Audio embedded, please turn up volume. Vimeo recording also included at bottom.
In our final project, we made a music video and explored the relationship between geometric motion and rhythm. We divided the video into four sections of movements, interacting with the rhythm and mood of the music.
My final project is a playable viola that creates art in the background based on the notes played and length of the notes played. I drew the viola utilizing arcs, triangles, lines, and other 2D shapes. Then I added sounds to the notes played and ellipses that move with the music.
Each note is connected to a key, that when pressed, plays a note and a visual representation of the sound as a green dot showing the placement of the note on the fingerboard. In addition, there are 20 uniquely colored balls hiding behind the viola that are connected to 20 notes that can be played with the keyboard. Each ball will move at its individual vertical and horizontal velocities when the key is pressed. When the key is lifted, the sound will stop and ball will stop in place. When the performer is finished playing, it will leave a pattern of balls in the background. With the end of each unique composition, the background will look unique, linking each unique piece of music with a unique piece of art.
Note: WordPress does not display the audio correctly, so here is a zip file with the audio files and functioning code. In order to run this code, you access it in the terminal and type “python -m SimpleHTTPServer” and the code will run properly. Above is a screenshot of the completely functioning code.
The purpose of this project is to gain different interpretations about the current events by giving the users the opportunity to draw or write about the issues that are presented to them. The content that gets presented is related to current events and political status. Furthermore, I would like to develop this project so that this website can exist in the online world with different interpretations and with opinions that can reside and see different opinions visually. This would be an anonymous participation by the public so we can get honest reviews about the political atmosphere around us and what people are thinking about.