/*
Yiran Xuan
Section A
yxuan@andrew.cmu.edu
Final Project
*/
var redframes = []; // array for red dragon sprites
var blueframes = []; //array for blue dragon sprites
var beat; //sound variables
var impact;
var fire;
var growl;
var charge;
/*
status key:
0 = default
1 = attack
2 = shield
3 = reload
4 = impact
5 = shielded impact
6 = death (not real status)
*/
//---------------------------------------
function preload(){ //load all sprites into respective arrays
//each sprite's index in array should match the status it represents
//ex) the red dragon's default sprite should have index of zero
/*
redframes.push(loadImage("./DragonDefault.png"));
blueframes.push(loadImage("./DragonDefault2.png"));
redframes.push(loadImage("./DragonAttack.png"));
blueframes.push(loadImage("./DragonAttack2.png"));
redframes.push(loadImage("./DragonShield.png"));
blueframes.push(loadImage("./DragonShield2.png"));
redframes.push(loadImage("./DragonReload.png"));
blueframes.push(loadImage("./DragonReload2.png"));
redframes.push(loadImage("./DragonImpact.png"));
blueframes.push(loadImage("./DragonImpact2.png"));
redframes.push(loadImage("./DragonShieldedImpact.png"));
blueframes.push(loadImage("./DragonShieldedImpact2.png"));
redframes.push(loadImage("./DragonDeath.png"));
blueframes.push(loadImage("./DragonDeath2.png"));
beat = loadSound("rockyoubeat.wav"); //import sounds
impact = loadSound("Strong_Punch.wav");
fire = loadSound("Flame.wav");
growl = loadSound("Growling Lion.wav");
charge = loadSound("lasercharge.wav");
*/
//default
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonDefault.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonDefault2.png"));
//attack
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonAttack.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonAttack2.png"));
//shield
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonShield.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonShield2.png"));
//reload
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonReload.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonReload2.png"));
//impact
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonImpact.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonImpact2.png"));
//shielded impact
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonShieldedImpact.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonShieldedImpact2.png"));
//death
redframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonDeath.png"));
blueframes.push(loadImage("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/DragonDeath2.png"));
beat = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/rockyoubeat.wav"); //import sounds
impact = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/Strong_Punch.wav");
fire = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/Flame.wav");
growl = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/Growling-Lion.wav");
charge = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/lasercharge.wav");
}
//--------------------------------------- Game Process functions
var RedDragon;
var BlueDragon;
var secondsbeforereload = 3;
var deadframecounter = 0; //after the endgame, counts number of frames before the game restarts
var cycle = 24; //number of frames in a cycle
var secondspercycle = 1; //how long one cycle
var framerate = cycle/secondspercycle;
var framecounter = 0; //counts frames to control the cycle
var actionwindow = cycle*2/3; //window for player input
function setup() {
createCanvas(600, 400);
imageMode(CENTER);
textStyle(BOLD);
textAlign(CENTER);
frameRate(framerate);
RedDragon = createDragon(3, 0, 1, redframes); //start with one health and no ammo
BlueDragon = createDragon(3, 0, -1, blueframes);
}
var redturn = true; //becomes false once a player has made move, ensures each player only makes one action per round
var blueturn = true;
function draw() {
background('white');
if(RedDragon.death || BlueDragon.death){ //if one dragon had died, just display default renders
GameEnd();
}
else{
if(framecounter < actionwindow){ //Stage 1: allowing player action input, displaying default renders
fill('green');
RedDragon.DefaultRender();
BlueDragon.DefaultRender();
}
else if (framecounter == actionwindow){ //Stage 2: processing player actions
fill('red');
RedDragon.Action();
BlueDragon.Action();
RedDragon.opponentaction = BlueDragon.currentaction;
BlueDragon.opponentaction = RedDragon.currentaction;
}
else if (framecounter < cycle*5/6){ //Stage 3: display player actions
fill('red');
RedDragon.ActionRender();
BlueDragon.ActionRender();
}
else if (framecounter == cycle*5/6){ //Stage 4: process opponent actions and end result
fill('red');
RedDragon.Result();
BlueDragon.Result();
}
else{ //Stage 5: display result of interaction
fill('red');
RedDragon.ResultRender();
BlueDragon.ResultRender();
}
framecounter++; //framecounter is here music stops after end of the game
}
textSize(30);
fill('green');
text("Health: " + RedDragon.health, RedDragon.x, RedDragon.y - 75); //display current healths
text("Health: " + BlueDragon.health, BlueDragon.x, BlueDragon.y - 75);
textSize(15);
fill('red');
text("J to attack, K to shield, L to reload", RedDragon.x, RedDragon.y - 125); //display current healths
fill('blue');
text("A to attack, S to shield, D to reload", BlueDragon.x, BlueDragon.y - 125);
if (framecounter == cycle){ //when cycle is complete
framecounter = 0;
redturn = true; //allows players action again
blueturn = true;
RedDragon.Reset(); //and reset round variables (currentmove, opponentmove, status)
BlueDragon.Reset();
beat.play();//beat starts playing here
}
}
//--------------------------------------- Event functions
function GameEnd(){
RedDragon.DefaultRender(); //display the dragons; DefaultRender contains death render as well
BlueDragon.DefaultRender();
var winner = "Nobody"; //default is draw
if(RedDragon.health > BlueDragon.health){ //comparing health to determine victor
winner = "Red Dragon";
}
if(RedDragon.health < BlueDragon.health){
winner = "Blue Dragon";
}
fill('black');
textSize(50);
text(winner + " Wins!", width/2, 75); //writing victory text
deadframecounter++;
if(deadframecounter == framerate*secondsbeforereload){ //reloads entire page after 3 seconds to restart game
location.reload();
}
}
function keyPressed(){
if(key == 'a' || key == 's' || key == 'd'){ //is the pressed key a valid blue action?
if(framecounter < actionwindow & blueturn){ //is it within the action window, and has blue made a move already?
switch(key){
case 'a':
BlueDragon.currentaction = 1; //A to fire
break;
case 's':
BlueDragon.currentaction = 2; //S to shield
break;
case 'd':
BlueDragon.currentaction = 3; //D to reload
break;
}
blueturn = false; //blue has spent its move
}
}
if(key == 'j' || key == 'k' || key == 'l'){ //is the pressed key a valid red action?
if(framecounter < actionwindow & redturn){ //is it within the action window, and has blue made a move already?
switch(key){
case 'j':
RedDragon.currentaction = 1; //A to fire
break;
case 'k':
RedDragon.currentaction = 2; //S to shield
break;
case 'l':
RedDragon.currentaction = 3; //D to reload
break;
}
redturn = false; //red has spent its move
}
}
}
//--------------------------------------- Dragon creation functions
function createDragon(startinghealth, startingammo, drdirection, drsprites) {
var dragon = {
health: startinghealth,
death: 0,
ammo: startingammo,
shield: false,
status: 0,
currentaction: 0, //action key: 0 = nonaction, 1 = shoot, 2 = shield, 3 = reload
opponentaction: 0,
direction: drdirection,
sprites: drsprites,
x: width/2 + drdirection*150, //where to render the sprite
y: 225,
Action: dragonAction, //processing gameplay
Result: dragonResult,
Reset: dragonReset,
GameOver: isAlive,
ActionRender: dragonActionRender,
ResultRender: dragonResultRender,
DefaultRender: dragonDefaultRender };
return dragon;
}
/*
status key:
0 = default
1 = attack
2 = shield
3 = reload
4 = impact
5 = shielded impact
6 = death (not real status)
*/
function dragonAction(){ //function to process dragon's action
switch(this.currentaction){ //processing currentaction
case 0: //if no action
break;
case 1: //if attacking
if(this.ammo == 0){
this.currentaction = 0; //if attempted to attack without ammo, will change to no action
}
else{
this.ammo--;
fire.play();
}
break;
case 2: //if shielding
this.shield = true;
break;
case 3: //if reloading
this.ammo++; //can reload indefinitely; reloads even if attacked
charge.play();
break;
}
this.ActionRender();
}
function dragonResult(){//function to process result of both dragon's actions
this.status = this.currentaction; //by default, status is the same as action
if(this.opponentaction == 1){ //unless attacked by other dragon
if(this.shield){
this.status = 5; //shield is up, attack is blocked
impact.play();
}
else{
this.status = 4;
this.health--; //otherwise, attack hits, takes damage
impact.play();
}
}
this.GameOver();
this.ResultRender();
}
function isAlive(){ //checks if dragon is alive or dead
if (this.health < 1){
this.death = 1;
growl.play();
}
else this.death = 0;
}
function dragonActionRender(){ //function to display the dragon
image(this.sprites[this.currentaction], this.x, this.y, 300, 225);
}
function dragonResultRender(){ //function to display the dragon
image(this.sprites[this.status], this.x, this.y, 300, 225);
}
function dragonDefaultRender(){
image(this.sprites[this.death*6], this.x, this.y, 300, 225); //renders either alive or dead state
}
function dragonReset(){ //resets the dragon actions and status to default at the end of the round
this.currentaction = 0;
this.status = 0;
this.opponentaction = 0;
this.shield = false;
}
(Using 1 Grace Day.)
(Recommend clicking the game to start it)
Dueling Dragons is the virtual, 1-computer-2-players version of the playground game “Shotgun”, in which players attempt to defeat their opponent by playing one of 3 moves (shoot, shield, reload) in accordance to a beat, usually clapping twice.
In my version, two dragons are fighting each other while “We Will Rock You”s stomp-stomp-clap plays; The final clap is starts a short time window in which both players can perform an action using the keys displayed.
Each player starts with 3 health and no ammo. Health is displayed, but ammo isn’t, for tactical reasons.
A player can make 4 moves:
0) no action (don’t press a key or press it out of the timing window); left vulnerable
1) attack; will expend an ammo only if there is any, otherwise will become no action
2) shield; protects the player from damage
3) reload; increases ammo by one, can increase indefinitely. A reload is still successful even if the player is damaged.
If both players are attacked, both of them will suffer damage
The game continues until at least one player’s health drops to zero, after which a win screen appears for 3 seconds, and then the page attempts to refresh (recommend manually refreshing the page)
Of course, there are sound effects!
]]>I am providing a zip file containing all the files involved in this project, available here: zip file .
There were too many files for the project to run adequately on word press. In order to run this program, the provided zip file must be downloaded, and a local server must be set up using either terminal in OSX or a command window in Windows. This would be accomplished by changing the directory to the file named Elizabeth Maday Final Project, and then typing in “python -m SimpleHTTPServer” or “python -m http.server”. Then the project can be viewed with the URL http://localhost:8000.
Sometimes this project seems to run better on Firefox than on Chrome.
This project was enjoyable to complete because it gave me an idea of what I might like to use p5 for in the future. I am interested in learning more about music technology and experimental methods of producing music, and I believe that p5 could be a great creative outlet.
]]>hi! welcome to my final project. please allow webcam access and sit in the center of your webcam for full effect. my project is a commentary on the artist John Baldessari. I have included a zip file below of my work as I am aware it may not run on WP. i will explain more and include photos of his work below:
/* Rani Randell
rrandell@andrew.cmu.edu
Section A
Final Project */
// please open in chrome and with your body centered in the middle of the webcam
var floatingText = 0
var cd = 80 //circle diameter for key pressed A
var myCamera;
function setup() {
createCanvas(640, 480);
myCamera = createCapture(VIDEO);
myCamera.size(640, 480);
myCamera.hide(); // attempt to size the camera.
}
function draw() {
image(myCamera, 0, 0);
myCamera.loadPixels();
// scrolling instructions along bottom of screen
noStroke();
fill('yellow');
rect(0, 400, 640, 200); //yellow bar with black scrolling writing
textSize(40);
textStyle(BOLD);
fill('black');
textFont('Courier New');
text('press keys a or b for a surprise', floatingText, 450);
floatingText = floatingText + 1
if (floatingText > 640) {
floatingText = -750
}
noStroke();
if (keyIsPressed) {
if ((key == 'a') || (key == 'A')) { //primary colored circles
fill('blue')
ellipseMode(CENTER);
ellipse(100, 100, cd, cd);
ellipse(200, 200, cd, cd);
ellipse(100, 200, cd, cd);
ellipse(200, 300, cd, cd);
ellipse(500, 100, cd, cd);
ellipse(600, 200, cd, cd);
ellipse(600, 300, cd, cd);
ellipse(450, 300, cd, cd);
ellipse(0, 0, cd, cd);
ellipse(0, 200, cd, cd);
ellipse(0, 300, cd, cd);
ellipse(450, 0, cd, cd);
ellipse(600, 0, cd, cd);
ellipse(260, 0, cd, cd);
ellipse(390, 0, cd, cd);
ellipse(80, 0, cd, cd);
ellipse(525, 260, cd, cd);
ellipse(200, 60, cd, cd);
ellipse(0, 150, cd, cd);
fill('yellow');
ellipse(0, 100, cd, cd);
ellipse(250, 70, cd, cd);
ellipse(200, 350, cd, cd);
ellipse(570, 290, cd, cd);
ellipse(480, 310, cd, cd);
ellipse(300, 0, cd, cd);
ellipse(640, 220, cd, cd);
ellipse(250, 300, cd, cd);
ellipse(0, 250, cd, cd);
ellipse(640, 0, cd, cd);
ellipse(210, 0, cd, cd);
ellipse(150, 210, cd, cd);
ellipse(470, 200, cd, cd);
ellipse(140, 120, cd, cd);
ellipse(600, 100, cd, cd);
ellipse(570, 30, cd, cd);
ellipse(120, 70, cd, cd);
ellipse(100, 350, cd, cd);
fill('red');
ellipse(0, 200, cd, cd);
ellipse(550, 330, cd, cd);
ellipse(550, 170, cd, cd);
ellipse(50, 170, cd, cd);
ellipse(175, 190, cd, cd);
ellipse(100, 300, cd, cd);
ellipse(640, 100, cd, cd);
ellipse(150, 0, cd, cd);
ellipse(510, 0, cd, cd);
ellipse(640, 290, cd, cd);
ellipse(450, 0, cd, cd);
ellipse(30, 77, cd, cd);
ellipse(460, 240, cd, cd);
ellipse(540, 50, cd, cd);
ellipse(160, 80, cd, cd);
ellipse(0, 350, cd, cd);
ellipse(450, 95, cd, cd);
ellipse(170, 280, cd, cd);
}
if ((key == 'b') || (key == 'B')) { //complementary colored circles
fill('orange');
ellipse(100, 100, cd, cd);
ellipse(200, 200, cd, cd);
ellipse(100, 200, cd, cd);
ellipse(200, 300, cd, cd);
ellipse(500, 100, cd, cd);
ellipse(600, 200, cd, cd);
ellipse(600, 300, cd, cd);
ellipse(450, 300, cd, cd);
ellipse(0, 0, cd, cd);
ellipse(0, 200, cd, cd);
ellipse(0, 300, cd, cd);
ellipse(450, 0, cd, cd);
ellipse(600, 0, cd, cd);
ellipse(260, 0, cd, cd);
ellipse(390, 0, cd, cd);
ellipse(80, 0, cd, cd);
ellipse(525, 260, cd, cd);
ellipse(200, 60, cd, cd);
ellipse(0, 150, cd, cd);
fill('purple');
ellipse(0, 100, cd, cd);
ellipse(250, 70, cd, cd);
ellipse(200, 350, cd, cd);
ellipse(570, 290, cd, cd);
ellipse(480, 310, cd, cd);
ellipse(300, 0, cd, cd);
ellipse(640, 220, cd, cd);
ellipse(250, 300, cd, cd);
ellipse(0, 250, cd, cd);
ellipse(640, 0, cd, cd);
ellipse(210, 0, cd, cd);
ellipse(150, 210, cd, cd);
ellipse(470, 200, cd, cd);
ellipse(140, 120, cd, cd);
ellipse(600, 100, cd, cd);
ellipse(570, 30, cd, cd);
ellipse(120, 70, cd, cd);
ellipse(100, 350, cd, cd);
fill('green');
ellipse(0, 200, cd, cd);
ellipse(550, 330, cd, cd);
ellipse(550, 170, cd, cd);
ellipse(50, 170, cd, cd);
ellipse(175, 190, cd, cd);
ellipse(100, 300, cd, cd);
ellipse(640, 100, cd, cd);
ellipse(150, 0, cd, cd);
ellipse(510, 0, cd, cd);
ellipse(640, 290, cd, cd);
ellipse(450, 0, cd, cd);
ellipse(30, 77, cd, cd);
ellipse(460, 240, cd, cd);
ellipse(540, 50, cd, cd);
ellipse(160, 80, cd, cd);
ellipse(0, 350, cd, cd);
ellipse(450, 95, cd, cd);
ellipse(170, 280, cd, cd);
}
}
}
below are some screen grabs of my working project, if for some reason the webcam isn’t working you can reference these! final 104 <- here is a zip file of my project as I am aware that it is not working on the WP.
John Baldessari is an artist who is most famous for his works where he took colored sticker dots and put them over the faces of people in photographs. This act is meant to be about erasure and obliteration. For my project I decided to flip that on its head and make it about erasing the background and focusing on the individuality. The duality of color (primary colors and their complement) are meant to emphasize individuality in humanity as wellBelow is a John Baldessari image to reference:
]]>
One image from the animation
Another image from the animation
My project is an interactive art form where a tree is decorated with ornaments in time with music playing in the background. The song that is playing is “Carol of the Bells” by the Trans Siberian Orchestra. However, since I used multiple js files for this project WordPress would not run the whole project. So I have attached a zip file to run all the files. Download and unzip the zip file. Then to look at the code, look at all the different js files. To look at the project, open the index. As long as the index is running in a browser that allows audio, the file should play correctly. Once the index is loaded, all that needs to be done to start the animation is click the mouse on the screen and the music should start playing.
]]>// Sara Frankel
// Final Project
// sfrankel
// Section A
var liftYourself;
var shostyTen;
var liftArray;
var fft;
var greatestWave;
var isPlaying;
var greatestOverall = 0;
var isLiftYourself;
function preload() {
shostyTen = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/shostakovich-symphony-no-10-mvt-2-gianandrea-noseda-london-symphony-orchestra.mp3");
liftYourself = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/Lift-Yourself.mp3");
}
function setup(){
var cnv = createCanvas(400, 400);
cnv.mouseClicked(togglePlay); //plays the canvas when clicked
fft = new p5.FFT();
liftYourself.amp(0.2);
shostyTen.amp(1);
isPlaying = false;
isLiftYourself = true;
}
function draw(){
background(0);
var spectrum = fft.analyze(); //uses FFT to use the "spectrum" of sound (i.e. the eyebrows)
var waveform = fft.waveform(); //uses FFT to use the waveform of the sound (i.e. the squiggled hair)
noStroke();
//draw variable to keep track of the greatest wave to give the "pulse" effect
greatestWave = 0;
for (i = 0; i < waveform.length; i++) {
if(waveform[i] > greatestWave) {
greatestWave = waveform[i];
}
}
//takes greatest overal wave value and stores it as greatest wave
if(greatestWave > greatestOverall){
greatestOverall = greatestWave;
}
//uses map use the value of the greatest wave of the sound and put it on a scale for color
fill(map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 0, 0));
//draws the "hair" of the eyebrow when turned on
//left eyebrow
for (var i = 0; i < spectrum.length; i++){
var x = map(i, 0, spectrum.length, 0, width / 3); //maps i on the length of the spectrum variable
var h = -height + map(spectrum[i], 0, 255, height, 0); //maps position in the spectrum array to allow height
rect(x + width * 0.75 - 50, height / 4 + 35, width / spectrum.length, h / 4);
}
//right eyebrow
for (var i = 0; i < spectrum.length; i++){
var x = map(i, 0, spectrum.length, width / 3, 0);
var h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x + 15, height / 4 + 20, width / spectrum.length, h / 4);
}
//draws base of eyebrows
stroke(255);
line(width / 4, height / 4 + 20, width / 4 + 50, height / 4 + 20);
line(width * 0.75 - 50, height / 4 + 35, width * 0.75, height / 4 + 35);
noFill();
//draw eyeballs
var y = map(greatestWave, -1, 1, 0, height); //allows for the eyes and head to pulse
ellipse(width / 4 + 20, height / 4 + 60, y / 3, y / 3);
ellipse(width * 0.75 - 20, height * 0.25 + 60, y / 6, y / 6);
//draws head
ellipse(width / 2, height / 2, y * 1.5, y * 1.5);
//calls that if the audio is playing, the color of hair and eyes change to the music
if(isPlaying) {
fill(map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 255, 0));
stroke(map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 255, 0));
} else {
noFill();
stroke(255);
}
//uses drawHairAtAngle function to draw the hair on the head that follows the pulse of the head (stays in spot with music)
drawHairAtAngle(-14 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-12 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-10 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-8 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-6 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-4 * PI / 18, y * 0.75, waveform);
//allows eyes to follow mouse, drawing eyeballs
var eX = map(mouseX, 0, y, -1, 1);
var eY = map(mouseY, 0, y, -1, 1);
ellipse(eX + width / 4 + 20, eY + height / 4 + 60, 40, 40);
ellipse(eX / 2 + width * 0.75 - 20, eY / 2 + height * 0.25 + 60, 20, 20);
//states that if playing, the color of the mouth and eyebrows change color
if(isPlaying) {
stroke(map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 0, 0));
} else {
stroke(255);
}
//draws mouth
for (var i = 0; i < waveform.length; i++){
var x = map(i, 0, waveform.length, width/4, width * 0.75);
var y = map(waveform[i], -1, 1, 0, height);
line(width / 2, y + 50, x, height / 2 + 50);
}
//displays instructions of the canvas and which song is playing
stroke(255);
noFill();
text('Click to play or pause - Press space to change song', 60, 15);
if(isLiftYourself) {
text("Kanye West - Lift Yourself", width - 150, height - 10);
} else {
text('Dmitri Shostakovich - Symphony No. 10 Second Movement', width - 360, height - 10);
}
}
// fade liftYourself if mouse is over canvas
function togglePlay() {
//if statement that allows for each song to play and not overlap another and still alows for the click to play/stop to work
if(isLiftYourself){
if (liftYourself.isPlaying()) {
liftYourself.pause();
isPlaying = false;
} else {
shostyTen.pause();
liftYourself.loop();
isPlaying = true;
}
} else {
if (shostyTen.isPlaying()) {
shostyTen.pause();
isPlaying = false;
} else {
liftYourself.pause();
shostyTen.loop();
isPlaying = true;
}
}
}
//object that helps to draw the hair along the head
function drawHairAtAngle(angle, rad, waveform) {
beginShape();
for (var i = 0; i < waveform.length; i++) {
//uses map to place the hairs along the radius of the circle evenly spaced
var hairY = map(i, 0, waveform.length, sin(angle) * rad + height / 2, sin(angle) * (rad) + height / 2 - 25);
var hairX = map(waveform[i], -0.5, 0.5, cos(angle) * (rad - 25) + width / 2, cos(angle) * (rad + 25) + width / 2);
vertex(hairX, hairY);
}
endShape();
}
//function to switch songs if space bar is clicked
function keyTyped() {
if(key === ' ') {
isLiftYourself = !isLiftYourself;
togglePlay();
}
}
For this project, I decided to visualize music. My first vision at this project was something more abstract, but as I was creating the project I felt it to be more fun to have a face. This face visualizes music in the sense that all aspects of it “dance” to the music. The eyebrows raise, the hair squiggles, and the mouth draws lines to give the effect of singing. What I wanted to prove in this project is that not only is Kanye West “boppable” to, but so can classical music. The image posted below is a screen shot taken from the Shostakovich.
The instructions for this project are:
To play click the canvas
To change the song click space
To dance along (with the eyes) move the mouse!
Hope you enjoy!
if code does not work correctly, here is the zip.file for it!
https://drive.google.com/file/d/1O-X48r1iUjrtR_PWghS4f_l9hLtnG8Vf/view?usp=sharing
PRESS ENTER
sketch
/* Name : Jonathon Liang / Curran Zhang
AndrewID : Jliang2 / Curranz
Section : Section A
Final Project
*/
var terrainSpeed1 = 0.0002;
var terrainDetail1 = 0.015;
var terrainSpeed2 = 0.0004;
var terrainDetail2 = 0.008;
var clouds = [];
var star = [];
var frames = [];
var HeadX = 260;
var HeadY = 325;
var ReflectionY =385
var step= 6;
var machox = 480;
var machoy = 300;
var girlx = 480;
var girly = 340;
var nekx = 480;
var neky = 240;
var towelx = 480;
var towely = 200;
var birdiex = 480;
var birdiey = 300;
function setup() {
createCanvas(480, 480);
//Iniate Clouds
for (var i = 0; i <5; i++) {
var r = random(width);
clouds[i] = makeClouds(r);
}
//Head Image Position
imageMode(CENTER);
frameRate(15);
}
function preload(){
//Cats
cat1 = loadImage("https://i.imgur.com/7hCkrYr.png");
cat2 = loadImage("https://i.imgur.com/TWXWeM0.png");
cat3 = loadImage("https://i.imgur.com/kRxHYt0.png");
cat4 = loadImage("https://i.imgur.com/kkpAzvD.png");
cat5 = loadImage("https://i.imgur.com/Hf9rTYl.png");
birdie = loadImage("https://i.imgur.com/RdcS35J.png");
//Head
var filenames = [];
filenames[0] = "https://i.imgur.com/leN6UXu.png";
filenames[1] = "https://i.imgur.com/dydccNf.png";
filenames[2] = "https://i.imgur.com/dcoiGqR.png";
filenames[3] = "https://i.imgur.com/wez5P2S.png";
filenames[4] = "https://i.imgur.com/9etlno8.png";
filenames[5] = "https://i.imgur.com/yrjv4XT.png";
filenames[6] = "https://i.imgur.com/hW3gKH6.png";
filenames[7] = "https://i.imgur.com/Jg0yJck.png";
filenames[8] = "https://i.imgur.com/dU1rruI.png";
for (var i = 0; i < filenames.length; i++) {
frames.push(loadImage(filenames[i]));
}
}
function draw() {
//Gradient Background
var from = color(250,0,0);
var to = color(270);
gradient(0,width,from,to);
rect(0,0,480,480);
makeMountain1();
makeMoon();
makeStar();
makeMountain1();
makeMountain2();
makeReflection();
updateClouds();
removeClouds();
addClouds();
strokeWeight(.5);
stroke(255);
text("early head gets the bird", 10, 15);
text("touch a cat, you'll be sad", 10, 30);
text("fly too high, and you'll die", 10, 45);
makeHead();
makeCat();
}
function gradient(y,w,from,to){
for (var i = y; i <= height; i++) {
var inter = map(i,y,y+w,0,1);
var col = lerpColor(from,to,inter);
stroke(col);
strokeWeight(2);
line(y,i,y+w,i);
}
}
function makeStar(){
fill(270);
for (var i = 0; i < 100; i++) {
var starX = random(width);
var starY = random(height);
ellipse(starX,starY,1,1);
}
}
function makeMountain1(){
noStroke();
fill(180,0,0);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
var y = map(noise(t), 0,1.8, height/8, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMountain2(){
fill(139,0,0);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height/2, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeReflection(){
fill(220,50,50);
rect(0, 375, width, 105);
fill(255,60,60);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height, height*.5);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMoon(){
noStroke();
fill(255,20);
ellipse(2*width/3,height/4,170,170);
ellipse(2*width/3,height/4,160,160);
ellipse(2*width/3,height/4,150,150);
ellipse(2*width/3,height/4,140,140);
fill(255,200);
ellipse(2*width/3,height/4,120,120);
}
function updateClouds(){
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].display();
}
}
function removeClouds(){
var keepClouds = [];
for (var i = 0; i < clouds.length; i++) {
if (clouds[i].x + clouds[i].breadth > 0) {
keepClouds.push(clouds[i]);
}
}
clouds= keepClouds;
}
function addClouds(){
var newCloud = .007;
if (random(0,1)<newCloud) {
clouds.push(makeClouds(width))
}
}
function cloudMove(){
this.x += this.speed;
}
function displayClouds(){
fill(255,50);
noStroke();
ellipse(this.x,this.y,this.width,this.height);
ellipse(this.x +10,this.y +10,this.width-10,this.height-10);
ellipse(this.x +20,this.y -10,this.width/2,this.height/2);
ellipse(this.x -20,this.y ,this.width-20,this.height-10);
}
function makeClouds(cloudy){
var cloud= {x: cloudy,
y:random(100, height/2),
speed: random(-.2,-.7),
width: random(50,100),
height:random(20,0),
breadth:50,
move:cloudMove,
display:displayClouds
}
return cloud;
}
function makeHead(){
//Main Head
push();
translate(HeadX,HeadY);
scale(.2,.2);
image(frames[frameCount % 8], 0, 0);
pop();
//Reflection
push();
translate(HeadX,ReflectionY);
scale(.2,-.2);
tint(255,127);
image(frames[frameCount % 8], 0, 0);
pop();
if (keyIsDown(ENTER)){
HeadY -= step;
ReflectionY += step;
} else { HeadY += step;
HeadY = min(HeadY, 350);
ReflectionY -= step;
ReflectionY = max(ReflectionY,405);
}
if (HeadY <= 100) {gameOver()};
}
function makeCat(){
//MachoCat
push();
translate(machox,machoy);
scale(.2,.2);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {lmachox = 480};
pop();
if (HeadX + 30 > machox & HeadX-30 < machox && machoy > HeadY && HeadY > machoy - 30) {
gameOver()};
//MachoCat Reflection
push();
translate(machox,419);
scale(.2,-.2);
tint(265,160);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {machox = 480};
pop();
//School Girl
push();
translate(girlx,girly);
scale(.18,.18);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
if (HeadX + 30 > girlx & HeadX-30 < girlx && girly > HeadY && HeadY > girly - 30) {
gameOver();}
//School Girl Reflection
push();
translate(girlx,409);
scale(.18,-.18);
tint(265,160);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
//Neka
push();
translate(nekx,neky);
scale(.6,.6);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx= 480};
pop();
if (HeadX + 30 > nekx & HeadX-30 < nekx && neky + 40 > HeadY && HeadY > neky - 10) {
gameOver()};
//Neka Reflection
push();
translate(nekx,509);
scale(.6,-.6);
tint(265,160);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx = 480};
pop();
//Towel
push();
translate(towelx,towely);
scale(.15,.15);
image(cat5, 0,0);
towelx-=5.05;
if (towelx < 0) {towelx = 480};
pop();
if (HeadX + 30 > towelx & HeadX-30 < towelx && towely > HeadY && HeadY > towely - 30) {
gameOver()};
//Birdie
push();
translate(birdiex,birdiey);
scale(-.15,.15);
image(birdie, 0,0);
birdiex-=5.05;
if (birdiex < 0) {birdiex = 480};
if (birdiey+30 > HeadY & HeadY> birdiey-30 && HeadX+30 > birdiex && HeadX-30 < birdiex) {
birdiex=480};
pop();
}
function gameOver() {
fill(0);
textSize(75);
textAlign(CENTER);
textStyle(BOLD);
text("GAME OVER", 240, 240);
noLoop();
}
For the final project, me and Jonathon decided to base our project off of the game Battle Cat. Our original idea was to do a health system for the floating head and have the cats slowly chip off the health. However, that was not doable within our available time. Therefore, we toned down and the goal of the game is to bypass the white cats and try to collect the red bird as much as possible. Flying to high into the sky would also be an instant game over. Over the course of this project, we tried to incorporate as much as we can into it. Ranging from images, array, moving terrain, and objects.
]]>/* Name : Jonathon Liang / Curran Zhang
AndrewID : Jliang2 / Curranz
Section : Section A
Final Project
*/
var terrainSpeed1 = 0.0002;
var terrainDetail1 = 0.015;
var terrainSpeed2 = 0.0004;
var terrainDetail2 = 0.008;
var clouds = [];
var star = [];
var frames = [];
var HeadX = 260;
var HeadY = 325;
var ReflectionY =385
var step= 6;
var machox = 480;
var machoy = 300;
var girlx = 480;
var girly = 340;
var nekx = 480;
var neky = 240;
var towelx = 480;
var towely = 200;
var birdiex = 480;
var birdiey = 300;
function setup() {
createCanvas(480, 480);
//Iniate Clouds
for (var i = 0; i <5; i++) {
var r = random(width);
clouds[i] = makeClouds(r);
}
//Head Image Position
imageMode(CENTER);
frameRate(15);
}
function preload(){
//Cats
cat1 = loadImage("https://i.imgur.com/7hCkrYr.png");
cat2 = loadImage("https://i.imgur.com/TWXWeM0.png");
cat3 = loadImage("https://i.imgur.com/kRxHYt0.png");
cat4 = loadImage("https://i.imgur.com/kkpAzvD.png");
cat5 = loadImage("https://i.imgur.com/Hf9rTYl.png");
birdie = loadImage("https://i.imgur.com/RdcS35J.png");
//Head
var filenames = [];
filenames[0] = "https://i.imgur.com/leN6UXu.png";
filenames[1] = "https://i.imgur.com/dydccNf.png";
filenames[2] = "https://i.imgur.com/dcoiGqR.png";
filenames[3] = "https://i.imgur.com/wez5P2S.png";
filenames[4] = "https://i.imgur.com/9etlno8.png";
filenames[5] = "https://i.imgur.com/yrjv4XT.png";
filenames[6] = "https://i.imgur.com/hW3gKH6.png";
filenames[7] = "https://i.imgur.com/Jg0yJck.png";
filenames[8] = "https://i.imgur.com/dU1rruI.png";
for (var i = 0; i < filenames.length; i++) {
frames.push(loadImage(filenames[i]));
}
}
function draw() {
//Gradient Background
var from = color(250,0,0);
var to = color(270);
gradient(0,width,from,to);
rect(0,0,480,480);
makeMountain1();
makeMoon();
makeStar();
makeMountain1();
makeMountain2();
makeReflection();
updateClouds();
removeClouds();
addClouds();
strokeWeight(.5);
stroke(255);
text("early head gets the bird", 10, 15);
text("touch a cat, you'll be sad", 10, 30);
text("fly too high, and you'll die", 10, 45);
makeHead();
makeCat();
}
function gradient(y,w,from,to){
for (var i = y; i <= height; i++) {
var inter = map(i,y,y+w,0,1);
var col = lerpColor(from,to,inter);
stroke(col);
strokeWeight(2);
line(y,i,y+w,i);
}
}
function makeStar(){
fill(270);
for (var i = 0; i < 100; i++) {
var starX = random(width);
var starY = random(height);
ellipse(starX,starY,1,1);
}
}
function makeMountain1(){
noStroke();
fill(180,0,0);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
var y = map(noise(t), 0,1.8, height/8, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMountain2(){
fill(139,0,0);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height/2, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeReflection(){
fill(220,50,50);
rect(0, 375, width, 105);
fill(255,60,60);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height, height*.5);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMoon(){
noStroke();
fill(255,20);
ellipse(2*width/3,height/4,170,170);
ellipse(2*width/3,height/4,160,160);
ellipse(2*width/3,height/4,150,150);
ellipse(2*width/3,height/4,140,140);
fill(255,200);
ellipse(2*width/3,height/4,120,120);
}
function updateClouds(){
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].display();
}
}
function removeClouds(){
var keepClouds = [];
for (var i = 0; i < clouds.length; i++) {
if (clouds[i].x + clouds[i].breadth > 0) {
keepClouds.push(clouds[i]);
}
}
clouds= keepClouds;
}
function addClouds(){
var newCloud = .007;
if (random(0,1)<newCloud) {
clouds.push(makeClouds(width))
}
}
function cloudMove(){
this.x += this.speed;
}
function displayClouds(){
fill(255,50);
noStroke();
ellipse(this.x,this.y,this.width,this.height);
ellipse(this.x +10,this.y +10,this.width-10,this.height-10);
ellipse(this.x +20,this.y -10,this.width/2,this.height/2);
ellipse(this.x -20,this.y ,this.width-20,this.height-10);
}
function makeClouds(cloudy){
var cloud= {x: cloudy,
y:random(100, height/2),
speed: random(-.2,-.7),
width: random(50,100),
height:random(20,0),
breadth:50,
move:cloudMove,
display:displayClouds
}
return cloud;
}
function makeHead(){
//Main Head
push();
translate(HeadX,HeadY);
scale(.2,.2);
image(frames[frameCount % 8], 0, 0);
pop();
//Reflection
push();
translate(HeadX,ReflectionY);
scale(.2,-.2);
tint(255,127);
image(frames[frameCount % 8], 0, 0);
pop();
if (keyIsDown(ENTER)){
HeadY -= step;
ReflectionY += step;
} else { HeadY += step;
HeadY = min(HeadY, 350);
ReflectionY -= step;
ReflectionY = max(ReflectionY,405);
}
if (HeadY <= 100) {gameOver()};
}
function makeCat(){
//MachoCat
push();
translate(machox,machoy);
scale(.2,.2);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {lmachox = 480};
pop();
if (HeadX + 30 > machox & HeadX-30 < machox && machoy > HeadY && HeadY > machoy - 30) {
gameOver()};
//MachoCat Reflection
push();
translate(machox,419);
scale(.2,-.2);
tint(265,160);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {machox = 480};
pop();
//School Girl
push();
translate(girlx,girly);
scale(.18,.18);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
if (HeadX + 30 > girlx & HeadX-30 < girlx && girly > HeadY && HeadY > girly - 30) {
gameOver();}
//School Girl Reflection
push();
translate(girlx,409);
scale(.18,-.18);
tint(265,160);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
//Neka
push();
translate(nekx,neky);
scale(.6,.6);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx= 480};
pop();
if (HeadX + 30 > nekx & HeadX-30 < nekx && neky + 40 > HeadY && HeadY > neky - 10) {
gameOver()};
//Neka Reflection
push();
translate(nekx,509);
scale(.6,-.6);
tint(265,160);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx = 480};
pop();
//Towel
push();
translate(towelx,towely);
scale(.15,.15);
image(cat5, 0,0);
towelx-=5.05;
if (towelx < 0) {towelx = 480};
pop();
if (HeadX + 30 > towelx & HeadX-30 < towelx && towely > HeadY && HeadY > towely - 30) {
gameOver()};
//Birdie
push();
translate(birdiex,birdiey);
scale(-.15,.15);
image(birdie, 0,0);
birdiex-=5.05;
if (birdiex < 0) {birdiex = 480};
if (birdiey+30 > HeadY & HeadY> birdiey-30 && HeadX+30 > birdiex && HeadX-30 < birdiex) {
birdiex=480};
pop();
}
function gameOver() {
fill(0);
textSize(75);
textAlign(CENTER);
textStyle(BOLD);
text("GAME OVER", 240, 240);
noLoop();
}
It all starts with an idea, but you can never tell where an idea can end up. Because ideas spread, they change, they grow, they connect us with the world. And in a fast-moving world, where good news moves at the speed of time and bad news isn’t always what is seems. Because when push comes to shove, we all deserve a second chance, to score.
For our Final Project Curran and I wanted to create a game that closely resembled our favorite mobile app game Battle Cats. But in our game we made it so that our protagonist cannot touch any of the white cats and has to try to eat the red chicken. The instructions are as followed: eat the chicken, avoid the white cats, and don’t fly too high; otherwise the game is over. Press enter to make the face move up.
Hope y’all enjoy.
]]>//Judy Li
//Section A
//judyli@andrew.cmu.edu
//Final Project
var yA = 1; //y-Axis
var c1; //color 1
var c2; //color 2
var x = [];
var gravity = 0.3; //downward acceleration
var springy = 1; //how much velocity is retained after bounce
var drag = 0.0001; //drag causes particles to slow down
var np = 25; //how many particles
var paperbirds = [];
function soot() {
background(204, 174, 98);
noStroke();
fill("pink");
ellipse(30, 30, 10, 10);
fill(186, 220, 88);
ellipse(25, 25, 10, 10);
fill(126, 214, 223);
ellipse(25, 40, 10, 10);
fill("coral");
ellipse(30, 35, 10, 10);
fill(224, 86, 253);
ellipse(40, 30, 10, 10);
fill("white");
ellipse(40, 40, 10, 10);
fill(0);
for (var i = 0; i < np; i++) {
//make a particle
var p = makeParticle(200, 200, random(-50, 50), random(-50, 50));
}
frameRate(10);
sootDraw();
}
function sootDraw() {
if (mouseIsPressed) {
var newp = makeParticle(mouseX, mouseY, random(-10, 10), random(-10, 0), random(0, 50));
particles.push(newp);
}
newParticles = [];
for (var i = 0; i < particles.length; i++) { // for each particle
var p = particles[i];
p.step();
p.draw();
if (p.age < 200) {
newParticles.push(p);
}
}
particles = newParticles;
}
function birds() {
setGradient(0, 0, width, height, c1, c2, yA);
drawClouds();
nBird();
nPosition();
nArray();
for (var i = 0; i < paperbirds.length; i++) {
paperbirds[i].display();
}
frameRate(10);
paperbirds.push(drawBirds());
}
function nBird() {
if (random(50, 50) < 50) {
paperbirds.push(drawBirds());
}
}
function nPosition() {
for (var i = 0; i < paperbirds.length; i++) {
paperbirds[i].move();
}
}
function nArray() {
var ogBird = [];
for (var i = 0; i < paperbirds.length; i++) {
if (paperbirds[i].x > 0) {
ogBird.push(paperbirds[i]);
}
}
paperbirds = ogBird;
}
function moveBird() {
this.x -= this.speed;
}
function seeBird() {
stroke(225, 255, 255, 200);
strokeWeight(random(1, 5));
point(this.x, this.y);
point(this.x + 2.5, this.y);
}
function drawBirds() {
var paperbirds = {x: width,
pdist: 100,
speed: 5,
birdsize: round(random(0, 5)),
y: round(random(0, height)),
move: moveBird,
display: seeBird
}
return paperbirds;
}
function drawClouds() {
noStroke();
//cloud1
fill(255, 255, 255, 200);
ellipse(75, 75, 80, 50);
ellipse(185, 75, 100, 60);
ellipse(135, 75, 115, 75);
//cloud2
ellipse(240, 200, 70, 50);
ellipse(380, 200, 100, 55);
ellipse(420, 200, 75, 30);
ellipse(300, 200, 120, 75);
//cloud3
ellipse(120, 360, 100, 40);
ellipse(240, 360, 80, 50);
ellipse(300, 360, 75, 30);
ellipse(180, 360, 120, 75);
}
function particleStep() {
this.age++;
this.x += this.dx;
this.y += this.dy;
if (this.x > width) { // bounce off right wall
this.x = width - (this.x - width);
this.dx = -this.dx * springy;
} else if (this.x < 0) { // bounce off left wall
this.x = this.x;
this.dx = -this.dx * springy;
}
if (this.y > height) { // bounce off bottom
this.y = height - (this.y - height);
this.dy = -this.dy * springy;
} else if (this.y < 0) { // bounce off top
this.y = -this.y;
this.dy = -this.dy * springy;
}
this.dy = this.dy + gravity; // force of gravity
// drag is proportional to velocity squared
// which is the sum of the squares of dy and dy
var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
// d is the ratio of old velocty to new velocity
var d = vs * drag;
// d goes up with velocity squared but can never be
// so high that the velocity reverses, so limit d to 1
d = min(d, 1);
// scale dx and dy to include drag effect
this.dx *= (1 - d);
this.dy *= (1 - d);
var rpx = width;
var rpy = height;
var f;
var d;
var rpc = 10;
var x = this.x;
var y = this.y;
var dirx = (x - rpx) / d;
var diry = (y - rpy) / d;
d = dist(x, y, rpx, rpy);
f = rpc / (Math.pow(d, 2));
this.dx += dirx * f;
this.dy += diry * f;
point(rpx, rpy);
}
function particleDraw() {
noStroke();
fill(0);
ellipse(this.x, this.y, this.size, this.size);
}
function setSize() {
return random(5, 25);
}
function makeParticle(px, py, pdx, pdy, size) {
p = {x: px, y: py,
dx: pdx, dy: pdy,
size: setSize(),
age: 0,
step: particleStep,
draw: particleDraw
}
return p;
}
var particles = [];
function setup() {
createCanvas(480, 480);
//colors
c1 = color(129, 236, 236);
c2 = color(255, 234, 167);
}
function draw() {
setGradient(0, 0, width, height, c1, c2, yA);
placeForeground();
if (mouseX < (width / 2) & mouseY < height) {
soot();
}
if (mouseX > (width / 2) & mouseY < height) {
birds();
}
}
function placeForeground() {
noStroke();
//chim
fill(150);
quad(20, height, 30, 100, 50, 100, 60, height);
fill(0);
rect(30, 90, 20, 10);
//big red
fill(255, 82, 82);
rect(90, 145, 300, 250);
//grey
fill(175);
rect(80, 160, 80, 45);
rect(100, 250, 60, 45);
rect(315, 200, 90, 50);
//top red
fill(225, 82, 82);
rect(110, 60, 260, 40);
//mini rooms
fill(205);
rect(85, 170, 70, 30);
rect(105, 260, 50, 30);
rect(320, 210, 80, 35);
rect(95, 105, 290, 40);
//green
fill(120, 180, 143);
quad(75, 165, 85, 155, 155, 155, 165, 165);
quad(95, 255, 105, 245, 155, 245, 165, 255);
quad(310, 205, 320, 195, 400, 195, 410, 205);
quad(80, 110, 100, 100, 380, 100, 400, 110);
quad(90, 65, 200, 15, 280, 15, 390, 65);
//bottom brown
fill(139, 69, 19);
rect(190, 280, 100, 12.5);
rect(75, 205, 90, 7.5);
rect(95, 295, 70, 7.5);
rect(310, 250, 100, 7.5);
//top brown
fill(250, 211, 144);
rect(200, 200, 80, 80);
//outer red
fill(200, 57, 57);
rect(60, 330, 130, 100);
rect(290, 330, 130, 100);
//main entrance
fill(250, 211, 144);
rect(190, 325, 100, 50);
//teal
fill(120, 200, 143);
quad(180, 325, 200, 315, 280, 315, 300, 325);
quad(180, 210, 210, 180, 270, 180, 300, 210);
//sign
fill(255, 240, 195);
ellipse(240, 180, 40, 20);
ellipse(240, 15, 50, 25);
ellipse(240, 315, 60, 10);
//noStroke();
fill(204, 174, 98);
stroke(204, 174, 98);
quad(0, width, width / 3, 360, 2 * (width / 3), 360, width, height);
stroke(204, 142, 25);
line(width / 3, 450, (2 * (width / 3)) + 140, 450);
line((width / 3) - 140, 465, 2 * (width / 3), 465);
stroke(179, 57, 57);
strokeWeight(1);
fill(179, 57, 57);
triangle(0, height, 0, height - 45, 120, 369);
triangle(width, height, width, height - 45, 360, 369);
beginShape();
curveVertex(0, height);
curveVertex(0, height);
curveVertex(35, 430);
curveVertex(72.5, 395);
curveVertex(115, 370);
curveVertex(width / 3, 360);
curveVertex(width / 3, 360);
endShape();
beginShape();
curveVertex(2 * (width / 3), 360);
curveVertex(2 * (width / 3), 360);
curveVertex(365, 370);
curveVertex(407.5, 395);
curveVertex(445, 430);
curveVertex(width, height);
curveVertex(width, height);
endShape();
}
function setGradient(x, y, w, h, c1, c2, axis) {
noFill();
if (axis == yA) {//top > bottom gradient
for (var i = y; i <= y + h; i++) {
var inter = map(i, y, y + h, 0, 1);
var c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x + w, i);
}
}
}
For the final project, I wanted to recreate three of my favorite scenes in the movie, Spirited Away. The first scene shows bridge and the exterior of the bath house. Since this building is famous in the movie, I wanted to start my project out with this first background image. When you move you mouse in the left hand side within the bounding box, it moves onto a new background/scene. This scene is the part when Chihiro is interacting with the soot creatures. She throws candy onto a corner of the floor so that the soot would get away from her. To go back to the original/first scene, you would just move your mouse down and out of the bounding box. And for the third scene, I remade the part that shows the flying paper birds through a simple animation. I really enjoyed that scene because it was really aesthetically filmed/made in the movie and I wanted to incorporate that.
]]>/*
Katherine Hua, Min Lee
Section A
khua@andrew.cmu.edu, mslee@andrew.cmu.edu
Final Project
*/
var characters = []; // images of the characters are loaded into this array
var mushroom; // image of mushroom that represents # of lives left is loaded into this variable
var cloud; // image of cloud is loaded into this variable
var cloudsX = []; //cloud's randomized x positions will be loaded into this array
var cloudsY = []; //cloud's randomized y positions will be loaded into this array
var cloudsSpeed = []; // cloud's randomized speed will be loaded into this array
var gameMode = 0; // determines which screen you see; title screen = 0, game = 1, game over = 2, instructions = 3
var lives = 3; // you start out with 3 lives
var score = 0; // you begin with a score of 0
var characterIndex; //assigns a number value to a character
var pipeNumber; // //assigns each pipe a number value
var characterX; //keeps track of the character's X values
var characterY = 180; //keeps track of the character's Y values
var characterSpeed = -3; // //keeps track of the character's speed
var pipesOccupied; //the pipe number that's occupied by a character
var newIndex; //new number value assigned to character
function preload() {
//links of character images
var characterImages = [];
mushroom = loadImage("https://i.imgur.com/V1vjvug.png"); //mushroom that is meant to represent # of lives
cloud = loadImage("https://i.imgur.com/7PCTEzk.png"); //clouds that will be floating by in the background
characterImages[0] = "https://i.imgur.com/Bf9U7OE.png"; //mario
characterImages[1] = "https://i.imgur.com/s7o5h2m.png"; //peach
characterImages[2] = "https://i.imgur.com/xQqZiZb.png"; //toad
characterImages[3] = "https://i.imgur.com/0bcsmDZ.png"; //bowser
characterImages[4] = "https://i.imgur.com/Wv9Dkzj.png"; //wario
characterImages[5] = "https://i.imgur.com/AkWIiIw.png"; //boo
//initial cloud positions
for (var i = 0; i < 4; i++) {
//setting the clouds to random initial positions
cloudsX[i] = width + i * 50;
cloudsY[i] = random(0, 130);
cloudsSpeed[i] = random(0.25, 1); // moving the clouds at a randomized speed between 0.25 and 1
};
//load images of characters into characters array
//allows for object to change characters
characters[0] = loadImage(characterImages[0]);
characters[1] = loadImage(characterImages[1]);
characters[2] = loadImage(characterImages[2]);
characters[3] = loadImage(characterImages[3]);
characters[4] = loadImage(characterImages[4]);
characters[5] = loadImage(characterImages[5]);
}
function setup() {
createCanvas(600, 400);
//random positions of character
pipeNumber = round(random(0, 5)); //randomly chooses which pipe the character will appear at
pipesOccupied = pipeNumber; //corresponding pipe number
characterX = width / 7 * (pipeNumber + 1) + 60; //character's x position that will determine their corresponding pipe
characterIndex = round(random(0, 5)); //randomly chooses which character will appear
}
function draw() {
background(21, 30, 99); // setting background to the blue
//creating the clouds; just loading the image onto the canvas; they do not move here yet
for (var i = 0; i < 4; i++) {
image(cloud, cloudsX[i], cloudsY[i]);
};
displayHill(); // creating the hill landscape moving in the background
//part of the Title Screen
//images of characters spread out across title screen
if (gameMode === 0) {
for (var x = 0; x < 6; x++) {
image(characters[x], (width/7 * (x+1)) - (width / 7 / 2) + 10, 110);
}
}
gameScreen(); // this is the actual game
displayChutes(); // creates the green chutes/pipes
displayGround(); // creates the criss-crossed red brick ground
titleScreen(); // this is the starting, default screen
drawScoreTally(); // keeps track of the score in gameScreen and gameOverScreen
instructionsScreen(); // instructions screen
displayButtons(); // creates the buttons in the actual game part
gameOverScreen(); // the game over screen after you lose all your lices
//clouds are made to move here at randomized speeds
for (var i = 0; i < cloudsX.length; i++) {
cloudsX[i] -= cloudsSpeed[i];
if (cloudsX[i] < -60) {
cloudsX[i] = width;
};
};
}
function drawScoreTally() {
if (gameMode === 1) { // we only want this visual element to appear in the gameScreen
push();
//making the yellow rectangle where the score will be kept
fill(181, 141, 38);
strokeWeight(2);
stroke(255, 229, 163);
rectMode(CENTER);
rect(width / 2, 35, 70, 20, 3);
noStroke();
//adding the actual text on top of the rectangle
fill(255,229, 163);
textAlign(CENTER);
text("Score:" + " " + score, width / 2, 40)
//text saying that if user wishes to restart the game at any point, the user can just press the key 'x' to restart the game
text("Press 'x' to restart game", width/2, 60);
pop();
};
}
//creating the generative hill landscape in the background of the game
function displayHill() {
var hill = 0.006
var hillSec = 0.0007;
push();
stroke(25, 83, 19);
beginShape();
for (i = 0; i < width; i ++) {
var h = (millis() * hillSec) + (i * hill);
var y = map(noise(h), 0, 1, 200, 100);
line(i, y, i, height);
}
endShape();
pop();
}
// creating the brick ground
function displayGround() {
push();
strokeWeight(2);
stroke(211, 71, 71);
fill(181, 38, 38);
rectMode(CORNER);
rect(0, 260, 600, 400-260);
for (var k = 0; k < 60; k ++) {
line(k * 10, 260, k * 10, 400);
line(0, 260 + k * 10, 600, 260 + k * 10);
}
pop();
}
//creating the green chutes/pipes
function displayChutes() {
if (gameMode === 0 || gameMode === 1 || gameMode === 3) { //we want the chutes/pipes to appear in all screens except the game over screen
push();
//creating 6 chutes/pipes
for (var j = 1; j < 7; j++) {
rectMode(CENTER); //drawing rectangles from the center rather than the corner
fill(43, 130, 58);
strokeWeight(3);
stroke(81, 163, 95);
rect((width/7) * j, 220, 65, 80, 2); //body of the chute
rect((width/7) * j, 200, 75, 40, 2); //head of the chute
strokeWeight(7);
//giving the pipes the highlight on their left side
line(55 + (width/7 * (j-1)), 186, 55 + (width/7 * (j-1)), 215);
line(60 + (width/7 * (j-1)), 225, 60 + (width/7 * (j-1)), 255);
}
pop();
}
}
function titleScreen() {
push();
if (gameMode === 0 || gameMode === 3) { // we want the title screen to appear in title screen and instructions screen
//creating title of the game: "Pipe it Up"
stroke(155, 115, 0);
strokeWeight(8);
fill(255, 203, 57);
textAlign(CENTER);
textSize(70);
textFont('arial')
text("PIPE IT UP", width / 2, (height / 3 * 2) + 60);
push();
//creating the two yellow buttons on bottom of screen
fill(155, 115, 0);
strokeWeight(2);
stroke(255, 230, 57);
rect(150, 350, 125, 35, 4); //left button
rect(325, 350, 125, 35, 4); // right button
textSize(15);
//creating the text on top of buttons
textFont('Arial');
strokeWeight(1);
stroke(255, 203, 57);
fill(255, 203, 57);
text("START GAME", 213, 373);
text("INSTRUCTIONS", 388, 373);
pop();
}
pop();
//changes cursor to hand when hovering over start button and instructions button
if (mouseX > 150 & mouseX < 275 && mouseY < 385 && mouseY > 350) {
cursor(HAND);
if (mouseIsPressed) {
gameMode = 1;
};
} else if (mouseX > 325 & mouseX < 450 && mouseY > 350 && mouseY < 385) {
cursor(HAND);
if (mouseIsPressed) {
gameMode = 3;
};
} else {
cursor(ARROW);
}
}
function instructionsScreen() {
if (gameMode === 3) { //we only want the instructions screen to occur during instructions Screen time
push();
//creating an lowered opacity blanket of black across the title screen
fill(0, 0, 0, 200);
rect(0,0,600,400);
//title of the instructions screen: "Instructions"
textSize(30);
strokeWeight(1);
stroke(255, 188, 0);
fill(255, 188, 0);
textAlign(CENTER);
text("INSTRUCTIONS", width/2, 80);
//purpose of the game
fill(255);
strokeWeight(1);
stroke(255);
textSize(18);
text("Keep the Mushroom Kingdom safe!", width/2, 125);
//instructions of the game
textSize(15);
noStroke();
textAlign(LEFT);
text("There are 6 pipes leading into the kingdom, each one assigned to a button \n on your keyboard : S, D, F, J, K, L. \n \n It is your job as royal guard to delegate who enters and who does not. \n Unfortunately, some baddies will try to infiltrate the kingdom \n and make you lose your job. But luckily, with the tap of a button, \n you can immediately prevent them from entering. \n But be careful! Reject a civilian and you'll get a demerit. \n Three demerits is a disadulation.", 50, 160);
textAlign(CENTER);
strokeWeight(1);
stroke(255);
text("Press 'x' to return to Start page", width/2, 350);
pop();
}
}
function gameScreen() {
if (gameMode === 1) {
//----------------------------- get random character to pop up at different location -------
//places character down
image(characters[characterIndex], characterX, characterY);
//if character reaches peak, move in opposite direction
if (characterY < 100) {
characterSpeed = characterSpeed * -1
//if character reaches bottom of the pipe, changes character randomly and goes to new pipe
} else if (characterY > 200) {
characterSpeed = characterSpeed * -1
characterIndex = round(random(0, 5))
pipesOccupied = round(random(0, 5))
characterX = width / 7 * (pipesOccupied) + 60
};
characterY += characterSpeed;
//----------------------------- correct answer / wrong answer ------------------------------
//draws lives as mushrooms
for (var i = 0; i < lives; i++) {
image(mushroom, 60 + (40 * i), 20)
};
//once lives reaches 0, game ends
if (lives === 0) {
gameMode = 2
};
}
}
function displayButtons() {
//draws each of the buttons
var txt = ["S", "D", "F", "J", "K", "L"];
if (gameMode === 1) {
push();
stroke(137, 144, 200);
strokeWeight(5);
//changing color of button if respective key is pressed
//if 's' key is pressed
if (keyIsPressed) {
if (key === 's') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width/7), height - height/7, 40, 40);
// if 'd' key is pressed
if (keyIsPressed) {
if (key === 'd') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width / 7) * 2, height - (height / 7), 40, 40);
// if 'f' key is pressed
if (keyIsPressed) {
if (key === 'f') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width / 7) * 3, height - (height / 7), 40, 40);
// if 'j' key is pressed
if (keyIsPressed) {
if (key === 'j') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width / 7) * 4, height - (height / 7), 40, 40);
// if 'k' key is pressed
if (keyIsPressed) {
if (key === 'k') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width / 7) * 5, height - (height / 7), 40, 40);
// if 'l' key is pressed
if (keyIsPressed) {
if (key === 'l') {
fill(39, 49, 124);
} else {
fill(91, 100, 168);
}
} else {
fill(91, 100, 168);
}
ellipse((width / 7) * 6, height - (height / 7), 40, 40);
// adding the text on top of the button
pop();
for (var j = 1; j < 7; j++) {
push();
fill(200, 184, 220);
noStroke();
textAlign(CENTER);
textSize(19);
text(txt[j - 1], (width / 7) * j , height - (height / 7) + 5);
pop();
}
}
}
function gameOverScreen() {
//press 'r' to restart
if (gameMode === 2) {
//title of the gameOverScreen: "game over"
push();
fill(11, 16, 90, 200);
rect(0, 0, 600, 400);
textSize(50);
fill(239, 0, 42);
strokeWeight(5);
stroke(145, 0, 26);
textAlign(CENTER);
text("GAME OVER", width/2, height/2 - 20);
//displays your score
textSize(30);
strokeWeight(2);
text("Score:" + " " + score, width/2, height/2 + 20);
//tells you how you can play again and restart the game
textSize(20);
strokeWeight(1);
fill(239, 0, 42);
text("Press 'r' to restart game", width/2, height/2 + 70);
pop();
};
}
function keyPressed() {
//if game hasn't started yet, press S to start
//if game started, press X to go to home screen
//if game over, press r to restart
if (gameMode === 1) {
if (key === 'x' || key === 'X') {
gameMode = 0;
level = 1;
score = 0;
// if character is bad guy, add point for pressing; else subtract life
//if character is good guy, subtract life for pressing and add point for not pressing
} else {
for (var i = 0; i < characters.length; i++) {
var keys = ["s", "d", "f", "j", "k", "l"]
if (pipesOccupied === i) {
//if good guy,
if (characterIndex === 0 || characterIndex === 1 || characterIndex === 2) {
if (key === keys[i]) {
lives -= 1
}
} else if (characterIndex === 3 || characterIndex === 4 || characterIndex === 5 & key === keys[i]) {
score += 1
} else if (characterIndex === 3 || characterIndex === 4 || characterIndex === 5 && key != keys[i]) {
lives -= 1
}
};
};
}
//GAMEOVER - press R to restart the game
} else if (gameMode === 2) {
if (key === 'r' || key === 'R') {
gameMode = 0;
level = 1;
score = 0;
lives = 3;
};
//INSTRUCTIONS - press X to go to title screen
} else if (gameMode === 3) {
if (key === 'x' || key === 'X') {
gameMode = 0;
};
};
}
Instructions:
Keep the Mushroom Kingdom safe! There are 6 pipes leading into the Mushroom Kingdom and each one is assigned to a respective button on your keyboard : S, D, F, J, K, L. It is your job as a royal guard of the kingdom to delegate who is able to enter and who is not. Unfortunately, some villains will try to infiltrate the kingdom and make you lose your job. Luckily, with the tap of a button, you can immediately prevent them from entering. But be careful! Reject a civilian and you’ll lose a demerit (life). “Three demerits is a disadulation” – Jim Halpert from The Office. haha
Statements:
What we have produced for our final project is a completely different direction than what we had proposed to do in our Proposal. After lots of thought, we decided to change the topic of our final project because we believed this was something that could best reflect our creativity and have a more set goal (and also in celebration of Nintendo’s release of Super Smash Bros Ultimate today).
In regards to the distribution of work, Min and I worked in person together throughout the whole process. In the beginning, we would just sit next to each other, create a visual element, and then come together to merge whatever the two of us came up with. After the visual aspects were basically all done and we had to get to the interactive component of the game, that is when things started to get a little more difficult. We had to communicate a lot and constantly merge our codes to make sure that we are using the same variables, going towards the same direction, and following the same general train of thought. In the end, I focused more on the game design and structure while Min focused more on gameplay and functionality.
In the beginning, we had wanted characters to be coming out of all six chutes randomly, but at all times. But, we couldn’t figure out how to prevent characters from appearing in pipes that another character already occupies. So, we shifted our goals to stick to one pipe. We also could not figure out how to debug our code so that if no key is pressed to capture a “bad” character, a life is lost, or vice versa, if no key is pressed to let a “good character remain free, points are added to the score. However other than those two problems, the rest of the game came out quite successfully.
]]>/*
Jamie Dorst
jdorst@andrew.cmu.edu
Final Project
Section A
*/
// global variables
// weather
var weather;
var weatherUrl;
var temp;
var currentLocation;
var condition;
var city;
var rainConditions = ["Patchy light drizzle", "Light drizzle", "Freezing drizzle",
"Heavy freezing drizzle", "Patchy light rain", "Light rain",
"Moderate rain at times", "Moderate rain",
"Heavy rain at times", "Heavy rain", "Light freezing rain",
"Moderate or heavy freezing rain", "Light sleet",
"Moderate or heavy sleet", "Ice pellets", "Light rain shower",
"Torrential rain shower", "Light sleet showers",
"Moderate or heavy sleet showers", "Light showers of ice pellets",
"Moderate or heavy showers of ice pellets"];
var cloudyConditions = ["Cloudy", "Overcast", "Mist", "Patchy rain possible",
"Patchy snow possible", "Patchy sleet possible",
"Patchy freezing drizzle possible", "Thundery outbreaks possible",
"Fog", "Freezing fog"];
var snowyConditions = ["Blowing snow", "Blizzard", "Patchy light snow", "Light snow",
"Patchy moderate snow", "Moderate snow", "Patchy heavy snow", "Heavy snow"];
// custom variables
var button;
var cityInput;
var myFont;
// rain
var rainArray = [];
var rainAmount;
var rainSpeed;
var visibleR = false;
// snow
var snowflakeImg;
var snowArray = [];
var snowAmount;
var snowSpeed;
var visibleS = false;
// clouds
var cloudCover;
var cloudArray = [];
var cloudAmount;
var wind;
var rightWind = ["S", "SE", "E", "NE", "NNE", "ENE", "ESE", "SSE"];
var leftWind = ["N", "NW", "W", "SW", "SSW", "WSW", "WNW", "NNW"];
// preload weather API and snowflake image
function preload() {
weatherUrl = 'https://api.apixu.com/v1/current.json?key=8f4b2cd0980d46aba2e201006182511&q=Pittsburgh';
loadJSON(weatherUrl, getWeather);
snowflakeImg = loadImage('https://i.imgur.com/VADyEQ9.png');
}
function setup() {
createCanvas(480, 480);
// case insensitive
var lowCon = condition.toLowerCase();
// make rain/snow relative to how heavy it is
if (lowCon.indexOf('light') > -1) {
rainAmount = 10;
rainSpeed = 2;
snowAmount = 10;
snowSpeed = 1;
} else if (lowCon.indexOf('moderate') > -1) {
rainAmount = 15;
rainSpeed = 3;
snowAmount = 15;
snowSpeed = 2;
} else if (lowCon.indexOf('heavy') > -1) {
rainAmount = 20;
rainSpeed = 4;
snowAmount = 20;
snowSpeed = 3;
} else {
rainAmount = 30;
rainSpeed = 5;
snowAmount = 30;
snowSpeed = 4;
}
// make amount of clouds relative to cloud cover
cloudAmount = map(cloudCover, 0, 100, 0, 30);
// prepare for rain/snow/clouds by filling array
for (var i = 0; i < rainAmount; i++) {
rainArray[i] = makeRain(random(170, 313), random(0, 315));
}
for (var i = 0; i < snowAmount; i++) {
snowArray[i] = makeSnow(random(175, 305), random(0, 315));
}
for (var i = 0; i < cloudAmount; i++) {
cloudArray[i] = makeCloud(random(-75, width + 75), random(320, height),
random(100, 170), 175);
}
// let user name a city with input and button
cityInput = createInput();
cityInput.position(width - cityInput.width - 40, 20);
button = createButton('GO');
button.position(cityInput.x + cityInput.width + 5, 20);
button.mouseClicked(changeCity);
}
// function to allow enter key to also submit input
async function keyPressed() {
if (keyCode === ENTER) {
changeCity();
}
}
// function to change the weather to the user-inputted city
function changeCity() {
// give variable a default
city = 'Pittsburgh'
// change city to inputted city
city = cityInput.value();
cityInput.value('');
// reload weather data
weatherUrl = 'https://api.apixu.com/v1/current.json?key=8f4b2cd0980d46aba2e201006182511&q=' + city;
loadJSON(weatherUrl, getWeather);
}
async function cloudUpdate() {
// make amount of clouds relative to cloud cover
cloudAmount = map(cloudCover, 0, 100, 0, 30);
// refill arrays so animations change
for (var i = 0; i < rainAmount; i++) {
rainArray[i] = makeRain(random(170, 313), random(0, 315));
}
for (var i = 0; i < snowAmount; i++) {
snowArray[i] = makeSnow(random(175, 305), random(0, 315));
}
for (var i = 0; i < cloudAmount; i++) {
cloudArray[i] = makeCloud(random(-75, width + 75), random(320, height),
random(100, 170), 175);
}
}
// get weather data
function getWeather(weather) {
temp = Number(weather.current.temp_f);
condition = weather.current.condition.text;
currentLocation = weather.location.name;
cloudCover = weather.current.cloud;
wind = weather.current.wind_mph;
windDir = weather.current.wind_dir;
cloudUpdate();
}
async function draw() {
// background is light during day, dark during night
if (hour() > 8 & hour() < 18) {
background("#0077CC");
} else {
background("#00487C");
}
// font and size
noStroke();
textFont("Sans-serif");
textAlign(CENTER);
fill("EBF2FA");
textSize(30);
text(currentLocation, width / 2, 88);
textSize(100);
text(temp + "°", width / 2, 220);
textSize(18);
text(condition, width / 2, 120);
textSize(12);
text("Enter a city name or zip code to change location", 145, 28);
// draw based on weather conditions
if (condition === "Sunny") {
sunny();
} else if (condition === "Clear") {
clearSky();
} else if (condition === "Partly cloudy") {
sunny();
cloudy();
} else if (rainConditions.some(weatherTest) == true) {
rainy();
} else if (cloudyConditions.some(weatherTest) == true) {
cloudy();
} else if (snowyConditions.some(weatherTest) == true) {
snowy();
} else if (condition === ("Patchy light rain with thunder") ||
("Moderate or heavy rain with thunder")) {
rainy();
thunder();
} else if (condition === ("Patchy light snow with thunder") ||
("Moderate or heavy snow with thunder")) {
snowy();
thunder();
}
}
// test weather conditions
function weatherTest(value) {
return value == condition;
}
function directionTest(value) {
return value == windDir;
}
//======================SUNNY=========================
function sunny() {
// color of sun mapped to how hot it is
// redder when hotter, yellower when cooler
var sunColorG = map(temp, 0, 110, 230, 155);
noStroke();
fill(255, sunColorG, 0);
// draw sun
ellipse(width / 2, 350, 100, 100);
// draw sun rays
push();
angleMode(DEGREES);
translate(width / 2, 350);
for (var i = 0; i < 10; i++) {
fill ("orange");
triangle(0, -80, -10, -60, 10, -60);
rotate(36);
}
pop();
}
//======================CLEAR=========================
// function to draw moon
function clearSky() {
noStroke();
fill("#EBF2FA");
ellipse(width / 2, 350, 150, 150);
fill("#E3E9F2");
ellipse(270, 330, 20, 20);
ellipse(220, 360, 60, 60);
ellipse(200, 300, 10, 10);
ellipse(277, 400, 25, 25);
ellipse(250, 291, 30, 30);
}
//=====================CLOUDY=========================
// function to make rain drop objects
function makeCloud(x, y, cloudColor) {
var cloudObj = {
x: x,
y: y,
cc: cloudColor,
move: cloudMove,
render: renderCloud
};
return cloudObj;
}
// function to draw clouds
function renderCloud() {
noStroke();
fill(this.cc);
ellipse(this.x, this.y, 75, 75);
ellipse(this.x + 60, this.y - 17, 100, 100);
ellipse(this.x + 110, this.y + 5, 50, 50);
}
// function to make clouds move
// based on wind speed and direction
function cloudMove() {
if (leftWind.some(directionTest) == true) {
if (this.x > -160) {
this.x -= map(wind, 0, 50, 0, 10);
} else if (this.x <= -37.5) {
this.x = width + 160;
}
} if (rightWind.some(directionTest) == true) {
if (this.x < width + 37.5) {
this.x += map(wind, 0, 50, 0, 10);
} else if (this.x >= width + 37.5) {
this.x = -160;
}
}
}
// weather condition function
function cloudy() {
for (var i = 0; i < cloudAmount; i++) {
cloudArray[i].render();
cloudArray[i].move();
}
}
//======================THUNDER=======================
// function to draw thunder
function thunder() {
stroke("yellow");
noFill();
angleMode(DEGREES);
arc(300, 320, 60, 60, 280, 0);
arc(300, 320, 70, 70, 280, 0);
arc(190, 315, 85, 85, 180, 285);
arc(190, 315, 95, 95, 180, 285);
}
//======================RAIN==========================
// function to make rain drop objects
function makeRain(x, y) {
var raindrop = {
x: x,
y: y,
fall: rainFall,
render: renderRain,
visibleR: visibleR
};
return raindrop;
}
// function to draw rain
function renderRain() {
noStroke();
// only display raindrops when they are below the cloud
if (this.visibleR == false) {
ellipse(this.x, this.y, 0, 0);
} else {
ellipse(this.x, this.y, 7, 13);
}
}
// function to make rain fall
function rainFall() {
if (this.y < height) {
this.y += rainSpeed
} else if (this.y >= height) {
this.y = random(300, 315);
}
if (this.y < 315) {
this.visibleR = false;
} else {
this.visibleR = true;
}
}
// weather condition function
function rainy() {
// case insensitive
var lowCon = condition.toLowerCase();
// make rain relative to how heavy it is
if (lowCon.indexOf('light') > -1) {
rainAmount = 10;
rainSpeed = 2;
} else if (lowCon.indexOf('moderate') > -1) {
rainAmount = 15;
rainSpeed = 3;
} else if (lowCon.indexOf('heavy') > -1) {
rainAmount = 20;
rainSpeed = 4;
} else {
rainAmount = 30;
rainSpeed = 5;
}
// color of rain dependent upon temperature
fill(0, map(temp, 32, 100, 255, 0), 255);
for (var i = 0; i < rainAmount; i++) {
rainArray[i].render();
rainArray[i].fall();
}
var rainCloud = makeCloud(190, 315, 100);
rainCloud.render();
}
//=======================SNOW=========================
// function to make snowflake objects
function makeSnow(x, y) {
var snowflake = {
x: x,
y: y,
fall: snowFall,
render: renderSnow,
visibleS: visibleS
};
return snowflake;
}
// function to draw snow
function renderSnow() {
if (this.visibleS == false) {
image(snowflakeImg, -5, -5, 1, 1);
} else {
image(snowflakeImg, this.x, this.y, 15, 15);
}
}
// function to make snow fall
function snowFall() {
if (this.y < height) {
this.y += snowSpeed;
} else if (this.y >= height) {
this.y = 315;
}
if (this.y < 315) {
this.visibleS = false;
} else {
this.visibleS = true;
}
}
// weather condition function
function snowy() {
// case insensitive
var lowCon = condition.toLowerCase();
// make snow relative to how heavy it is
if (lowCon.indexOf('light') > -1) {
snowAmount = 10;
snowSpeed = 1;
} else if (lowCon.indexOf('moderate') > -1) {
snowAmount = 15;
snowSpeed = 2;
} else if (lowCon.indexOf('heavy') > -1) {
snowAmount = 20;
snowSpeed = 3;
} else {
snowAmount = 30;
snowSpeed = 4;
}
fill(255);
for (var i = 0; i < snowAmount; i++) {
snowArray[i].render();
snowArray[i].fall();
}
var snowCloud = makeCloud(190, 315, 100);
snowCloud.render();
}
For my final project, I created a weather app. It defaults to Pittsburgh, but you can enter in any city or zip code you like and get the weather there. All of the animations are relative to some function of the weather such as the amount of rain, percent of cloud coverage, wind direction, and/or temperature. I learned a lot through making this project, from coming up with a plausible idea to figuring out how to get it to upload, and I’m happy with what I was able to produce.
]]>