The video shows how the program should work – words said include “wind” “phone” “black” “yellow” “sock” “shoe” “roof” “ceiling” “cold” “warm” “wind” “water”.
I was trying to create some kind of fuzzy text or spoken word visualizer/analyzer, in a compositional landscape, using the p5.Speech library.
The width of the grayscale boxes is according to the letter of the word.
The morse code is a translation of the letters.
The text is a fuzzy recognition of the words, stretches according to the amplitude.
The ellipses are a representation of amplitude.
The voice recognition does not work too well, but overall I’m satisfied with the effect.
The project requires a local server to run due to the microphone components.
Instructions:
1. Download and extract FINAL PROJECT
2. Install node js
3. type npm install -g http-server into node terminal and enter
4. cd the extracted folder and enter
5. type http-server -c-1 and enter
6. node terminal will give you links
7. enter the link into a browser
8. file should run!
https://helenxwu.github.io/ –> link to game
https://drive.google.com/a/andrew.cmu.edu/file/d/1NQmUsm_kBniAq7vku2QIYw7QzBkgUOP_/view?usp=sharing –> link to zip file
How to run zip:
1) download file
2) move to desktop
3) open zip folder
4) On mac– open terminal (command+space and search “terminal”)
5) type in “python -m SimpleHTTPServer 8000”
6) go to browser–type in localhost:8000 where the URL would usually go
7) find desktop listing and click on it
8) find downloaded folder and click on it
9) file will load!
For our final project, Tiffany and I made a dance dance revolution game to the Mii remix. We delved into an entirely new library (the p5js sound extension) and learned a lot about different techniques for signal processing. For the main sound visualizer, we used Fast Fourier Transform algorithm (FFT) to sample the music files’ signals over a period of time, and divided its frequency components to create the bouncing colors that react and move according to note and rhythm.
Additionally, we mapped the volume controls to create new objects under an object function, to randomly generate 4 different types of arrows. We then set a range for the function to work under so the score counter could add points. We also created a start screen and end screen for the game under two separate functions.
]]>// Tiffany Lai (thlai) & Helen Wu (hdw)
// 15-104, Section A
// Project 12 - Final
//var font; // variable for font
var music; // variable for music
var fft; // variable for p5.FFT library
var amp; // variable for p5.Amplitude library
var leftArrows = [];
var opacity = 255;
var scoreCount = 0;
var playMode = 0;
function preload() {
//font = loadFont('font/slkscr.ttf'); // load font 'silk screen'
music = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/music-2.mp3"); // load music
}
function setup() {
createCanvas(480, 480);
fft = new p5.FFT(0.9, 256); // load p5.FFT library
amp = new p5.Amplitude(); // load p5.Amplitude
}
function draw() {
background(22, 35, 42);
circleBeat(); // background sound visualization
displayTriangles(); // display top triangles
moveTriangles(); // top triangles go down when pressing specific keys
generateArrows();
for (var i = 0; i < leftArrows.length; i++) {
leftArrows[i].move();
leftArrows[i].render();
if (leftArrows[i].y < -500) {
leftArrows.shift();
}
}
scoreCounter(); // score counter
endScreen();
startScreen();
}
//start screen
function startScreen() {
fill(255, 56, 115, opacity);
rect(0,0,width,height);
textSize(12);
if (frameCount%2 == 0){
fill(255,opacity);
//textFont(font);
textAlign(CENTER);
textSize(12);
text("CLICK TO PLAY", width/2, height/2);
}
}
//music plays
function mouseClicked() {
displayTriangles(); // display main triangles
opacity = 0;
moveTriangles();
if (playMode == 0) {
music.play();
playMode = 'sustain';
} else {
playMode = 0;
music.stop();
}
}
// background sound visualization
function circleBeat() {
var spectrum = fft.analyze(); // analyze music spectrum
// drawing the circle
push();
translate(width/2, height/2);
for (var i = 0; i < spectrum.length; i++) {
var angle = map(i, 0, spectrum.length, 0, 360); // map spectrum to degrees
var spec = spectrum[i];
var r = 2 * map(spec, 0, 256, 20, 100);
var x = r * cos(angle);
var y = r * sin(angle);
fill(200, i*3, i*5); // fill with gradient
noStroke();
ellipse(x, y, 3, 3); // tiny center circles
}
pop();
}
//==========CREATE TOP TRIANGLES ==========//
// make triangles object
function makeTriangles (l, d, u, r) {
var triangles = {
left: l,
down: d,
up: u,
right: r,
display: displayTriangles,
move: moveTriangles
}
return triangles;
}
// display triangles
function displayTriangles() {
fill(255);
noStroke();
// draw four anchor triangles
triangle(115, this.l+66, 154, this.l+88, 154, this.l+44); // left
triangle(185, this.d+53, 207, this.d+92, 229, this.d+53); // down
triangle(272, this.u+40, 250, this.u+79, 295, this.u+79); // up
triangle(325, this.r+44, 325, this.r+89, 364, this.r+66); // right
// draw 3D part of anchor triangles
fill(116, 136, 133);
quad(115, this.l+66, 154, this.l+88, 154, 93, 115, 71); // left
quad(250, this.u+79, 295, this.u+79, 295, 85, 250, 85); // up
fill(230, 160, 133);
quad(185, this.d+53, 185, 62, 207, 102, 207, this.d+92); // down (left)
quad(207, this.d+92, 207, 102, 229, 62, 229, this.d+53); // down (right)
quad(325, this.r+89, 325, 94, 364, 71, 364, this.r+66); // right
}
function moveTriangles(){
// move triangles down when you press specific arrow key
if (keyIsDown(LEFT_ARROW)) {
this.l = 3;
} else if (keyIsDown(DOWN_ARROW)) {
this.d = 5;
} else if (keyIsDown(UP_ARROW)) {
this.u = 4;
} else if (keyIsDown(RIGHT_ARROW)) {
this.r = 3;
} else {
this.l = 0;
this.d = 0;
this.u = 0;
this.r = 0;
}
}
//========== GENERATE ARROWS ==========//
function makeArrows(aX, aY, spd, rot) {
var arrows = {
x: aX,
y: aY,
speed: spd,
rotateArrow: rot,
move: moveArrows,
render: displayArrows,
generate: generateArrows
}
return arrows;
}
function displayArrows() {
push();
stroke(0, 200, 200);
strokeWeight(5);
noFill();
translate(this.x, this.y);
rotate(this.rotateArrow);
triangle(115, 66, 154, 88, 154, 44);
pop();
//triangle(this.x+115, this.y+66, this.x+154, this.y+88, this.x+154, this.y+44);
}
function moveArrows() { // speed of clouds
this.y -= this.speed;
}
function generateArrows() {
var vol = amp.getLevel();
if ((vol > 0.33 & vol < 0.34) || (vol > 0.18 && vol < 0.2) || (vol > 0.03 && vol < 0.032)) {
var randomizer = int(random(0,4)); // if the volume level is over 0.3
if(randomizer == 0){
var newArrow = new makeArrows(0, 420, 4, 0); // make new arrow object
leftArrows.push(newArrow);
}
if (randomizer == 1) {
var newArrow = new makeArrows(140, 840, 4, 3/2*PI); // make new arrow object
leftArrows.push(newArrow);
}
if (randomizer == 2) {
var newArrow = new makeArrows(340, 420, 4, 1/2*PI); // make new arrow object
leftArrows.push(newArrow);
}
if (randomizer == 3) {
var newArrow = new makeArrows(480, 840, 4, PI); // make new arrow object
leftArrows.push(newArrow);
}
}
}
function endScreen() {
if (music.isPlaying() ) {
var endOpacity = 0;
} else {fill(255, 56, 115, endOpacity);
var endOpacity = 255;
rect(0, 0, width, height);
textSize(12);
if (frameCount%2 == 0){
fill(255,endOpacity);
textFont(font);
textAlign(CENTER);
textSize(12);
text("GAME OVER", width/2, height/2);
text("SCORE: " + scoreCount, width/2, height/2+20);
}
}
}
// ========== COUNTER ========== //
function scoreCounter() {
// draw borders on screen
noStroke();
fill(110, 120, 120);
rect(0, 0, width, 7);
rect(0, 0, 7, height);
rect(0, height-7, width, 7);
rect(width-7, 0, 7, height);
fill(116, 136, 133);
quad(182, height, 187, height-25, 292, height-25, 297, height);
fill(255);
text("SCORE: " + scoreCount, width/2, 472);
for (var i = 0; i < leftArrows.length; i++) {
if((keyIsDown(LEFT_ARROW))) {
if (leftArrows[i].y > -10 & leftArrows[i].y < 30 && (leftArrows[i].x ==0)) {
scoreCount = scoreCount + 10;
leftArrows.shift();
}
}
if(keyIsDown(DOWN_ARROW)){
if (leftArrows[i].y > 180 & leftArrows[i].y < 220 && (leftArrows[i].x == 140)) {
scoreCount = scoreCount + 10;
leftArrows.shift();
}
}
if(keyIsDown(UP_ARROW)){
if (leftArrows[i].y > -90 & leftArrows[i].y < -50 && (leftArrows[i].x == 340)) {
scoreCount = scoreCount + 10;
leftArrows.shift();
}
}
if(keyIsDown(RIGHT_ARROW)){
if (leftArrows[i].y > 110 & leftArrows[i].y < 150 && (leftArrows[i].x == 480)) {
scoreCount = scoreCount + 10;
leftArrows.shift();
}
}
}
}
]]>//monica huang
//monicah1
//final project
var drops = [];
var terrain = [];
var stars = [];
var fireworks = [];
var cols, rows;
var scl = 90;
var w = 500;
var h = 500;
var flying = 0;
var gravity;
var speed;
var particles = [];
var flowfield;
var fr;
var inc = 0.1;
var zoff = 0;
var sound;
function setup() {
createCanvas(1100, 500, WEBGL);
speed = map(mouseX, 2, width, 5, 2);
//throw off lines
for (var i = 0; i < 10; i++) {
drops[i] = new Drop();
}
//colors
colorMode(HSB, 255);
cols = floor(width / scl);
rows = floor(height / scl);
fr = createP('');
flowfield = new Array(cols * rows);
for (var i = 0; i < 10; i++) {
particles[i] = new Particle();
}
//flowing plain
cols = w / scl;
rows = h/ scl;
for (var x = 0; x < cols; x++) {
terrain[x] = [];
for (var y = 0; y < rows; y++) {
terrain[x][y] = 0;
}
}
}
function draw() {
background(125,255,0);
speed = map(mouseX, 0, width, 0, 5);
//throw off lines
for (var i = 0; i < drops.length; i++) {
drops[i].fall();
drops[i].show();
}
//colors
var yoff = 0;
for (var y = 0; y < rows; y++) {
var xoff = 0;
for (var x = 0; x < cols; x++) {
var index = x + y * cols;
var angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
var v = p5.Vector.fromAngle(angle);
v.setMag(1);
flowfield[index] = v;
xoff += inc;
stroke(0, 50,170);
}
yoff += inc;
zoff += 0.0003;
}
for (var i = 0; i < particles.length; i++) {
particles[i].follow(flowfield);
particles[i].update();
particles[i].edges();
particles[i].show();
}
fr.html(floor(frameRate()));
//flowing plain
flying -= 0.1;
var yoff = flying;
for (var y = 0; y < rows; y++) {
var xoff = 0;
for (var x = 0; x < cols; x++) {
terrain[x][y] = map(noise(xoff, yoff), 0, 1, -100, 100);
xoff += 0.2;
}
yoff += 0.2;
}
translate(0, 50);
rotateX(-PI/3);
fill(0,0,0);
translate(-w/2, -h/2);
for (var y = 0; y < rows-1; y++) {
beginShape(TRIANGLE_STRIP);
for (var x = 0; x < cols; x++) {
vertex(x*scl, y*scl, terrain[x][y]);
vertex(x*scl, (y+1)*scl, terrain[x][y+1]);
}
endShape();
}
}
//---------------------------------------------------------------------------
// lines
function Drop() {
this.x = random(width*2);
this.y = random(-500, -500);
this.z = random(0, 10);
this.len = map(this.z, 0, 10, 0, 30);
this.yspeed = map(this.z, 0, 10, 1, 20);
this.fall = function() {
this.y = this.y + this.yspeed;
var grav = map(this.z, 0, 60, 0, 0.6);
this.yspeed = this.yspeed + grav;
if (this.y > height) {
this.y = random(-200, -200);
this.yspeed = map(this.z, 0, 20, 4, 10);
}
}
this.show = function() {
var thick = map(this.z, 0, 20, 1, 3);
strokeWeight(thick);
stroke(random(0,255), random(0,255), random(0,255));
line(this.x, this.y, this.x, this.y+this.len);
}
}
//colors
function Particle() {
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxspeed = 2;
this.h = 0;
this.prevPos = this.pos.copy();
this.update = function() {
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.follow = function(vectors) {
var x = floor(this.pos.x / scl);
var y = floor(this.pos.y / scl);
var index = x + y * cols;
var force = vectors[index];
this.applyForce(force);
}
this.applyForce = function(force) {
this.acc.add(force);
}
this.show = function() {
stroke(random(0,255), random(0,255), random(0,255));
this.h = this.h + 1;
if (this.h > 255) {
this.h = 0;
}
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function() {
this.prevPos.x = this.pos.x;
this.prevPos.y = this.pos.y;
}
this.edges = function() {
if (this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if (this.pos.x < 0) {
this.pos.x = width;
this.updatePrev();
}
if (this.pos.y > height) {
this.pos.y = 0;
this.updatePrev();
}
if (this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
I am inspired by space, speed, and motion in galaxy. I am interested in creating 3d dimensional space and motion with 2 dimensional lines and colors.
https://alpha.editor.p5js.org/shariwa/sketches/H16PfJF-G
Since this code has sounds, the WordPress account doesn’t display it properly. Above is a link to the p5.js alpha editor where you can properly view my code. Once at the website click the play button on the top left corner of the screen
My project looked at combining motion graphics and sounds. I wanted the graphics to work such that more was revealed as you moved around the canvas – everything is made out of two colours so as the mouse moves in the horizontal direction, you get to view more of the graphics as a differentiation is created between the background and the actual graphics.
I had an issue with running the local server on my laptop so I used the oscillation program from p5.js to get a sine curve amplitude and frequency to create a sound that my motion graphics responded to. The larger objects respond to the sound that is generated. The rippling, striped circle responds to the silence in between the beep noises. The white ellipse curve is its own thing that just renders what a traditional sine curve looks like.
When the canvas is clicked on, the noise stops and the motion graphics continue. To restart the noise you have to refresh the page.
^mouseX at at 0
^mouseX at maximum width
Instructions to run the file:
1)Download and unzip the file below
2) run a local server and access the file this way (it will not work otherwise unless you download the p5 editor and open it using the play button)
3) wait about 2 minutes before clicking the game to start. There are a lot of graphics so it takes a really long time to load so I would just keep clicking around the top of the screen after about 2 minutes until it loads and lets you play
4)refresh the page to restart if u lose and enjoy! Also don’t come too close to the edges of the screen.
Here is the embedded code just in case:
//Hannah Kim
//Section A
//hannahk2@andrew.cmu.edu
//Final Project
//variable for background image
var bg;
//variable for rain particles
var particles;
//variable for portal
var portalSprite;
//variable for random portal x position
var ran1;
//variable for random portal y position
var ran2;
//variable for spiders group
var spiders;
//arrays within array storing specific positions
//of spiders on top of lillypads
var spiderPos = [
[103, 242],
[155, 260],
[134, 292],
[160, 311],
[223, 290],
[207, 299],
[192, 304],
[200, 328],
[185, 322],
[193, 362],
[205, 347],
[220, 374],
[172, 377],
[193, 405],
[166, 399],
[240, 422],
[215, 428],
[182, 430],
[140, 410],
[157, 339],
[151, 362],
[130, 315],
[113, 347],
[229, 413],
[125, 377],
[101, 389],
[82, 356],
[37, 397],
[110, 429],
[88, 440],
[223, 459],
[176, 468],
[197, 488],
[275, 450],
[261, 436],
[220, 476],
[236, 518],
[191, 536],
[146, 546],
[160, 518],
[92, 480],
[260, 543],
[236, 582],
[269, 284],
[255, 289],
[252, 313],
[229, 314],
[251, 334],
[254, 378],
[281, 384],
[295, 271],
[303, 286],
[285, 300],
[289, 331],
[291, 352],
[311, 338],
[322, 318],
[320, 292],
[333, 340],
[321, 380],
[346, 361],
[332, 403],
[345, 429],
[308, 428],
[334, 449],
[377, 415],
[373, 391],
[320, 492],
[312, 476],
[349, 484],
[345, 502],
[337, 548],
[318, 529],
[376, 510],
[406, 375],
[381, 352],
[361, 301],
[85, 539],
[54, 575],
[101, 610],
[396, 301],
[416, 317],
[398, 338],
[445, 325],
[436, 352],
[416, 397],
[387, 448],
[384, 481],
[457, 437],
[435, 484],
[470, 352],
[431, 555]
];
//sets normal game state with timer at 0
var gameState = "menu";
var timer = 0;
//preloads background image
function preload() {
bg = loadImage("assets/spiderbg.png");
}
function setup() {
createCanvas(500, 668);
//sets random values for x position of portal
ran1 = random(100, 400);
//sets random values for y position of portal
ran2 = random(550, 600);
//creates sprite for the portal at random position
//and assigns animation
portalSprite = createSprite(ran1, ran2);
portalSprite.addAnimation("normal", "assets/portal0000.png", "assets/portal0002.png")
//scales the portal to be smaller
portalSprite.scale = .2;
//slows down the frame rate of the animation
portalSprite.animation.frameDelay = 20;
//creates particle group for rain
particles = new Group();
//assign new sprites to groups
for (var i = 0; i < 100; i++) {
//puts all creation and initialization instructions in a
//premade function found at bottom of code
createParticle();
}
//creates sprite group for spiders
spiders = new Group();
//for loop to create all spiders at positions in position array
for (var i = 0; i < spiderPos.length; i++) {
//creates spider sprites at specified positions
var s = createSprite(spiderPos[i][0], spiderPos[i][1]);
//animation for spiders in normal state
s.addAnimation("playing", "assets/spider0000.png", "assets/spider0009.png");
//plays the spider animation starting at different frames
var f = floor(random(0, s.animation.getLastFrame()));
s.animation.changeFrame(f);
//animation for spiders when they're looking at you before game ends
s.addAnimation("looking", "assets/spider0010.png", "assets/spider0012.png");
//sets the circle around the spider which ends the game when touched
s.setCollider("circle", 0, 0, 90);
//increases the size of the spider as the y position increases
//by indexing into the position array and multiplying by decimal
var spiderSize = 0.04;
s.scale = spiderSize * .005 * (spiderPos[i][1]);
//trigger the looking function + looking animation when
//mouse goes over the spider collider
s.onMouseOver = function() {
//changes animation to looking animation
looking(spiders);
}
//add spider sprites
spiders.add(s);
}
}
//function for when you touch a spider and
//it looks at you and the game ends
function looking(g) {
if (gameState == "game") {
for (var i = 0; i < g.length; i++) {
var sp = g[i];
sp.changeAnimation("looking");
//delays frame rate of animation
sp.animation.frameDelay = 10;
}
gameState = "looking";
//adds timer to countdown to game over state
//after the looking animation is triggered
timer = 60;
}
}
function draw() {
background(255);
//sets up the menu state with text and background
if (gameState == "menu") {
s = "OH NO! You have fallen down a sewer and have been plunged into a fantastical realm. Reach the portal swiftly to get back to the human realm without coming into contact with the spiders. Good luck! Click anywhere to begin."
background(0)
textSize(30);
fill(156, 183, 226)
text(s, 10, 10, 400, 400);
s2 = "This fantasy realm, The Conjured Isles, is inhabited by hundred eyed spiders who are extremely wise. They usually pass their time playing in never ending rain. They live ontop of lillypads in the blood river. They are currently ruled by a mysterious creature that looms over the realm atop a black cloud, whom the people respect intensely."
textSize(20);
fill(156, 183, 226)
text(s2, 10, 450, 400, 600);
//on clicking on the screen the game starts + goes into "game" state
if (mouseIsPressed) {
gameState = "game";
}
}
//draw sprites if the game state changes from menu
if (gameState != "menu") {
drawSprites();
//counts down from timer once game state goes into "looking" and
//at 0 the game state changes to "gameOver"
if (gameState == "looking") {
timer--;
if (timer <= 0) {
gameState = "gameOver";
}
}
//sets up the game over state with text and background
if (gameState == "gameOver") {
background(0);
s3 = "You were seen and banished by the spiders before you could reach the human realm. Better luck next time!"
textSize(30);
fill(156, 183, 226)
text(s3, 10, 10, 400, 400);
//if game state is not "gameOver" display normal background
} else {
image(bg);
//if the mouse is within the bounds of the portal,
//change game state to won
if (gameState == "game" & mouseX < ran1 + 25 && mouseX > ran1 - 25 &&
mouseY < ran2 + 25 && mouseY > ran2 - 25) {
gameState = "won";
}
//if the mouse gets too close to the left and right side
//and the bottom side, (for cheaters), end game
if (gameState == "game" & mouseX < 10 || mouseX > width - 10 || mouseY > height - 10) {
gameState = "gameOver"
}
//sets up the won state with text and background
//removes sprites
if (gameState == "won") {
background(0);
s4 = "You reached successfully the portal and returned to the human realm! Congrats!"
textSize(30);
fill(156, 183, 226)
text(s4, 10, 10, 400, 400);
s.remove();
}
//code to draw the rain particles
for (var i = 0; i < particles.length; i++) {
//stores the particle in a temporary variable called p
var p = particles[i];
//scales it down
p.scale = 0.15;
//moves all the y positions of the particles down
//for rain falling effect
p.position.y += 10;
//wraps particle to the top when it reaches the bottom
if (p.position.y > height) {
p.position.y = -50;
}
}
//draw all sprites
drawSprites();
}
}
}
//function to create the rain particle
function createParticle() {
//creates a sprite at a random position
var newParticle = createSprite(random(0, width), random(0, height));
//assigns an animation
newParticle.addAnimation("falling", "assets/cloud.png");
//adds it to the particle group
particles.add(newParticle);
}
Here are screenshots of the game also:
^ the menu page
^the game in its normal state
^ the game when the player touches a spider
^ the game over state
^ the winning state
For this project I wanted to create a game based mostly on graphics, visuals, and backgrounds. I wanted to create a game where the player has to navigate through a tricky trap-like environment. The player has to avoid coming into contact with the inhabitants of an imaginary realm while hurrying to reach a portal to get back to the human realm. They have to navigate through a mob of spiders resting on top of lillypads without touching them and being seen. This project was really fun for me, despite having to code the positions of the spiders individually so that they would fit nicely on top of the lillypads that I chose. I really enjoyed making the background in particular, which I made for this project by painting first in watercolor, then scanning into photoshop and drawing ontop of it digitally. I also really enjoyed coming up with the narrative aspect of the project, and the world building.
]]>/*Jessica Nip
Section A
jknip@andrew.cmu.edu
Project-12
*/
//define global variables------------------------------------------------------
var x;
var y;
var dx;
var dy;
var current_block;
var old_blocks = [];
var blockw = 90;
var blockh = 70;
var clicked = false;
var score = 0;
var gameover = false;
var windowmargin = 10;
var start_speed;
var bground = ["https://i.imgur.com/gZ7wNWJ.png"];
var intro = "STACK THE HIGHEST TOWER.";
//colors
var darkblue;
var lightpink;
var lightred;
var grey;
var grey2;
var grey3;
var grey4;
var canvasw;
var canvash;
//---------------------------------------------------------------------------
function preload() {
//background skyline
bground = loadImage(bground[0]);
}
//---------------------------------------------------------------------------
function setup() {
//define initial canvas settings
createCanvas(350, 600);
x = width/2;
y = 10;
dx = 1;
dy = 0;
frameRate(30);
canvash = height;
canvasw = width;
start_speed = 1;
//define color RGB
darkblue = color(44,62,80);
lightpink = color(252,146,179);
lightred = color(252,67,73);
grey = color(225);
grey2 = color(215,218,219);
grey3 = color(160);
grey4 = color(200);
//call object function
current_block = new blockFeeder(width/2, 10, blockw,blockh,start_speed);
}
//---------------------------------------------------------------------------
function draw() {
background(grey2);
//skyline
fill(darkblue);
image(bground, 0, height*(3/5)-25, width, height/3);
rect(0,height*(8/10), width, height);
//sun
fill(lightred);
ellipse(width*(3/4),200,70,70);
//gameover screen
if (gameover){
fill(darkblue);
rect(0,0,width,height);
fill(255);
textSize(22);
textStyle(BOLD);
text("GAME OVER", width/4, height/2-height/30);
textStyle(NORMAL);
textSize(14);
text("Your tower was " + score + "/F.", width/4, height/2);
}
//stacking blocks correctly
else {
current_block.draw();
current_block.update();
for (var i = 0; i < old_blocks.length; i++) {
if (score > 3){
old_blocks[i].y += 2;
}
old_blocks[i].draw();
}
//gameover if blocks not stacked in same column
if (score > 0){
if (old_blocks[score-1].y > height){
gameover = true;
}
}
countScore();
//if block hits bottom of canvas, push block into old blocks array
if (current_block.hitbottom) {
old_blocks.push(current_block);
start_speed += 1;
current_block = new blockFeeder(width/2, 10, blockw,blockh,start_speed);
}
}
}
//create object-------------------------------------------------------------
function blockFeeder(x, y, width, height, speed) {
this.x = x;
this.y = y;
this.dx = speed;
this.dy = 0;
this.width = width;
this.height = height;
this.isclicked = false;
this.hitbottom = false;
this.draw = function() {
//crane (make it not fall with clicked block)
if (!this.isclicked){
fill(darkblue);
noStroke();
rect(this.x + this.width/2, this.y - windowmargin, this.width/6, this.height/6);
}
//floor
fill(grey3);
stroke(grey);
rect(this.x, this.y, this.width, this.height);
//block window decor
fill(grey);
rect(this.x + windowmargin, this.y + windowmargin*2, this.width/3, this.height/2);
rect(this.x + windowmargin*5, this.y + windowmargin*2, this.width/3, this.height/2);
fill(grey4);
stroke(grey);
rect(this.x + windowmargin, this.y + windowmargin*2, this.width/3, this.height/3);
rect(this.x + windowmargin*5, this.y + windowmargin*2, this.width/3, this.height/3);
}
//create horizontal crane movement
this.update = function() {
this.x += this.dx;
this.y += this.dy;
if ((this.x + this.width) > canvasw) {
this.dx = -this.dx;
} else if (this.x < 0) {
this.dx = -this.dx;
}
//make new block stack on previous height boundary
if (score == 0){
if (this.y + this.height > canvash) {
this.dy = 0;
this.hitbottom = true;
this.y = canvash - this.height;
}
}
//check if new block collides with bottom block accordingly
else {
if (this.y + this.height > old_blocks[score-1].y) {
if (abs(this.x-old_blocks[score-1].x) < blockw/2){
this.dy = 0;
this.hitbottom = true;
this.y = old_blocks[score-1].y - this.height;
}
else {
this.dy = 0;
this.hitbottom = true;
this.y = old_blocks[score-1].y - this.height;
gameover = true;
}
}
}
}
//move block to bottom of canvas when clicked
this.pressedButton = function(){
this.isclicked = true;
if (!this.hitbottom){
this.dx = 0;
this.dy = 10;
}
}
}
//---------------------------------------------------------------------------
function countScore(){
//define type settings
strokeWeight(1);
fill(255);
noStroke();
textSize(20);
textStyle(NORMAL);
text(score + "/F", width - 45, height - 20);
textSize(13);
textStyle(BOLD);
text(intro, windowmargin*2, height-20);
//when block stacks, add score
if (current_block.hitbottom) {
score += 1;
}
}
//---------------------------------------------------------------------------
function mousePressed() {
//follow block rules when mouse is pressed
current_block.pressedButton();
//remove intro when mouse pressed
intro = " ";
}
Instructions
Stack the highest tower by aligning blocks with at least 50% accuracy! The horizontal and vertical speed increases will make the level harder over time. Your tower height will also be recorded.
Description
Inspired by classic tower stack mobile games, I wanted to create an alternative version of it using a simple horizontal “crane”, with pressure given to the player from its increased speed over time. As the player begins to stack a higher tower, original blocks also begin to slide downwards, creating more time pressure for players. I also wanted to explore creating minimalistic graphics for a challenging, interactive game.
Instructions: Press any key to continue when text is finished scrolling. Click on choice boxes to select choice.
//choice variables
var choiceNow = false;
var choiceSoon = false;
var lastChoice = 1;
var buttonChoice = [0, 0, 0, 0, 0];
var choice1 = ["Go Forward", "Feel Around", "Stay Still"];
var choice2 = ["Go Back", "Kick", "Fall Down"];
var choice3 = ["Scarlet", "Cerulean", "Emerald", "None"];
var doorUnlocked = false;
//text variables
var textAll = []; //array containing all text objects
var textList = [
//0-2
"You awake to find yourself in a dark room.",
"You can't see anything, probably because it is dark.",
"What are you going to do?",
//3-5
"You decide to move forward, not that it really matters what direction you move in because it all looks the same.",
"This area of the room smells like apples; it makes you nauseous.",
"Now what are you going to do?",
//6-9
"You decide that this area isn't as good as the last one, so you walk backwards to whence you came.",
"As you moonwalk to your origin, the apple smell dissipates, easing your uneasiness.",
"Now back in your starting area, you feel a calm serenity wash over your eyebrows.",
"What are you going to do?",
//10-13
"You decide to wave your arms frantically, almost instantly thwacking a wall to your left.",
"After massaging your injured hand, you run your hand across the wall and notice some buttons.",
"There are 3 buttons, and you are stupidly confident that you know their colors even though it is pitch black.",
"Which button do you wish to press?",
//14-15
"You hear a satisfying 'Click' as you press the Scarlet button.",
"Which button do you wish to press?",
//16-17
"The Cerulean button gives you much resistance, but you eventually manage to become victorious and press the button.",
"Which button do you wish to press?",
//18-19
"You feel an exhilerating rush of energy enter your body through your fingertip as you press the Emerald button.",
"Which button do you wish to press?",
//20-22
"You decide that the buttons aren't worthy of your tender carresses and go back.",
"You are back where you were before, it's just as dark as before.",
"What are you going to do?",
//23-29
"You decide that this is probably all a dream and that the proper course of action is to do nothing.",
"After doing nothing for so long, you become drowsy, eventually falling asleep on the floor.",
"zzzzzzzzz",
"...",
"You awake to find yourself in a dark room.",
"You can't see anything, probably because it is dark.",
"What are you going to do?",
//30-34
"You decide to vent your frustrations by violently thrusting your foot forward, only for it to meet a metal object.",
"The metal object wins, leaving your foot in a sorry state.",
"You examine the metal object more closely and discover that it's a door, but it's locked.",
"You recover from your defeat and contemplate your course of action.",
"What are you going to do?",
//35-40
"You decide to do some pushups, but your arms are too weak and you fall to the floor.",
"When your nose crunches against the cold ground, you feel some engravings scratch against you.",
"Rubbing your fingers across the floor, you feel some words.",
"'Blue', 'Green', 'Blue', 'Red', 'Green'.",
"Wondering what these words mean, you stand back up and wipe the blood from your upper lip.",
"What are you going to do?",
//41-43
"You decide to cautiously extend your foot outwards, but there is nothing there to challenge its movement.",
"You then advance through the empty space, no metal object impeding your progress.",
"Did you escape? Or is this just the beginning?"];
var textNum = 0;
var currentText = 0;
var count = 0;
var letterGap = 10;
var timeGap = 3; //timing between letter placements
var textTop; //top of text box
var textLimit; //length of displayed text
function setup() {
createCanvas(480, 360);
textSize(20);
textTop = 2 * height / 3;
textAlign(CENTER);
textAssign();
}
function draw() {
currentText = textNum;
background(0);
present(1, 2, choice1, 3, 2, 10, 4, 23, 9);
present(2, 5, choice2, 6, 3, 30, 10, 35, 11);
present(3, 9, choice1, 3, 2, 10, 4, 23, 9);
present4();
present5();
present6();
present7();
present(8, 22, choice1, 3, 2, 10, 4, 23, 9);
present(9, 29, choice1, 3, 2, 10, 4, 23, 9);
if (lastChoice == 10) {
if (doorUnlocked) {
lastChoice = 12;
textNum = 41
} else {
present(10, 34, choice2, 6, 3, 30, 10, 35, 11);
}
}
present(11, 40, choice2, 6, 3, 30, 10, 35, 11);
present(12);
unlockDoor();
}
//put each text line into an object
function textAssign() {
for (var i = 0; i < textList.length; i ++) {
var newText = {words: textList[i],
scroll: textScroll,
next: nextText}
textAll.push(newText);
}
}
//access the line of text and display it in a scroll style
function textScroll() {
fill(255);
strokeWeight(0);
stroke(255);
textSize(2 * letterGap);
var xPos = 0;
var yPos = 0;
textLimit = min((count / timeGap), this.words.length);
for (var i = 0; i < textLimit; i ++) {
xPos += letterGap;
//if overflow, start a new line
if (25 + letterGap + xPos > width - 25 - letterGap) {
xPos = letterGap;
yPos += letterGap * 2;
}
text(this.words.charAt(i), 25 + letterGap + xPos,
textTop + letterGap * 2 + yPos);
}
count = min(count + 1, this.words.length * timeGap);
if (count == this.words.length * timeGap & choiceSoon == true) {
choiceNow = true;
} else {
choiceNow = false;
}
}
//perform text functions
function textStep(t) {
textAll[t].scroll();
textAll[t].next();
textBox();
}
//displays the text box
function textBox() {
noFill();
strokeWeight(3);
stroke(255);
rectMode(CORNERS);
rect(25, textTop, width - 25, height - 25);
}
//make it so when you press a key, next text comes in
function nextText() {
if (count == this.words.length * timeGap
& keyIsPressed == true
&& textNum != textList.length - 1
&& choiceSoon == false) {
textNum += 1
count = 0;
}
}
//display the choice options in multiple boxes
function choiceDisplay(choice) {
for (var i = 0; i < choice.length; i ++) {
var boxSide = (width - 25 * (choice.length + 1)) / choice.length;
noFill();
strokeWeight(2);
stroke(255);
rectMode(CORNER);
rect(25 * (i + 1) + (boxSide * i),
height / 3 - boxSide / 2, boxSide, boxSide);
fill(255);
strokeWeight(1);
text(choice[i], 25 * (i + 1) + (boxSide * i) + boxSide / 2, height / 3);
}
}
//allow player to make a choice depending on click location
function choiceAction(choice) {
var boxSide = (width - 25 * (choice.length + 1)) / choice.length;
if (mouseIsPressed) {
if (mouseY > height / 3 - boxSide / 2 &
mouseY < height / 3 + boxSide / 2) {
for (var i = 0; i < choice.length; i ++) {
if (mouseX > 25 * (i + 1) + (boxSide * i) &
mouseX < 25 * (i + 1) + (boxSide * i) + boxSide) {
return i;
}
}
}
}
}
//button panel
function present4() {
if (lastChoice == 4) {
textStep(currentText);
if (currentText == 13) {
choiceSoon = true;
if (choiceNow == true) {
choiceDisplay(choice3);
var choice = choiceAction(choice3);
if (choice == 0) {
textNum = 14;
lastChoice = 5;
count = 0;
buttonChoice.shift();
buttonChoice.push(1);
} else if (choice == 1) {
textNum = 16;
lastChoice = 6;
count = 0;
buttonChoice.shift();
buttonChoice.push(2);
} else if (choice == 2) {
textNum = 18;
lastChoice = 7;
count = 0;
buttonChoice.shift();
buttonChoice.push(3);
} else if (choice == 3) {
textNum = 20;
lastChoice = 8;
count = 0;
}
}
} else {
choiceSoon = false;
}
}
}
//scarlet button press
function present5() {
if (lastChoice == 5) {
textStep(currentText);
if (currentText == 15) {
choiceSoon = true;
if (choiceNow == true) {
choiceDisplay(choice3);
var choice = choiceAction(choice3);
if (choice == 0) {
textNum = 14;
lastChoice = 5;
count = 0;
buttonChoice.shift();
buttonChoice.push(1);
} else if (choice == 1) {
textNum = 16;
lastChoice = 6;
count = 0;
buttonChoice.shift();
buttonChoice.push(2);
} else if (choice == 2) {
textNum = 18;
lastChoice = 7;
count = 0;
buttonChoice.shift();
buttonChoice.push(3);
} else if (choice == 3) {
textNum = 20;
lastChoice = 8;
count = 0;
}
}
} else {
choiceSoon = false;
}
}
}
//cerulean button press
function present6() {
if (lastChoice == 6) {
textStep(currentText);
if (currentText == 17) {
choiceSoon = true;
if (choiceNow == true) {
choiceDisplay(choice3);
var choice = choiceAction(choice3);
if (choice == 0) {
textNum = 14;
lastChoice = 5;
count = 0;
buttonChoice.shift();
buttonChoice.push(1);
} else if (choice == 1) {
textNum = 16;
lastChoice = 6;
count = 0;
buttonChoice.shift();
buttonChoice.push(2);
} else if (choice == 2) {
textNum = 18;
lastChoice = 7;
count = 0;
buttonChoice.shift();
buttonChoice.push(3);
} else if (choice == 3) {
textNum = 20;
lastChoice = 8;
count = 0;
}
}
} else {
choiceSoon = false;
}
}
}
//emerald button press
function present7() {
if (lastChoice == 7) {
textStep(currentText);
if (currentText == 19) {
choiceSoon = true;
if (choiceNow == true) {
choiceDisplay(choice3);
var choice = choiceAction(choice3);
if (choice == 0) {
textNum = 14;
lastChoice = 5;
count = 0;
buttonChoice.shift();
buttonChoice.push(1);
} else if (choice == 1) {
textNum = 16;
lastChoice = 6;
count = 0;
buttonChoice.shift();
buttonChoice.push(2);
} else if (choice == 2) {
textNum = 18;
lastChoice = 7;
count = 0;
buttonChoice.shift();
buttonChoice.push(3);
} else if (choice == 3) {
textNum = 20;
lastChoice = 8;
count = 0;
}
}
} else {
choiceSoon = false;
}
}
}
//door open exit
function present12() {
if (lastChoice == 12) {
choiceSoon = false;
textStep(currentText);
}
}
//general present function, isn't used for button presses
function present(lastC, choiceLine, choiceNum, newTextNum0, newLastC0, newTextNum1,
newLastC1, newTextNum2, newLastC2) {
if (lastChoice == lastC) {
textStep(currentText);
if (currentText == choiceLine) {
choiceSoon = true;
if (choiceNow == true) {
choiceDisplay(choiceNum);
var choice = choiceAction(choiceNum);
if (choice == 0) {
textNum = newTextNum0;
lastChoice = newLastC0;
count = 0;
} else if (choice == 1) {
textNum = newTextNum1;
lastChoice = newLastC1;
count = 0;
} else if (choice == 2) {
textNum = newTextNum2;
lastChoice = newLastC2;
count = 0;
} else if (choice == 3) {
textNum = newTextNum3;
lastChoice = newLastC3;
count = 0;
}
}
} else {
choiceSoon = false;
}
}
}
function unlockDoor() {
if (buttonChoice[0] == 2 &
buttonChoice[1] == 3 &&
buttonChoice[2] == 2 &&
buttonChoice[3] == 1 &&
buttonChoice[4] == 3) {
doorUnlocked = true;
}
}
This project was pretty fun to work on, but I’m actually a bit disappointed in it. It’s a text-based adventure with a simple non-puzzle that’s really more of a proof of concept.
]]>For my project I mainly based my project on whack a mole game combined with the pokemon that everyone loves, Diglet. The game lasts for 60 sec and during time the player would want to hit as many diglets as possible. Once the game ends the user can press r to restart the game. Hope you enjoy the game!
//Alvin Luk
//Section A
//akluk@andrew.cmu.edu
//Final Project
//initialize constants and variables
//number of rows of diglets in the canvas
var rows = 3;
//body height of the diglet
var diglet_h = 30;
//number of diglets in the game
var num_diglets = 11;
//array to contain the diglet objects
var diglets = [];
//temporary dummie variable to help push all the diglets
var temp_diglet;
//number of diglets the player has hit in a single run of game/score
var num_hit;
//number of 0.5 sec passed elapsed
var time_elapsed = 0;
//duration of game 60sec
var game_time = 120;
//whether the game has ended
var ended = 0;
//hammer mode to determine if hammer is down or up
var mode;
//start position for even rows
var startx1 = 60;
//start position for odd row
var startx2 = 120;
//spacing with each diglet
var spacing = 120;
//height spacing
var dy = 90;
function setup() {
createCanvas(480, 360);
//creates the diglets in the right positions
// and pushes it into the array of diglets
for (var i = 0; i < rows; i++) {
//even rows
if ((i % 2) == 0){
for (var j = startx1; j < width; j += spacing){
temp_diglet = new diglet(j,dy*(i+1));
diglets.push(temp_diglet);
}
}
//odd rows
else {
for (var j = startx2; j < width; j += spacing){
temp_diglet = new diglet(j,dy*(i+1));
diglets.push(temp_diglet);
}
}
}
//initialize score for player
num_hit = 0;
//update the diglets ever half second to determine if they pop up
//and update timer every 0.5 sec
setInterval(function(){
for (var index = 0; index < num_diglets; index ++){
diglets[index].update();
}
time_elapsed += 1;
}, 500);
}
function draw() {
background(40,180,40);
noStroke();
//change the display of the hammer
if (mouseIsPressed){
mode = 1;
}
else {
mode = 0;
}
//end the game when the timer has ended
if (time_elapsed >= game_time){
ended = 1;
}
//if game has not ended, draw the holes for the diglets in the correct location
if (ended == 0){
for (var i = 0; i < rows; i++) {
//odd rows
if ((i % 2) == 0){
for (var j = 60; j < width; j += 120){
drawHole(j,dy*(i+1));
}
}
//even rows
else {
for (var j = 120; j < width; j += 120){
drawHole(j,dy*(i+1));
}
}
}
//draw every diglet in the array of diglets
for (var index = 0; index < num_diglets; index ++){
diglets[index].draw();
}
//draw hammer in passive position
if (mode == 0) {
fill(130,82,1);
rect(mouseX-5,mouseY-25,10,50);
fill(120);
rect(mouseX-25,mouseY-35, 50,20);
}
//draw hammer in active position
else {
fill(130,82,1);
rect(mouseX,mouseY-5,50,10);
fill(120);
rect(mouseX-10,mouseY-25, 20,50);
}
//display score and time left for the game
fill(255);
textSize(15);
text("Score : " + num_hit, 400,340);
text("Time Left : " + (game_time-time_elapsed)/2,5,340);
}
//game over screen
else {
fill(0);
rect(0,0,width,height);
fill(255);
text("Game Over!", width/2 - width/10, height/2);
text("Final Score : " + num_hit, width/2 - width/10,height/2 + height/15);
text("Press R to restart", width/2 - width/10, height/2 + 2*height/15);
}
}
//draw the hole sorry for much random numbers to make it look natural
function drawHole(x,y){
fill(0);
ellipse(x,y,80,40);
fill(103,104,76);
ellipse(x-40,y,22,12);
ellipse(x+40,y,22,12);
fill(90,77,65);
ellipse(x-32,y+8,20,12);
ellipse(x+28,y+8,24,14);
fill(119,120,119);
ellipse(x-22,y+13,20,12);
ellipse(x+12,y+16,24,15);
fill(100,100,100);
ellipse(x-4,y+18,28,15);
}
//object of diglet
function diglet(x,y,duration){
//base variables
this.x = x;
this.y = y;
this.duration = duration;
//draw the diglet, with eyes and body
this.draw = function() {
if (this.duration > 0) {
//brown of diglet
fill(181,147,119);
rect(this.x-diglet_h/2,this.y-diglet_h,diglet_h,diglet_h);
ellipse(this.x,this.y-diglet_h,diglet_h,diglet_h);
fill(0);
ellipse(this.x-diglet_h/6,this.y-diglet_h,3,6);
ellipse(this.x+diglet_h/6,this.y-diglet_h,3,6);
fill(255);
ellipse(this.x-diglet_h/6,this.y-diglet_h-2,1,1);
ellipse(this.x+diglet_h/6,this.y-diglet_h-2,1,1);
//nose color
fill(239,187,210);
ellipse(this.x,this.y-diglet_h+6,diglet_h/3,5);
}
}
//update whether the diglet appears
this.update = function(){
if (this.duration > 0){
this.duration = this.duration - 0.5;
}
else {
var temp_ratio = random(0,1);
if (temp_ratio < 0.15){
this.duration = random([1,2,3,4]);
}
}
}
//check if user clicked the diglet
this.inDiglet = function(click_x,click_y){
if (((click_x > this.x-diglet_h/2) & (click_x < this.x-diglet_h/2) && (click_y > this.y - diglet_h) && (click_y < this.y)) || (dist(click_x,click_y,this.x,this.y-diglet_h) < diglet_h)){
if (this.duration > 0){
this.duration = 0;
num_hit += 1;
}
}
}
}
//check if when the mouse is pressed if it hits any diglet
function mousePressed() {
for (var i = 0; i < num_diglets; i++){
diglets[i].inDiglet(mouseX,mouseY);
}
}
//when the game is over and you press r reset the game
function keyTyped(){
if ((key === 'r') & (ended == 1)){
ended = 0;
time_elapsed = 0;
ended = 0;
num_hit = 0;
}
}
]]>//Allison Mui
//15-104 Section A
//amui1@andrew.cmu.edu
//Final Project
//variables for image
var monty = [];
var flyingMonty;
var swimmingMonty;
var evilOcty;
var bubble;
var bubbleX = [];
var bubbleY = [];
var punchMonty = [];
var monster;
var monstFall = [];
var homeMonty;
//variables for mouse movement
var targetX;
var targetY;
//variables for different states
var begin = true;
var home = false;
var world1 = false;
var world2 = false;
var world3 = false;
var over = false;
//variables for begin state
var playX;
var playY;
//variables for fire world1
var fires = [];
var fireCounter = 0;
var waterArray = [];
//variables for sea world
var octyY = 10;
var octySpeed = 4;
var inkSpeed;
var inkX = 280;
var inks = [];
var inkCounter = 0;
//variables for fight world
var fightmontyX = 130;
var fightmontyY = 350;
var fighttargetX = 130;
var fighttargetY = 350;
var monstX = 300;
var monstY = 280;
var monstSpeed = 5;
var level = 1;
//loads images
function preload() {
//image for home monty
homeMonty = loadImage("https://i.imgur.com/LudAnMM.png");
//images for walking monty
var montyfile = [];
montyfile[0] = "https://i.imgur.com/jF4qiIL.png";
montyfile[1] = "https://i.imgur.com/Q2Y2NMk.png";
montyfile[2] = "https://i.imgur.com/Bhzuxet.png";
montyfile[3] = "https://i.imgur.com/NXGRLMb.png";
//loads monty
for (var i = 0; i < 4; i++) {
monty[i] = loadImage(montyfile[i]);
}
//image for fire world
flyingMonty = loadImage("https://i.imgur.com/uogV1b7.png");
//images for sea world
bubble = loadImage("https://i.imgur.com/ZzkbRgi.png")
swimmingMonty = loadImage("https://i.imgur.com/FwBvECT.png");
evilOcty = loadImage("https://i.imgur.com/gYrnKp2.png");
//images for fight world
kickmonty = loadImage("https://i.imgur.com/ZpfaJlx.png")
punchMonty[0] = loadImage("https://i.imgur.com/jF4qiIL.png");
punchMonty[1] = loadImage("https://i.imgur.com/Q2Y2NMk.png");
punchMonty[2] = loadImage("https://i.imgur.com/wCvUx2R.png");
punchMonty[3] = loadImage("https://i.imgur.com/NXGRLMb.png");
monster = loadImage("https://i.imgur.com/E0lKepM.png")
monstFall[0] = loadImage("https://i.imgur.com/E0lKepM.png")
monstFall[1] = loadImage("https://i.imgur.com/FX8hPMk.png");
}
function setup() {
createCanvas(480,450);
imageMode(CENTER);
frameRate(4);
// Initialize the character and target positions
characterX = width/2;
characterY = height/2;
targetX = characterX;
targetY = characterY;
//fire world1
dif = 0;
for (var i = 0; i < 6; i++) {
fires[i] = makeFire(width/4 + dif);
dif += random(50,80);
}
//randomizing location for bubbles for sea world
for (b = 0; b < 15; b++) {
bubbleX.push(random(width));
bubbleY.push(random(height));
}
//load bubble picture
bubble.loadPixels();
//loads home monty picture
homeMonty.loadPixels();
}
function draw(){
if (begin == true) {
drawBegin();
}
if (home == true) {
drawHome();
}
//calculates distance from monty to the world 1 icon
var distWorld1 = dist(characterX,characterY,width/4,height/4);
//if close enough, change the booleans to show a new screen
if (distWorld1 < 10) {
home = false;
world1 = true;
drawworld1();
}
//calulate distance from monty to world 2 icon
var distWorld2 = dist(characterX,characterY,width/2+width/4,height/4);
//if close enough, change booleans and show new screen
if (distWorld2 < 10) {
home = false;
world2 = true;
drawworld2();
}
//calculates distance from monty to world 3 icon
var distWorld3 = dist(characterX,characterY,width/2,height/2+width/4+20);
//if close enough, change booleans and show new screen
if (distWorld3 < 10) {
home = false;
world3 = true;
drawworld3();
}
//if too many points were lost (parameters in specific world), change screen
if (over == true) {
gameOver();
}
}
function drawBegin() {
background(0);
image(homeMonty,width/2,height/2-20);
textSize(24);
fill(255);
text("Lonnie's World",160,80);
textSize(16);
text("Lonnie travels from fire to sea, avoiding danger",80,110);
textSize(20);
text("Press play to begin", 160,350);
var dPlay = dist(playX,playY,160,350);
print(dPlay);
if (dPlay < 80) {
begin = false;
home = true;
}
}
function drawHome() {
textSize(14);
background(0);
frameRate(4);
//world 1
strokeWeight(0);
fill(229,115,115);
ellipse(width/4,height/4,50,50);
fill(240,171,171);
ellipse(width/4,height/4,35,35);
fill(255);
text("Flames of Fury", width/4-40,height/4-35);
//world 2
fill(109,181,255);
ellipse(width/2+width/4,height/4,50,50);
fill(167,211,255);
ellipse(width/2+width/4,height/4,35,35);
fill(255);
text("Waves of Fear", width/2+width/4-35,height/4-35);
//fight world
fill(255,253,41);
ellipse(width/2,height/2+width/4+20,50,50);
fill(255,254,127);
ellipse(width/2,height/2+width/4+20,35,35);
fill(255);
text("Fight Club",width/2-25,height/2+width/4-15);
//move monty according to where user clicks
var dx = targetX - characterX;
var dy = targetY - characterY;
//cycles through all image files to walk
image(monty[frameCount%4], characterX, characterY);
characterX = characterX + dx/10;
characterY = characterY + dy/10;
}
function mousePressed() {
//sets new target for play button
playX = mouseX;
playY = mouseY;
//set boundaries for user's mouse
targetX = mouseX;
targetY = mouseY;
targetX = constrain(mouseX,0,width-50);
targetY = constrain(mouseY,0,height-50);
//sets new target for the fight world
fighttargetX = mouseX;
fighttargetY = mouseY;
}
function drawworld1() {
background(0);
frameRate(12);
//sets the monster's position
var flyingmontyX = mouseX;
var flyingmontyY = mouseY;
//constrains the monsters position to not move past the middle and canvase
var flyingmontyY = constrain(flyingmontyY,40,height-90);
var flyingmontyX = constrain(flyingmontyX,45,height/2);
//displays image
image(flyingMonty,flyingmontyX,flyingmontyY);
strokeWeight(0);
//displays fire
showFire();
//instructions
noFill();
stroke(255);
strokeWeight(1);
rect(0,height-50,width,50);
strokeWeight(0);
fill(255);
text("Avoid the fire or you'll get burned!", 10,height-28);
text("Points: " + fireCounter, width-70,height-30);
//if mouse over "go home" returns to the home screen
text("Go Home", width-70, height-10);
var distHome = dist(mouseX,mouseY,width-70,height-10);
if (distHome < 15) {
home = true;
}
//ends game if points too low
if (fireCounter < -100) {
over = true;
}
}
function drawworld2() {
frameRate(15);
background(175,246,249);
//draw bubbles
for (bub = 0; bub < 15; bub++) {
image(bubble,bubbleX[bub],bubbleY[bub]);
}
//changes speed by a random amount(speedif) as time goes on
if (frameCount % 60 == 0) {
speeddif = random(1,3);
octySpeed = octySpeed + speeddif;
}
//make new ink blots at different times
if (frameCount % 60 == 0) {
inks.push(makeInk(inkX,octyY));
}
//displays ink
showInk();
//monty moves with mouse
swimX = mouseX;
swimY = mouseY;
//sets boundaries so monty doesn't go off the page
var swimY = constrain(swimY,30,height-90);
var swimX = constrain(swimX,0,width/4);
//display monty
image(swimmingMonty,swimX,swimY);
//displays the octopus monster
image(evilOcty,width-120,octyY);
//moves octy
octyY += octySpeed;
//sets actions so octy doesn't move off the page
if (octyY > height-90) {
octySpeed = -octySpeed;
}
if (octyY < 10) {
octySpeed = -octySpeed;
}
//instructions
rectMode(CORNER);
fill(40,40,57);
stroke(255);
strokeWeight(1);
rect(0,height-50,width,50);
strokeWeight(0);
fill(255);
text("The evil octopus is squirting ink!", 10,height-28);
text("Avoid the head of the ink!", 10, height-10);
text("Points: " + inkCounter, width-70,height-30);
text("Go Home", width-70, height-10);
//calculates where mouse is, if over home button, draw home state
var distHome = dist(mouseX,mouseY,width-65,height-10);
if (distHome < 15) {
home = true;
}
//only go through this only if inks array is populated
//add points if monster successfully avoids the ink
if (inks.length > 0) {
//if monster hits the ink, deduct 5 points
if ((swimX > inks[0].x-100 & swimX < inks[0].x+100) &&
(swimY > inks[0].y-5 && swimY < inks[0].y+30)) {
inkCounter -= 1;
}
//remove ink blots after it moves off the page
if (inks[0].x < 0) {
inkCounter += 1;
inks.shift(1);
}
}
//end game if too many points lost
if (inkCounter < -100) {
over = true;
}
}
function drawworld3() {
background(47,100,145);
//draw boxing design
drawBoxingRing();
//calculates distance between monster fighting and monty
var dFight = dist(fightmontyX,fightmontyY,monstX,monstY);
//if monty runs into monster, then game is over
if (dFight < 90) {
over = true;
}
//fight monster
//punches monster if monty is close enough
if(dFight < 98 & keyIsDown(80)) {
//if monster is punched, monster "falls down"
//cycles through image array
image(monstFall[frameCount%2],monstX,monstY);
}
//if monster is not punched, move monster from right to left
else {
image(monster,monstX,monstY);
monstX -= monstSpeed;
//sets boundary for the monster
if (monstX < 150) {
monstSpeed = -monstSpeed;
}
if (monstX > 300) {
monstSpeed = -monstSpeed;
}
}
//image of the fighting monty
//calculates distance for movement of monty
var dx = fighttargetX - fightmontyX;
var dy = fighttargetY - fightmontyY;
//constrains the boundary of monty
fightmontyX = constrain(fightmontyX,30,300);
fightmontyY = constrain(fightmontyY,height-150,height-80);
//moves monty
fightmontyX = fightmontyX + dx/10;
fightmontyY = fightmontyY + dy/10;
//if user doesn't call monty to move, monty is still
if (fightmontyX == fighttargetX & fightmontyY == fighttargetY) {
image(monty[0], fightmontyX, fightmontyY);
}
//if monty is punching, restrict image so punch monty will match
if (keyIsDown(80) & (frameCount%4 == 0 || (frameCount%4 == 2))) {
image(punchMonty[2],fightmontyX,fightmontyY);
}
//if user calls monty to move, monty moves and cycles through all image files
if (fightmontyX != fighttargetX || fightmontyY != fighttargetY) {
image(monty[frameCount%4],fightmontyX,fightmontyY);
}
//instructions
fill(35,75,109);
stroke(255);
strokeWeight(1);
rect(0,height-50,width,50);
strokeWeight(0);
fill(255);
textSize(13);
text("Battle the hungry bear!", 10,height-28);
text("Click to move and hold 'p' to punch!", 10, height-10);
text("Level: " + level, width-70,height-30);
text("Go Home", width-70, height-10);
//calculates distance from user's mouse to the go home button
var distHome = dist(mouseX,mouseY,width-65,height-10);
//if user's mouse is on the go home button, draw home state
if (distHome < 15) {
home = true;
}
//increases level after some time passed
if (frameCount%2000 == 0) {
level += 1;
}
}
function drawBoxingRing() {
//background design to make look like boxing setting
strokeWeight(0);
fill(35,79,109);
rect(0,height-120,width,100);
stroke(35,79,109);
strokeWeight(15);
line(10,height-50,width/4-20,130);
line(250,height-50,width/2+80,130);
line(250,height-50,width/4+30,130);
line(480,height-50,380,130);
strokeWeight(0);
fill(35,75,109);
rect(0,0,width,130);
//lights
stroke(255);
strokeWeight(5);
line(150,145,160,145);
line(155,140,155,150);
line(300,170,310,170);
line(305,165,305,175);
//banner
fill(189,57,51);
strokeWeight(5);
rect(width-180,30,140,40);
strokeWeight(0);
fill(255);
textSize(15);
text("Fight! Train! Win!",width-165,55);
//boxing ring
fill(255);
strokeWeight(0);
triangle(20,height-50,100,height-160,100,height-50);
rect(100,height-160,280,150);
triangle(380,height-50,380,height-160,460,height-50);
fill(189,57,51);
triangle(30,height-50,100,height-150,100,height-50);
rect(100,height-150,280,150);
triangle(380,height-50,380,height-150,450,height-50);
//boxing horizontal lines - "strings around the ring"
stroke(255);
strokeWeight(3);
//left
line(30,height-140,125,height-248);
line(30,height-120,125,height-230);
line(30,height-100,125,height-210);
//mid
line(125,height-230,360,height-230);
line(125,height-210,360,height-210);
line(125,height-190,360,height-190);
//right
line(360,height-248,450,height-140);
line(360,height-230,450,height-120);
line(360,height-210,450,height-100);
//boxing columns
fill(142,43,38);
strokeWeight(0);
rect(20,height-200,40,200,5);
rect(100,height-250,40,100,5);
rect(340,height-250,40,100,5);
rect(height-30,height-200,40,200,5);
}
function gameOver() {
background(0);
textSize(50);
text("Game Over",15,height/2);
textSize(14);
text("Please refresh to start over :)",20,height/2+50);
}
function showInk() {
//moves and draws inks in the ink array
for (var i = 0; i < inks.length; i++) {
inks[i].draw();
inks[i].move();
}
}
function moveInk() {
this.x -= this.speed;
}
function drawInk() {
//draw ink
strokeWeight(0);
fill(40,40,57);
rectMode(CENTER);
rect(this.x,this.y,200,20,10);
rect(this.x,this.y+25,180,20,10);
}
function makeInk(x,y) {
m = {x:x,
y:y,
speed: random(5,8),
draw: drawInk,
move: moveInk}
return m;
}
function showFire() {
//go through fire Array
for (var fiyah = 0; fiyah < fires.length; fiyah++) {
//alternate fire design
//if even number, show fire coming from the bottom of the canvas
if (fiyah % 2 == 0) {
fires[fiyah].drawup();
fires[fiyah].move();
}
//if odd number, show fire coming from the top
if (fiyah % 2 != 0) {
fires[fiyah].drawdown();
fires[fiyah].move();
}
}
}
function moveFire() {
//sets the monster's position
var flyingmontyX = mouseX;
var flyingmontyY = mouseY;
//constrains the monsters position to not move past the middle and canvase
var flyingmontyY = constrain(flyingmontyY,40,height-90);
var flyingmontyX = constrain(flyingmontyX,45,height/2);
//moves fire
this.x -= this.speed;
//if fire moves off page, points go up
if (this.x < 0-30) {
this.x = width;
fireCounter += 1;
}
//calculates distance from monty to fire
if (flyingmontyY < height/2) {
var dFire = dist(flyingmontyX,flyingmontyY,this.x,this.h);
}
if (flyingmontyY > height/2) {
var dFire = dist(flyingmontyX,flyingmontyY,this.x,height-this.h);
}
//if monty too close to fire, deduct points
if (dFire < 20) {
fireCounter -= 5;
}
}
//if fire is coming from the floor
function drawupFire(){
//draws redish flame
fill(216,82,42);
triangle(this.x-20,height-50,this.x-5-random(1,10),height-50-(this.h+60)-random(1,50),
this.x+50+random(1,10),height-50);
triangle(this.x,height-50,this.x+10+random(-1,5),height-50-(this.h+60)-random(1,60),
this.x+50+random(1,10),height-50);
triangle(this.x,height-50,this.x+20+random(1,10),height-50-(this.h+60)-random(1,50),
this.x+55+random(1,10),height-50);
//draws orange flame
fill(221,144,44);
triangle(this.x-15,height-50,this.x-5-random(1,10),height-50-(this.h+40)-random(1,40),
this.x+40+random(1,10),height-50);
triangle(this.x,height-50,this.x+10+random(-1,5),height-50-(this.h+40)-random(1,50),
this.x+40+random(1,10),height-50);
triangle(this.x,height-50,this.x+20+random(1,10),height-50-(this.h+40)-random(1,40),
this.x+45+random(1,10),height-50);
//draws dark yellow flame
fill(233,219,47);
triangle(this.x-10,height-50,this.x-5-random(1,10),height-50-(this.h+20)-random(1,30),
this.x+30+random(1,10),height-50);
triangle(this.x,height-50,this.x+10+random(-1,5),height-50-(this.h+20)-random(1,40),
this.x+30+random(1,10),height-50);
triangle(this.x,height-50,this.x+20+random(1,10),height-50-(this.h+20)-random(1,30),
this.x+35+random(1,10),height-50);
//draws light yellow frame
fill(255,250,163);
triangle(this.x-5,height-50,this.x-5-random(1,10),height-50-this.h-random(1,20),
this.x+20+random(1,10),height-50);
triangle(this.x,height-50,this.x+10+random(-1,5),height-50-this.h-random(1,30),
this.x+20+random(1,10),height-50);
triangle(this.x,height-50,this.x+20+random(1,10),height-50-this.h-random(1,20),
this.x+25+random(1,10),height-50);
}
//if fire coming from ceiling
function drawdownFire(){
//draws redish flame
fill(216,82,42);
triangle(this.x-20,0,this.x-5-random(1,10),0+(this.h+60)-random(1,50),
this.x+50+random(1,10),0);
triangle(this.x,0,this.x+10+random(-1,5),0+(this.h+60)-random(1,60),
this.x+50+random(1,10),0);
triangle(this.x,0,this.x+20+random(1,10),0+(this.h+60)-random(1,50),
this.x+55+random(1,10),0);
//draws orange flame
fill(221,144,44);
triangle(this.x-15,0,this.x-5-random(1,10),0+(this.h+40)-random(1,40),
this.x+40+random(1,10),0);
triangle(this.x,0,this.x+10+random(-1,5),0+(this.h+40)-random(1,50),
this.x+40+random(1,10),0);
triangle(this.x,0,this.x+20+random(1,10),0+(this.h+40)-random(1,40),
this.x+45+random(1,10),0);
//draws dark yellow flame
fill(233,219,47);
triangle(this.x-10,0,this.x-5-random(1,10),0+(this.h+20)-random(1,30),
this.x+30+random(1,10),0);
triangle(this.x,0,this.x+10+random(-1,5),0+(this.h+20)-random(1,40),
this.x+30+random(1,10),0);
triangle(this.x,0,this.x+20+random(1,10),0+(this.h+20)-random(1,30),
this.x+35+random(1,10),0);
//draws light yellow frame
fill(255,250,163);
triangle(this.x-5,0,this.x-5-random(1,10),0+this.h-random(1,20),
this.x+20+random(1,10),0);
triangle(this.x,0,this.x+10+random(-1,5),0+this.h-random(1,30),
this.x+20+random(1,10),0);
triangle(this.x,0,this.x+20+random(1,10),0+this.h-random(1,20),
this.x+25+random(1,10),0);
}
function makeFire(x){
f = {x:x,
h: random(20,130),
speed: random(1,8),
drawup: drawupFire,
drawdown: drawdownFire,
move: moveFire}
return f;
}
Features
Reflection
I enjoyed this project a lot because it was so challenging, but fun and rewarding. I really felt like I put what I learned in this class to test. Trying to incorporate something I learned from each week, I saw the vast power creative computing has. The most enjoyable part was seeing how far this project has come: from storyboard to now. The most challenging part was trying to fix, adjust, and adapt my game when a programming difficulty came up (which was often). In addition, I had a lot of fun creating the visuals in this project and then adding motion to them. All in all, I am happy with my project’s final outcome.
Caption: Above is my first storyboard of my game. As you can see, my idea has changed quite a bit from beginning to end. However, my main concept of moving a character through different worlds or states remained the same.
Caption: Above are the 3 worlds my character travels through.
]]>