Yiran Xuan – Final Project – Dueling Dragons

sketch

/*
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!

Hannah Cai—Final Project

(The audio seems to only work in wordpress on Chrome).

instructions:
hover over points to hear their pitches.
click points to activate them.
click points again to deactivate them.
clicked points that are close enough to each other will link to each other. (try not to link too many or the program will lag lol)
explore and enjoy the soundscape!

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Final Project
*/

//particle position arrays
var particleNumber = 200; //number of particles
var psize = 1.5; //particle size
var px = []; //particle x position
var py = []; //particle y position
var pz = []; //particle z position
var distanceToPoint; //dist from (mouseX, mousY) to (px, py)
var amplitude = 3.14 * 3; //amplitude of bobbing animation
var waveSpeed; //speed of bobbing animation
var theta = 0; //plugin for sin()


//particle sound arrays
var threshold = 100; //minimum distance between mouse and particle to trigger glow/sound
var notes = [130.81, 146.83, 164,81, 174.61, 196, 220, 246.94, //pitches of whole notes from C3
            261.63, 293.66, 329.63, 349.23, 392.00, 440, 493.88, 
            523.25, 587.33, 659.25, 698.46, 783.99, 880, 987.77, 
            1046.5, 1174.66, 1318.51, 1396.91, 1567.98, 1760, 2093]; //to C7
var ppitch = []; //pitch values for each particle
var pOsc = []; //oscillator for each particle
var pvolume = 0; //volume of each particle
var pOscOn = []; //array of booleans for if the oscillators are on

//misc other particle arrays
var pClicked = []; //array of booleans for if the particle was clicked
var glowSize; //size of particle glow

//arrays for cursor
var xarray = [0, 10, 20, 30, 40, 50];
var yarray = [0, 10, 20, 30, 40, 50];
var s;

//arrays for camera and perspective
var camX;
var camY;
var camZ;
var rotateX;
var rotateY;

//arrays for lines between particles
var connect = [];
var connectionThreshold = 500;

function setup() {
    createCanvas(windowWidth, windowHeight, WEBGL); //fit canvas to window size

    //set up variables; store in arrays
    for (i = 0; i < particleNumber; i++) {
        px.push(random(-width * 0.8, width * 0.8));
        py.push(random(-height, height));
        pz.push(random(-width, height / 2));
        ppitch.push(notes[floor(random(0, notes.length))]);
        pOscOn.push(false);
        pClicked.push(false);
        makeOsc(i);
    }
}

function makeOsc(index) {
    myOsc = new p5.SinOsc();
    myOsc.freq(ppitch[index]);
    pOsc.push(myOsc); //store oscillators in pOsc array
}

function playOsc(index) {
    var maxVolume = 0.01;
    pvolume = constrain(pvolume, 0, maxVolume);
    //turn clicked particles permanently on
    if (pClicked[index] === true) { 
        pvolume = maxVolume;
    } else { 
    //unclicked particles get louder as the mouse gets closer
        pvolume = map(distanceToPoint, threshold, 0, 0, maxVolume);
    }
    //make particles with lower pitches louder, so all ranges are heard clearly
    var factor =  map(ppitch[index], ppitch[0], ppitch[ppitch.length - 1], 5, 1);
    pvolume *= factor;
    pOsc[index].amp(pvolume);
}

function stopOsc(index) {
    pOsc[index].stop();
}

function draw() {
    background(0);
    noStroke(); //get rid of default black stroke

    //map camera position to mouse position to simulate orbit control
    camX = map(mouseX, 0, width, -width / 2, width / 2);
    camY = map(mouseY, 0, height, -height / 2, height / 2);
    camZ = (height/2.0) / tan(PI*30.0 / 180.0);
    camera(camX, camY, camZ, 0, 0, 0, 0, 1, 0);

    //set up particles
    for (i = 0; i < particleNumber; i++) {
        drawLines(i); //draw lines between clicked particles
        //create bobbing movement

        waveSpeed = map(pz[i], -width, height, 20000, 70000); //create parallax effect
        theta += (TWO_PI / waveSpeed);
        if (theta > amplitude) {
            theta = -theta;
        }
        py[i] += sin(theta);

        push();
        translate(px[i], py[i], pz[i]);
        drawGlow(i); //draw glow of each particle
        //draw each particle
        fill(255); 
        smooth();
        sphere(psize);
        pop();

        //play a particle's oscillator if the mouse's 
        //distance is less than the threshold
        if (distanceToPoint <= threshold) {
            if (pOscOn[i] == false) {
                pOsc[i].start();
                pOscOn[i] = true;
            }
            playOsc(i);
        }

        //stop a particle's oscillator if the mouse's 
        //distance is greater than the threshold
        if (distanceToPoint > threshold & pClicked[i] == false) {
            stopOsc(i);
            pOscOn[i] = false;
        }
    }

    //cursor
    noCursor(); //turn off the cursor icon, display below instead
    //this is basically the code from the snake lab we did
    for (var i = 0; i < xarray.length; i++) {
        fill(255, 255, 200);
        s = 8 - (xarray.length - i);
        ellipse(xarray[i], yarray[i], s, s);
    }
    xarray.push(mouseX - width / 2);
    yarray.push(mouseY - height / 2);
    if (xarray.length > 8) {
        xarray.shift();
        yarray.shift();
    }
}

function drawGlow(index) {
    push();
    noStroke();
    //rotate the (flat) ellipses to face the cameras to simulate 3d glow
    rotateX(radians(map(camY, -height / 2, height / 2, 40, -40)));
    rotateY(radians(map(camX, -width / 2, width / 2, -45, 45)));

    //calculate distance from mouse to each point
    distanceToPoint = dist(mouseX - width / 2, mouseY - height / 2, px[index], py[index]);
    
    //clicked particles have a pulsing glow;
    //unclicked particles glow when the mouse hovers close to them
    if (pClicked[index] === true) {
        glowSize = map(sin(theta), TWO_PI, 0, psize, 100);
    } else {
        glowSize = map(distanceToPoint, 100, psize, psize, 100);
    }
    //draw the actual glow (a radial alpha gradient)
    for (r = psize; r < glowSize; r += 1.5) {
        fill(255, 255, 200, map(r, psize, glowSize, 2, 0));
        ellipse(0, 0, r);
    }
    pop();
}

function drawLines(index) {
    push();
    //push the indices of clicked particles in the "connect" array;
    //turn off/remove particles from the array if clicked again
    if (pClicked[index] == true & ! connect.includes(index)) {
        connect.push(index);
    } else if (pClicked[index] == false) {
        connect.splice(index, 1);
    }

    //connect groups of particles that are clicked if the distance between is less than the threshold
    stroke(255);
    strokeWeight(1);
    noFill();
    for (i = 0; i < connect.length; i++) {
        for (j = i + 1; j < connect.length; j++) {
            if (dist(px[connect[i]], py[connect[i]], pz[connect[i]], 
                px[connect[j]], py[connect[j]], pz[connect[j]]) < connectionThreshold) {
                beginShape(LINES);
                vertex(px[connect[i]], py[connect[i]], pz[connect[i]]);
                vertex(px[connect[j]], py[connect[j]], pz[connect[j]]);
                endShape();
            }
        }
    }
    noStroke();
    pop();
}

//if window is resized, refit the canvas to the window
function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function mouseClicked() {
    for (i = 0; i < particleNumber; i++) {
        distanceToPoint = dist(mouseX - width / 2, mouseY - height / 2, px[i], py[i]);
        //toggle pClicked on and off if mouse clicks within 10 pixels of a particle
        if (distanceToPoint < 10 & pClicked[i] == false) {
            pClicked[i] = true;
        } else if (distanceToPoint < 10 & pClicked[i] == true) {
            pClicked[i] = false;
        }
    }
}

Here’s a zip file for the fullscreen version.
final project fin

There are still a few bugs I’m aware of that I don’t know how to fix:
1. sometimes the links will flicker, adding another grouped point sometimes fixes it
2. sometimes the volume is louder than it should be upon refreshing/starting the program. I constrained the volume to try and avoid this but it didn’t seem to help
3. sometimes all the oscillators start off turned on upon refreshing/starting the program (if you move your mouse close to a point, the sine wave will start and stop, instead of fading in and out).

Generally, refreshing the page fixes all of these bugs, so please refresh the page if you notice any of the above!

I enjoyed this project a lot. Even though I spent a lot of time struggling and debugging, I feel like I learned a lot about both WEBGL and using sound/oscillators. I’m pretty satisfied in the final visual effects as well, although unfortunately, the program will start to lag if too many linked points are formed. Also unfortunately, my aim with this project was to familiarize myself more with objects, but I was completely stuck trying to format things in objects so I made everything with a ton of arrays instead. I definitely want to revisit this project in the future and format it properly with objects. In general, I definitely want to keep adding to this project because it’s still pretty clunky and buggy right now. I was planning to add a start screen, instructions, the ability to record audio, and different modes (eg a “wander” mode where the cursor moves around on its own), but I didn’t have time to even try implementing most of those before the deadline. In the future, though, I definitely want to try and make this something that could be a standalone interactive website (and add it to my portfolio, lol).

In general, I loved this class and I learned a lot! Thank you to Dannenberg and all the TAs!

Yingyang Zhou-Final Project

Instruction:
-press blank space for next line
-press “a” when you see the line you like
-press “g” for generating your poem
(your poem will be on top but you can press blank space to keep skimming the rest of the poem)
//running this on website, you probably need to click the canvas first because the blank space key is conflict with the scrolling down on web page.

sketch

//Yingyang Zhou
//yingyanz@andrew.cmu.edu
//Final Project
//section A


var poemRilke = "After_the summer's_yield_Lord_it is_time_to let_your shadow_lengthen_on the sundials_and in the pastures_let_the rough winds_fly_As for_the final fruits_coax them_to roundness_Direct_on them_two days of warmer light_to hale them golden_toward their term_and harry_the last few drops_of sweetness_through the wine.";
var words = poemRilke.split("_");
var num = 0;
var numMy = 0;
var l = 0;
var speed = 1;
var myPoem = [];

var inc = 0.1;
var scl = 10;
var cols, rows;
var zoff = 0;
var particles = [];
var flowfield;


// function preload(){
//      whiteNoise = loadSound("forestsurroundings.wav"); 
// }



function setup() {
    createCanvas(400, 400);
    colorMode(RGB, 255);
    cols = floor(width / scl);
    rows = floor(height / scl);


    flowfield = new Array(cols * rows);

    for (var i = 0; i < 300; i++) {
        particles[i] = new Particle();
  } 
    background(255);

    // var button = createButton("generate my poem");
    // button.mousePressed(generatePoem);
}


function draw() {

  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);
    }
    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();
  }
    for(var i = 0; i < words.length; i++){
        textAlign(CENTER, CENTER); 
        fill(50, 50, 50, random(10));
        textFont("Segoe Script");  
        // stroke(50, 50, 50, random(10));
        strokeWeight(0.5);
        text(words[l-1], width/2, 20*(num+1) - speed);
    }

    if(num > 18){
      num = 0;
      reset();
    }
    if(l > words.length){
      l = 0;
    }

    // whiteNoise.play();
}
function reset(){
  
  flowfield = new Array(cols * rows);

  for (var i = 0; i < 300; i++) {
        particles[i] = new Particle();
  } 
  background(255);
}

function generatePoem(){
  background(220);
  // var randomLine;
  for(var i = 0; i < myPoem.length; i++){
    stroke(0);
    text(myPoem[i], width/2, 20*(i+1));
  }

}


function Particle() {
  this.pos = createVector(random(width), random(height));
  this.vel = createVector(0, 0);
  this.acc = createVector(0, 0);
  this.maxspeed = 4;
  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(this.h, 5);
    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();
    }

  }

}

function keyTyped(){ 
  if(key === ' '){
    num ++;
    numMy ++;
    l ++;
}
  if(key === 'a'){
    myPoem.push(words[l-1]);
    for(var i = 0; i < 5; i++){
        print(myPoem[i]);
    }

  }
  if(key ==='g'){
    generatePoem();
  }


}

For the final, I was initially had idea doing something more related to sound but realized that would be hard on WordPress website, so I change the idea a little bit.

I was always interested the what random can do for programming, it always turn out surprising. I had idea of gerating a poem of my own, from the pecies of poem/sentence/paragraph, poem is sometime a collection of different fragaments.

This program shows here as from an example, it is a poem I like very much from Rilke, a germany poet.

I use perlin noise keep running as a dynamic background, which I am very pleased I had it working.

Xindi Lyu_Final Project

sketch

var puzzle1A = [
  { x:40, y:40,active: false,color:138 },
  
]
var puzzle1B = [
  { x:40, y:120,active: false,color:138 },
  
]
var puzzle1C = [
  { x:40, y:210,active: false,color:138 },
  
]
var puzzle1D = [
  { x:40, y:300,active: false,color:138 },
  
]
var puzzle1E = [
  { x:40, y:380,active: false,color:138 },
  
]
var puzzle1F = [
  { x:40, y:460,active: false,color:138 },
  
]
var puzzle1G = [
  { x:40, y:540,active: false,color:138 },
  
]
var puzzle2A = [
  { x:40, y:40,active: false,color:31},
  
]
var puzzle2B = [
  { x:40, y:120,active: false,color:31 },
  
]
var puzzle2C = [
  { x:40, y:200,active: false,color:31 },
  
]
var puzzle2D = [
  { x:60, y:280,active: false,color:31 },
  
]
var puzzle2E = [
  { x:40, y:350,active: false,color:31 },
  
]
var puzzle2F = [
  { x:40, y:430,active: false,color:31 },
  
]
var puzzle2G = [
  { x:40, y:510,active: false,color:31},
  
]
var countB1=1;
var countB2=1;
var countB3=1;
var countB4=1;
var countB5=1;
var countB6=1;
var countB7=1;

var countA1=1;
var countA2=1;
var countA3=1;
var countA4=1;
var countA5=1;
var countA6=1;
var countA7=1;
var button;

var a=28;
// Set up canvas
function setup() {
  frameRate(16);
  // Create canvas using width/height of window.
  createCanvas(500, 600);  
  rectMode(CENTER);
  a=a+1;
}

// Draw on the canvas.
function draw() {
  background(100,48,40);
  stroke(50,48,40)
  strokeWeight(1.3);
  line(0,400,600,400);
  noStroke();
  fill(49,48,46);
  rect(380,360,60+random(0,5),80+random(0,3));
    rect(120,360,60+random(0,5),80+random(0,3));
  textSize(15);
  fill(random(100,105));
  
text("1800",360,360);
text("1662",100,360);
textStyle(BOLD);
textSize(15);

fill(100);
text("CLICK TO ENTER",50,500);
text("CLICK TO ENTER",350,500);


  if(a==20){
    puzzle2();
  }else if(a==10){
    puzzle1();
  }

}
function mouseClicked(){
  if(350<mouseX){
  a=20;
}else if(mouseX<150){
  a=10;
}
}
function puzzle1() {
background(67,99,138);
stroke(67,99,138);
var countA=countA1+countA2+countA3+countA4+countA5+countA6+countA7;

//triangle(288,160,358,160,323,195);
if (puzzle1A.length > 0) {
    for (var i = 0; i < puzzle1A.length; i++) {
     
      var ta=puzzle1A[i];
       var dist1A=dist(ta.x,ta.y,323,171.67)
 

        if(dist1A<10&mouseIsPressed){
        ta.x=323;
        ta.y=171.67
        countA1=0
      }
      noFill();
      stroke(ta.color-71,ta.color-39,ta.color);
      triangle(288,160,358,160,323,195);
      stroke(67,99,138);
      fill(28,41,81);
      triangle(ta.x-35,ta.y-11.67,ta.x,ta.y+23.33,ta.x+35,ta.y-11.67);
      }
    }
    

    if (puzzle1B.length > 0) {
    for (var i = 0; i < puzzle1B.length; i++) {
     
      var tb=puzzle1B[i];
       var dist1B=dist(tb.x,tb.y,305.5,211)
 

        if(dist1B<10&mouseIsPressed){
        tb.x=305.5;
        tb.y=211
        countA2=0
      }
       noFill();
      stroke(tb.color-71,tb.color-39,tb.color);
      beginShape();
      vertex(288,228);
      vertex(323,261);
      vertex(323,195);
      vertex(288,160);
      endShape(CLOSE)
      stroke(67,99,138);
      fill(28,41,81);
      beginShape();
      vertex(tb.x-17.5,tb.y+17);
      vertex(tb.x+17.5,tb.y+50);
      vertex(tb.x+17.5,tb.y-16);
      vertex(tb.x-17.5,tb.y-51);
      endShape(CLOSE);
      }
    }
       if (puzzle1C.length > 0) {
    for (var i = 0; i < puzzle1C.length; i++) {
     
      var tc=puzzle1C[i];
       var dist1C=dist(tc.x,tc.y,288,262)
 

        if(dist1C<10&mouseIsPressed){
        tc.x=288;
        tc.y=262;
        countA3=0
      }
       noFill();
      stroke(tc.color-71,tc.color-39,tc.color);
      beginShape();
      vertex(288,228);
      vertex(323,261);
      vertex(288,298);
      vertex(253,261);
      endShape(CLOSE)
      stroke(67,99,138);
      fill(28,41,81);
      beginShape();
      vertex(tc.x,tc.y-34);
      vertex(tc.x+35,tc.y-1);
      vertex(tc.x,tc.y+36);
      vertex(tc.x-35,tc.y-1);
      endShape(CLOSE);
      }
    }
    fill(28,41,81);

if (puzzle1D.length > 0) {
    for (var i = 0; i < puzzle1D.length; i++) {
     
      var td=puzzle1D[i];
       var dist1D=dist(td.x,td.y,253,285.67)
 

        if(dist1D<10&mouseIsPressed){
        td.x=253;
        td.y=285.67;
        countA4=0
      }
       noFill();
      stroke(td.color-71,td.color-39,td.color);
      triangle(253,261,288,298,218,298);
      stroke(67,99,138);
      fill(28,41,81);
      triangle(td.x,td.y-24.67,td.x+35,td.y+12.33,td.x-35,td.y+12.33);
      }
    }
    fill(28,41,81);
if (puzzle1E.length > 0) {
    for (var i = 0; i < puzzle1E.length; i++) {
     
      var te=puzzle1E[i];
       var dist1E=dist(te.x,te.y,234.75,253.75)
 

        if(dist1E<10&mouseIsPressed){
        te.x=234.75;
        te.y=253.75;
        countA5=0
      }
       noFill();
      stroke(te.color-71,te.color-39,te.color);
      beginShape();
      vertex(209,253.75);
      vertex(234.75,228);
      vertex(260.5,253.75);
      vertex(234.75,279.5);
      endShape(CLOSE)
      stroke(67,99,138);
      fill(28,41,81);
      beginShape();
      vertex(te.x-25.75,te.y);
      vertex(te.x,te.y-25.75);
      vertex(te.x+25.75,te.y);
      vertex(te.x,te.y+25.75);
      endShape(CLOSE);
      }
    }
if (puzzle1F.length > 0) {
    for (var i = 0; i < puzzle1F.length; i++) {
     
      var tf=puzzle1F[i];
       var dist1F=dist(tf.x,tf.y,288,315.17)
 

        if(dist1F<10&mouseIsPressed){
        tf.x=288;
        tf.y=315.17;
        countA6=0
      }
       noFill();
      stroke(tf.color-71,tf.color-39,tf.color);
      triangle(288,298,313.75,323.75,262.25,323.75);
      stroke(67,99,138);
      fill(28,41,81);
      triangle(tf.x,tf.y-17.17,tf.x+25.75,tf.y+8.58,tf.x-25.75,tf.y+8.58);
      }
    }
    if (puzzle1G.length > 0) {
    for (var i = 0; i < puzzle1G.length; i++) {
     
      var tg=puzzle1G[i];
       var dist1G=dist(tg.x,tg.y,236.5,315.17)
 

        if(dist1G<10&mouseIsPressed){
        tg.x=236.5;
        tg.y=315.17;
        countA7=0
      }
       noFill();
      stroke(tg.color-71,tg.color-39,tg.color);
      triangle(236.5,298,262.25,323.75,210.75,323.75);
      stroke(67,99,138);
      fill(28,41,81);
      triangle(tg.x,tg.y-17.17,tg.x+25.75,tg.y+8.58,tg.x-25.75,tg.y+8.58);
      }
    }
     fill(28,41,81);

if (countA<1){
hint1();
}
textSize(40);
textStyle(BOLD);
fill(255);
text(countA,400,50);
}

function puzzle2() {
  background(69,93,31);
  stroke(69,93,31);
  fill(33,64,22);
  var countB=countB1+countB2+countB3+countB4+countB5+countB6+countB7;
  
  if (puzzle2A.length > 0) {
    for (var i = 0; i < puzzle2A.length; i++) {
     
      var ka=puzzle2A[i];
       var dist2A=dist(ka.x,ka.y,336.67,176.67)
 

        if(dist2A<10&mouseIsPressed){
        ka.x=336.67;
        ka.y=176.67
        countB1=0
      }
      noFill();
      stroke(ka.color+38,ka.color+62,ka.color);
      triangle(320,160,370,160,320,210);
      stroke(69,93,31);
      fill(33,64,22);
      triangle(ka.x-16.67,ka.y-16.67,ka.x+33.33,ka.y-16.67,ka.x-16.67,ka.y+33.33);
      }
    }
  
  if (puzzle2B.length > 0) {
    for (var i = 0; i < puzzle2B.length; i++) {
     
      var kb=puzzle2B[i];
       var dist2B=dist(kb.x,kb.y,295,210)
 

        if(dist2B<10&mouseIsPressed){
        kb.x=295;
        kb.y=210;
        countB2=0
      }
      noFill();
      stroke(kb.color+38,kb.color+62,kb.color);
      rect(295,210,50,50);
      stroke(69,93,31);
      fill(33,64,22);
      rect(kb.x,kb.y,50,50);
      }
    }
 
  if (puzzle2C.length > 0) {
    for (var i = 0; i < puzzle2C.length; i++) {
     
      var kc=puzzle2C[i];
       var dist2C=dist(kc.x,kc.y,253.33,176.67)
 

        if(dist2C<10&mouseIsPressed){
        kc.x=253.33;
        kc.y=176.67
        countB3=0
      }
      noFill();
      stroke(kc.color+38,kc.color+62,kc.color);
      triangle(270,210,270,160,220,160);
      stroke(69,93,31);
      fill(33,64,22);
      triangle(kc.x+16.67,kc.y-16.67,kc.x-33.33,kc.y-16.67,kc.x+16.67,kc.y+33.33);
      }
    }
  
        if (puzzle2D.length > 0) {
    for (var i = 0; i < puzzle2D.length; i++) {
     
      var kd=puzzle2D[i];
       var dist2D=dist(kd.x,kd.y,325,252.5)
 

        if(dist2D<10&mouseIsPressed){
        kd.x=325;
        kd.y=252.5
        countB4=0
      }
      noFill();
      stroke(kd.color+38,kd.color+62,kd.color);
      beginShape();
      vertex(270,235);
      vertex(345,235);
      vertex(380,270);
      vertex(305,270);
      endShape(CLOSE)
      stroke(69,93,31);
      fill(33,64,22);
      beginShape();
      vertex(kd.x-55,kd.y-17.5);
      vertex(kd.x+20,kd.y-17.5);
      vertex(kd.x+55,kd.y+17.5);
      vertex(kd.x-20,kd.y+17.5);
      endShape(CLOSE)
      }
    }

       
      if (puzzle2E.length > 0) {
    for (var i = 0; i < puzzle2E.length; i++) {
     
      var ke=puzzle2E[i];
       var dist2E=dist(ke.x,ke.y,370,235)
 

        if(dist2E<10&mouseIsPressed){
        ke.x=370;
        ke.y=235
        countB5=0
      }
      noFill();
      stroke(ke.color+38,ke.color+62,ke.color);
     beginShape();
      vertex(345,235);
      vertex(370,210);
      vertex(395,235);
      vertex(370,260);
      endShape(CLOSE)
      stroke(69,93,31);
      fill(33,64,22);
      beginShape();
      vertex(ke.x-25,ke.y);
      vertex(ke.x,ke.y-25);
      vertex(ke.x+25,ke.y);
      vertex(ke.x,ke.y+25);
      endShape(CLOSE)
      }
    }

      //triangle(305,270,280,295,330,295) 305 286.67;
       if (puzzle2F.length > 0) {
    for (var i = 0; i < puzzle2F.length; i++) {
     
      var kf=puzzle2F[i];
       var dist2F=dist(kf.x,kf.y,305,286.67)
 

        if(dist2F<10&mouseIsPressed){
        kf.x=305;
        kf.y=286.67
        countB6=0
      }
      noFill();
      stroke(kf.color+38,kf.color+62,kf.color);
      triangle(305,270,280,295,330,295);
      stroke(69,93,31);
      fill(33,64,22);
      triangle(kf.x,kf.y-16.67,kf.x-25,kf.y+8.33,kf.x+25,kf.y+8.33);
      }
    }
      //triangle(380,270,355,295,405,295);
 if (puzzle2G.length > 0) {
    for (var i = 0; i < puzzle2G.length; i++) {
     
      var kg=puzzle2G[i];
       var dist2G=dist(kg.x,kg.y,380,286.67)
 

        if(dist2G<10&mouseIsPressed){
        kg.x=380;
        kg.y=286.67
        countB7=0
      }
      noFill();
      stroke(kg.color+38,kg.color+62,kg.color);
      triangle(380,270,355,295,405,295);
      stroke(69,93,31);
      fill(33,64,22);
      triangle(kg.x,kg.y-16.67,kg.x-25,kg.y+8.33,kg.x+25,kg.y+8.33);
      }
    }
    if (countB<1){
hint2();
}
textSize(40);
textStyle(BOLD);
fill(255);
text(countB,400,50);
}

function mousePressed() {
  if (puzzle1A.length > 0) {
    for (var i = 0; i < puzzle1A.length; i++) {
     
      var ta = puzzle1A[i];
      var radius1A=dist(ta.x,ta.y,ta.x-25,ta.y-1.67);
          distance1A = dist(mouseX, mouseY,ta.x,ta.y);
      if (distance1A < radius1A) {
        ta.active = true;
      } else {
       ta.active = false;
      }
    }
  }
   if (puzzle1B.length > 0) {
    for (var i = 0; i < puzzle1B.length; i++) {
     
      var tb = puzzle1B[i];
      var radius1B=dist(tb.x,tb.y,tb.x-10.5,tb.y+10);
          distance1B = dist(mouseX, mouseY,tb.x,tb.y);
      if (distance1B < radius1B) {
        tb.active = true;
      } else {
       tb.active = false;
      }
    }
  }
     if (puzzle1C.length > 0) {
    for (var i = 0; i < puzzle1C.length; i++) {
     
      var tc = puzzle1C[i];
      var radius1C=dist(tc.x,tc.y,tc.x,tc.y+36);
          distance1C = dist(mouseX, mouseY,tc.x,tc.y);
      if (distance1C < radius1C) {
        tc.active = true;
      } else {
       tc.active = false;
      }
    }
  }
if (puzzle1D.length > 0) {
    for (var i = 0; i < puzzle1D.length; i++) {
     
      var td = puzzle1D[i];
      var radius1D=dist(td.x,td.y,td.x,td.y-24.67);
          distance1D = dist(mouseX, mouseY,td.x,td.y);
      if (distance1D < radius1D) {
        td.active = true;
      } else {
       td.active = false;
      }
    }
  }
  if (puzzle1E.length > 0) {
    for (var i = 0; i < puzzle1E.length; i++) {
     
      var te = puzzle1E[i];
      var radius1E=dist(te.x,te.y,te.x-25.75,te.y);
          distance1E = dist(mouseX, mouseY,te.x,te.y);
      if (distance1E < radius1E) {
        te.active = true;
      } else {
       te.active = false;
      }
    }
  }
    if (puzzle1F.length > 0) {
    for (var i = 0; i < puzzle1F.length; i++) {
     
      var tf = puzzle1F[i];
      var radius1F=dist(tf.x,tf.y,tf.x,tf.y-17.17);
          distance1F = dist(mouseX, mouseY,tf.x,tf.y);
      if (distance1F < radius1F) {
        tf.active = true;
      } else {
       tf.active = false;
      }
    }
  }
   if (puzzle1G.length > 0) {
    for (var i = 0; i < puzzle1G.length; i++) {
     
      var tg = puzzle1G[i];
      var radius1G=dist(tg.x,tg.y,tg.x,tg.y-17.17);
          distance1G = dist(mouseX, mouseY,tg.x,tg.y);
      if (distance1G < radius1G) {
        tg.active = true;
      } else {
       tg.active = false;
      }
    }
  }
   if (puzzle2A.length > 0) {
    for (var i = 0; i < puzzle2A.length; i++) {
     
      var ka = puzzle2A[i];
      var radius2A=dist(ka.x,ka.y,ka.x-25,ka.y-1.67);
          distance2A = dist(mouseX, mouseY,ka.x,ka.y);
      if (distance2A < radius2A) {
        ka.active = true;
      } else {
       ka.active = false;
      }
    }
  }

  if (puzzle2B.length > 0) {
    for (var i = 0; i < puzzle2B.length; i++) {
     
      var kb = puzzle2B[i];
      var radius2B=dist(kb.x,kb.y,kb.x-25,kb.y-25);
          distance2B = dist(mouseX, mouseY,kb.x,kb.y);
      if (distance2B < radius2B) {
        kb.active = true;
      } else {
       kb.active = false;
      }
    }
  }
    if (puzzle2C.length > 0) {
    for (var i = 0; i < puzzle2C.length; i++) {
     
      var kc = puzzle2C[i];
      var radius2C=dist(kc.x,kc.y,kc.x-25,kc.y-1.67);
          distance2C = dist(mouseX, mouseY,kc.x,kc.y);
      if (distance2C < radius2C) {
        kc.active = true;
      } else {
       kc.active = false;
      }
    }
  }
   if (puzzle2D.length > 0) {
    for (var i = 0; i < puzzle2D.length; i++) {
     
      var kd = puzzle2D[i];
      var radius2D=dist(kd.x,kd.y,kd.x-55,kd.y-17.5);
          distance2D = dist(mouseX,mouseY,kd.x,kd.y);
      if (distance2D < radius2D) {
        kd.active = true;
      } else {
       kd.active = false;
      }
    }
  }
  if (puzzle2E.length > 0) {
    for (var i = 0; i < puzzle2E.length; i++) {
     
      var ke = puzzle2E[i];
      var radius2E=dist(ke.x,ke.y,ke.x-25,ke.y);
          distance2E = dist(mouseX,mouseY,ke.x,ke.y);
      if (distance2E < radius2E) {
        ke.active = true;
      } else {
       ke.active = false;
      }
    }
  }
   if (puzzle2F.length > 0) {
    for (var i = 0; i < puzzle2F.length; i++) {
     
      var kf = puzzle2F[i];
      var radius2F=dist(kf.x,kf.y,kf.x,kf.y-16.67);
          distance2F = dist(mouseX,mouseY,kf.x,kf.y);
      if (distance2F < radius2F) {
        kf.active = true;
      } else {
       kf.active = false;
      }
    }
  }
  if (puzzle2G.length > 0) {
    for (var i = 0; i < puzzle2G.length; i++) {
     
      var kg = puzzle2G[i];
      var radius2G=dist(kg.x,kg.y,kg.x,kg.y-16.67);
          distance2G = dist(mouseX,mouseY,kg.x,kg.y);
      if (distance2G < radius2G) {
        kg.active = true;
      } else {
       kg.active = false;
      }
    }
  }
  return false;
}
function mouseDragged() {
   if (puzzle1A.length > 0) {
    for (var i = 0; i < puzzle1A.length; i++) {
      var ta = puzzle1A[i];
     
      if (ta.active) {
        ta.x = mouseX;
       ta.y = mouseY;
       ta.color=ta.color+0.2;
        break;
      }
     
      }
    
  }
   if (puzzle1B.length > 0) {
    for (var i = 0; i < puzzle1B.length; i++) {
      var tb = puzzle1B[i];
     
      if (tb.active) {
        tb.x = mouseX;
       tb.y = mouseY;
       tb.color=tb.color+0.2;
        break;
      }
     
      }
    
  }
   if (puzzle1C.length > 0) {
    for (var i = 0; i < puzzle1C.length; i++) {
      var tc = puzzle1C[i];
     
      if (tc.active) {
        tc.x = mouseX;
       tc.y = mouseY;
       tc.color=tc.color+0.2;
        break;
      }
     
      }
    
  }

if (puzzle1D.length > 0) {
    for (var i = 0; i < puzzle1D.length; i++) {
      var td = puzzle1D[i];
     
      if (td.active) {
        td.x = mouseX;
       td.y = mouseY;
       td.color=td.color+0.2;
        break;
      }
     
      }
    
  }

  if (puzzle1E.length > 0) {
    for (var i = 0; i < puzzle1E.length; i++) {
      var te = puzzle1E[i];
     
      if (te.active) {
        te.x = mouseX;
       te.y = mouseY;
       te.color=te.color+0.2;
        break;
      }
     
      }
    
  }
  if (puzzle1F.length > 0) {
    for (var i = 0; i < puzzle1F.length; i++) {
      var tf = puzzle1F[i];
     
      if (tf.active) {
        tf.x = mouseX;
       tf.y = mouseY;
       tf.color=tf.color+0.2;
        break;
      }
     
      }
    
  }
    if (puzzle1G.length > 0) {
    for (var i = 0; i < puzzle1G.length; i++) {
      var tg = puzzle1G[i];
     
      if (tg.active) {
        tg.x = mouseX;
       tg.y = mouseY;
       tg.color=tg.color+0.2;
        break;
      }
     
      }
    
  }
    if (puzzle2A.length > 0) {
    for (var i = 0; i < puzzle2A.length; i++) {
      var ka = puzzle2A[i];
     
      if (ka.active) {
        ka.x = mouseX;
       ka.y = mouseY;
       ka.color=ka.color+0.2;
        break;
      }
      }
  }
     if (puzzle2B.length > 0) {
    for (var i = 0; i < puzzle2B.length; i++) {
      var kb = puzzle2B[i];
     
      if (kb.active) {
        kb.x = mouseX;
       kb.y = mouseY;
       kb.color=kb.color+0.2;
        break;
      }
      }
  }
     if (puzzle2C.length > 0) {
    for (var i = 0; i < puzzle2C.length; i++) {
      var kc = puzzle2C[i];
     
      if (kc.active) {
        kc.x = mouseX;
       kc.y = mouseY;
       kc.color=kc.color+0.2;
        break;
      }
      }
  }
if (puzzle2D.length > 0) {
    for (var i = 0; i < puzzle2D.length; i++) {
      var kd = puzzle2D[i];
     
      if (kd.active) {
        kd.x = mouseX;
       kd.y = mouseY;
       kd.color=kd.color+0.2;
        break;
      }
      }
  }
if (puzzle2E.length > 0) {
    for (var i = 0; i < puzzle2E.length; i++) {
      var ke = puzzle2E[i];
     
      if (ke.active) {
        ke.x = mouseX;
       ke.y = mouseY;
       ke.color=ke.color+0.2;
        break;
      }
      }
  }
if (puzzle2F.length > 0) {
    for (var i = 0; i < puzzle2F.length; i++) {
      var kf = puzzle2F[i];
     
      if (kf.active) {
        kf.x = mouseX;
       kf.y = mouseY;
       kf.color=kf.color+0.2;
        break;
      }
      }
  }
if (puzzle2G.length > 0) {
    for (var i = 0; i < puzzle2G.length; i++) {
      var kg = puzzle2G[i];
     
      if (kg.active) {
        kg.x = mouseX;
       kg.y = mouseY;
       kg.color=kg.color+0.2;
        break;
      }
      }
  }
  // Prevent default functionality.
  return false;
}

function hint1(){
    textSize(40);
    var b=0;
    b=b+30;
textStyle(BOLD);

fill(67+b,99+b,138+b);
text("DODO BIRD",100,400);
textStyle(ITALIC);
text("~1662",150,450);
}

 function hint2(){
    textSize(40);
    var b=0;
    b=b+30;
textStyle(BOLD);

fill(69+b,93+b,31+b);
text("BLUEBUCK",100,400);
textStyle(ITALIC);
text("~1800",150,450);
}

This Project is inspired by Chinese puzzle and is focused on two extincted animals. The player can click left or right side of the canvas to enter either of the two puzzles. Each puzzle is consist of 7 pieces and hints will show up while the players is “stuck”. After the puzzle is completed the name of the extincted specie will reveal.

Lingfan Jiang & Kai Zhang – Final Project

sketch

//Lingfan Jiang/ Kai Zhang
//Section B
//lingfanj@andrew.cmu.edu / kaiz1@andrew.cmu.edu
//final project

//bird variables
var g = 0.5;
var v = 0;
//upforce
var Fup = 20;
var birdx = 120;
var birdy = 240;
//pipe
var pipes = [];
var currentPipeY;
var gap = 170;
//counter
var successC = 0;
//lean degrees
var gameOn = true;
//terrain
var terrainDetail = 0.002;
var terrainSpeed = -0.001;
//clouds
var clouds = [];
var cloudsx = [];
var cloudsy = [];
var cloudsSpeed = -0.5;
var cloudsSize = [];

var gameOn = true;

var totalTime;
//board content
var level = ["Bronze", "Silver", "Gold", "Platinum", "Diamond", "Master", "王者!"]
var newcolor = ["green", "pink", "gold", "orchid", "tan", "grey", "white"]
var numbercount;


function setup() {
    createCanvas(640,480);
    frameRate(80);
    pipes.push(makePipes()); 
}


function draw() {


    background(170, 237, 239);

    //create cloud objects
    updateAndDisplayclouds();

    terrain();

    updateAndDisplayPipes();

    drawBird(birdx, birdy);

    controlBird();

    //create pipe each 80 frames
    if (frameCount % 90 == 0 & gameOn) {
        pipes.push(makePipes());
    }

    if (pipes.length != 0) {
        //remove the already gone pipes
        if (pipes[0].x < -50) {
            pipes.shift();
        }

        //hit test
        if (pipes[0].x < birdx + 18 & pipes[0].x + 30 > birdx - 18) {
            if (birdy - 15 < pipes[0].gapY || birdy + 15 > pipes[0].gapY + gap) {
                //hit indicator
                fill("red");
                ellipse(birdx + 5, birdy, 30, 30);
                //make the pipes stop
                for (var i = 0; i < pipes.length; i++) {
                    pipes[i].speed = 0;
                }
                gameOn = false;

                //game over content
                textAlign(CENTER);
                textSize(50);
                fill("orange");
                text("GAME OVER", width / 2, height / 2);
                fill("orange");
                push();
                rectMode(CENTER);
                textSize(18);
                rect(320, 300, 100, 50);
                fill(255);
                noStroke();
                text("RESTART", 321, 307);
                pop();

                //add score
                } else if (pipes[0].x == birdx - 2) {
                successC ++;
            }
        }
    }


    drawBoard();
}

////////////////////////////////
function controlBird(){
    v += g;
    birdy += v;

    //make the bird stop when it hits the bottom or the top
    if (birdy > height & gameOn) {
        birdy = height;
        v = 0;
    }
    else{
        birdy = birdy;
    }

    if (birdy < -30) {
        birdy = -30;
        v = 0;
    }
}

function updateAndDisplayclouds(){
    for (var n = 0; n < 8; n ++) {
        cloudsx.push(-150, random(width) + 150);
        cloudsy.push(random(40, 100));
        cloudsSize.push(random(80, 140));

        clouds[n] = makeClouds(cloudsx[n], cloudsy[n], cloudsSize[n]);
        clouds[n].cdraw();
        cloudsx[n] += cloudsSpeed;
        if (cloudsx[n] < -100) {
            cloudsx[n] = random (width + 100, width + 150);
        }
    }
}

function drawBird(x, y) {
    push();
    translate(x, y);
    angleMode(DEGREES);
    rotate(1.5 * v);
    fill("yellow");
    ellipse(0, 0, 36, 30);
    fill("white");
    ellipse(0 + 9, 0 - 5, 15, 15);
    ellipse(0 - 15, 0, 17, 8);
    fill("black");
    ellipse(0 + 13, 0 - 6, 5, 5);
    fill("orange");
    ellipse(0 + 10, 0 + 8, 20, 8);
    ellipse(0 + 10, 0 + 2, 20, 8);
    pop();
}

function drawBoard(){
    noFill();
    strokeWeight(2);
    stroke(0);
    rect(10, 10, 140, 46);
    noStroke();
    fill(0);
    textSize(18);
    textAlign(CENTER);
    text("Score: " + successC, 80, 30);
    text("Level: " + level[numbercount], 80, 48);
    strokeWeight(1);
    stroke(0);
}


function keyPressed() {
    if (key === " " & gameOn) {
        v -= Fup;
        //set up a maximum speed for the bird
        if (v < -10) {
        v = -10;
        }
    }
}


function mouseClicked() {
    //reset the game when the game is over
    if (mouseX > 270 & mouseX < 370 && mouseY > 275 && mouseY < 325 && gameOn == false) {
        pipes = [];
        gameOn = true;
        successC = 0;
    }
}


function makePipes() {
    var pipe = {
        x: 640,
        gapY: random(50, height - gap - 40),
        pwidth: 50,
        speed: 2,
        move: pipeMove,
        draw: pipeDraw,
        col: "green"
    }
    return pipe;
}


function pipeDraw() {
    //change the color and level when the score gets higher
    numbercount = floor(successC / 5);
    if (numbercount > 6) {
        numbercount = 6;
    }
    fill(newcolor[numbercount]);
    push();
    translate(this.x, 0);
    rect(0, -10, this.pwidth, this.gapY);
    rect(-3, this.gapY - 30, this.pwidth + 6, 30);
    rect(0, this.gapY + gap, this.pwidth, height - this.gapY - gap + 10);
    rect(-3, this.gapY + gap, this.pwidth + 6, 30);

    strokeWeight(5);
    stroke(255);
    line(10, 10, 10, this.gapY - 40);
    line(10, 470, 10, this.gapY + gap + 40);

    line(7, this.gapY - 10, 7, this.gapY - 20);
    line(7, gap + this.gapY + 10, 7, gap + this.gapY + 20);
    pop();
}


function pipeMove(){
    this.x -= this.speed;
}


function updateAndDisplayPipes() {
    for (var i = 0; i < pipes.length; i++) {
        pipes[i].move();
        pipes[i].draw();
    }
}


function terrain() {
    push();
    stroke(135, 210, 167);

    for (var q = 0; q < width; q++) {
        var t = (q * terrainDetail) - (millis() * terrainSpeed / 10);
        var y = map(noise(t), 0, 1 , height / 2 - 40, height - 50);
        line(q, y, q, height);
    }
    pop();

}

function makeClouds(x, y, size) {
    var cloud = {"cx": x, "cy": y, "csize": size, "cdraw": cloudDraw};
    return cloud;
}

function cloudDraw() {
    push();
    noStroke();
    fill(255);
    ellipse(this.cx, this.cy, this.csize, this.csize * 0.7);
    pop();
}

Introduction:

For our group final project, we decided to recreate the once viral game on mobile platforms – Flappy Birds, back in 2013. I(Kai) still recall how I would spend hours playing the game and tried to master it. Unfortunately, the game was removed from App Store because of it being “too addictive”. Up till now, I still have the game on my phone, despite it was too old for my current operating system. In order to experience a very unique game again, we tried to take a shot to develop the game.

 

Development Process:

First of all, Lingfan started to build the basic framework of the game, by creating an object “the bird” that will rise as we press the space button using basic physics, along with an array of tubes as objects that show up as time lapsed from right end of the canvas. Then I’ve taken over the file. I first used primitive geometries to create the tubes and the bird so they resemble the original look of the game. Also I’ve created the background and clouds that moved along with the camera panned, of course, of a much slower speed. As a next step, I started working on the “collision” moments when bird hit the tube. The logic is when the x position of tube passes through the location of the bird, the program determines if the bird is in between the gap of the tubes. If not, the tube turned grey, and an indicator would show up and informed the player the bird has hit the tube. The game was pretty much playable at this point, but we still need a reward/failure system, otherwise the game would run forever, even if the bird hits the tube. Lingfan then took over the file again and created it. He set a Boolean that determines if the game is over or not, which changes its value from true to false as it hits the tube. And then a button was created to restart the game. Every time the bird hits the tube, it would fall and we’ll see the “GAME OVER” appearing at the center of the screen. After the restart button is clicked, the code wipes the existing tubes array and brings back the bird so we can replay the game. As a final step, we worked together to clean up the code and further polish the game, including adding the score counter, a game rank indicator that tells you how good you are playing this game, the change of tube colors as you promote to the next level, the 3-dimensional look of the tube, etc. As this point, the game was pretty much finished.

 

Reflections:

One of the surprises about the game we’ve created is how it felt so close to the original game as we are playing. And during the development of the game, we’ve taken advantage of most skills that we acquired during the semester, so we got to practice pretty much everything again. Please go ahead and give it a try, and we hope you will enjoy the game as much as we do.

 

Game instruction:

Simply tap the space key so the bird rises to avoid the tube and earn 1 point each time the bird flies past a gap. You will get to the next level of the rank every time you successfully passed 5 tubes. (We tried to make it a little easier and more rewarding for you, as the original game was pretty hard to beat.)

Tanvi Harkare – Final Project

tanviharkare_sketch

//position of ball
var px = 100;
var py = 100;
var yvel = 4;
var ox = 400;
var bs = 30;

var r = 100;
var rx = 200;
var count = 0;
var score = 0;
var hscore = 0;

var obspeed = 2;

var terrainSpeed = 0.0005;
var terrainDetail = 0.005;
var terrainSpeed2 = 0.0002;
var terrainDetail2 = 0.002;


function preload() {
    mySnd = loadSound("boing.wav");
    mySnd.setVolume(0.5);
}
// to play the sound from within draw() or anywhere:

function setup(){
    createCanvas(400, 400);
    frameRate(30);
}

function draw(){
    background(255);
    py -= yvel;
    yvel -= 0.3;

    for (var x = 0; x < width; x++) {
        stroke(243, 184, 141);
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, 0, height);
        line(x, y, x, height); 
        stroke(143, 61, 75);
        var t2 = (x * terrainDetail2) + (millis() * terrainSpeed2);
        var y2 = map(noise(t2), 0,1, 0, height);
        line(x, y2 + (y2 / 2), x, height); 
    }
    noStroke();
    fill(74, 47, 72);
    ellipse(px, py, bs, bs);
    fill(43, 29, 66);
    if(ox > 0){
        rect(ox, 0, 10, r);
        rect(ox, height - rx, 10, rx);
        ox -= obspeed;        
    }

    else if(ox <= 0){
        r = random(0, 200);
        rx = 300 - r;
        ox = 400;
        score++;
        count++;
        if (count % 5 === 0){
            obspeed += 1;
        }
    }
    intersect();
    fill(0);
    textSize(12);
    text("Score: " + score, 10, 10);
}

function mousePressed(){
    mySnd.play();
    yvel = 6;

}

function intersect(){
    if(py - (bs / 2) < r || py + (bs / 2) > height - rx ){
        if(px < ox + 10 & px > ox - 10){
            if(score > hscore){
                hscore = score;
                score = 0;
            }
            noLoop();
            textSize(18);
            text("You Lost :(", 300, 20);
            text("Score: " + hscore, 300, 50);
            text("Play Again!", 300, 80);
            }
        }
}

For this project, I wanted to create a game that would have a level of difficulty as time progressed. This game is a classic spinoff of the popular game flappy bird – a sphere that bounces every time you click the mouse. Your job is to make sure your sphere doesn’t hit any of the obstacles that move along the screen. In order to get the boing sound every time the ball bounces, download the zip file with all the files!

tharkare_finalzip

Liz Maday Final Project

Liz Maday’s Virtual Instrument

emaday sketch copy

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.

Alessandra Fleck – Final Project

sketch

//Name: Alessandra Fleck 
//Class Section : B
//Email: afleck@andrew.cmu.edu
//Assignment-12-Final

//USING ML5 TO IMPLEMENT MACHINE LEARNING MODEL -- see html for library src
//POSENET - HUMAN POSE ESTIMATION, USING MACHINE LEARNING  

var myCamera; //variable to hold onto webcam data
var poseNet;
var pose =[];
var imgPlanet; //store first planet image
var imgPlanet2; //store second planet image
var imgPlanet3; //store third planet image for right hip

//NON RESPONSIVE BACKGROUND ENVIRONMENT
var stars =[]; //array to hold the stars

//CHARACTER HELMET VARIABLES
var headX = 0;
var headY = 0;
//CHARACTER EYES VARIABLES
var lefteyeX = 0;
var lefteyeY = 0;
var righteyeX = 0;
var righteyeY = 0;
//CHARACTER HANDS
var lefthandX = 0;
var lefthandY = 0;
var righthandX = 0;
var righthandY = 0;
//CHARACTER HIP
var rightHipX = 0;
var rightHipY = 0;


function preload(){
    //load media for use in the sketch
    var planetOneURL = "https://i.imgur.com/f0QBerx.png";
    imgPlanet = loadImage(planetOneURL);
    var planetTwoURL = "https://i.imgur.com/v6UuYtt.png";
    imgPlanet2 = loadImage(planetTwoURL);
    var planetThreeURL = "https://i.imgur.com/bjO4uOW.png";
    imgPlanet3 = loadImage(planetThreeURL);
}

function setup(){
    createCanvas(640,480);
    //load planet one image pixels
    imgPlanet.loadPixels();

    myCamera = createCapture(VIDEO); //giving permission to browser to connect to webcam
    myCamera.size(640,480); //setting display dimensions of camera
    myCamera.hide(); // to hide extra video display below canvas
    poseNet = ml5.poseNet(myCamera, modelLoaded); // load the posenet model and connect it to the video
    poseNet.on('pose', myPose);//when person is detected, execute

}
 //check that ml5 is running on p5js 
function modelLoaded(){
    console.log('model is loaded');
}

//for one person at a time
function myPose(pose){
    //TEST POSE
    console.log(pose); //record+print the poses as detected by the camera
    //note that pose is an array
    if (pose.length > 0){
        //CHARACTER HELMET CAMERA POSITION
        headX = pose[0].pose.keypoints[0].position.x;
        headY = pose[0].pose.keypoints[0].position.y;
        
        //CHARACTER LEFT EYE CAMERA POSITION
        lefteyeX = pose[0].pose.keypoints[1].position.x;
        lefteyeY = pose[0].pose.keypoints[1].position.y;
        //CHARACTER RIGHT EYE CAMERA POSITION
        righteyeX = pose[0].pose.keypoints[2].position.x;
        righteyeY = pose[0].pose.keypoints[2].position.y;
        //CHARACTER LEFT HAND CAMERA POSITION - note that the index is for left wrist
        lefthandX = pose[0].pose.keypoints[9].position.x;
        lefthandY = pose[0].pose.keypoints[9].position.y;
        //CHARACTER RIGHT HAND CAMERA POSITION - note that the index is for left wrist

    //reduce jittering of shapes by implementing linear interpolation 
    //takes position of shape and camera position and taking 0.2 in between
         //RIGHT HAND CAMERA POSTION AND LAG USING LERP FUNCTION
        var righthandNX = pose[0].pose.keypoints[10].position.x;
        var righthandNY = pose[0].pose.keypoints[10].position.y;
        righthandX = lerp(righthandX,righthandNX,0.8);
        righthandY = lerp(righthandY,righthandNY,0.8);

        //CHARACTER RIGHT HIP CAMERA POSITION
        rightHipX = pose[0].pose.keypoints[12].position.x;
        rightHipY = pose[0].pose.keypoints[12].position.y;

    }
}

function draw(){
    //draw the camera image to the canvas using image function
    image(myCamera, 0, 0, width, height); 

    //stars at random
    for(var i=0; i<random(8); i++){
        stars.push(new star()); //put new star into array
    }

    for (var birth of stars){
        birth.display();
    }

    //maintain shape scale to distance from camera
    var cameraDistance = dist(lefteyeX, lefteyeY, righteyeX, righteyeY); 

    filter(POSTERIZE,8); // filters video image into posterize
    filter(INVERT); //overlay gray filter

   
    //CHARACTER HEAD SHAPE SETTING
    fill(250);
    ellipse(headX,headY,200,200); //using nose location for character head
    fill(0);
    ellipse(headX,headY+25,30,10); //using nose location for character mouth
    
    //CHARACTER LEFT EYE SHAPE SETTING
    fill(0);
    ellipse(lefteyeX, lefteyeY, cameraDistance/2,cameraDistance/2);
    //CHARACTER RIGHT EYE SHAPE SETTING
    fill(0);
    ellipse(righteyeX, righteyeY, cameraDistance/2,cameraDistance/2);

    //FIRST (GREEN) PLANET IMAGE MOVING IN RESPONSE TO RIGHT HAND
    image(imgPlanet,righthandX,righthandY,50,50);
    image(imgPlanet,righthandX+50,righthandY+50,100,100);
    image(imgPlanet,righthandX+20,righthandY+100,10,10);
    //SECOND (ORANGE) PLANET IMAGE MOVING IN RESPONSE TO LEFT HAND
    image(imgPlanet2,lefthandX+20,lefthandY,50,50);
    image(imgPlanet2,lefthandX-100,lefthandY,30,30);
    image(imgPlanet2,lefthandX+50,lefthandY+50,60,60);

    //USING CHARACTER RIGHT HIP AS GALAXY
    image(imgPlanet3,rightHipX,rightHipY-50,300,150);


}

function star(){
    this.posX = 0;
    this.posY = random(-100,400);
    this.size = random(50,100);
    this.display = function(){
        fill(0);
        ellipse(this.posX,this.posY, this.size);
    }
}




index

afleck_Final

 

For the final project I wanted to explore a part of p5js that involved computer vision. Originally going to do an Augmented Reality project for objects placement, I ended up going more towards computer vision as it is easier to do with a webcam and there are lots of resources available for it in correlation with p5js. To use computer vision I added the Ml5 library to my html file and used the posNet() model that predicts live time human body estimation with machine learning.

Using posNet I was able to identify different keypoint indexes for different parts of the body and link those to where I could input shapes. As I love space, I thought it might be neat to create a responsive space environment with the movement of the body. I began with making the head and eyes as a large moon thats responds to different distances from the camera and scales to the distance. I then created planets in illustrator and added them into the scene. Using linear interpolation, I was able to detach the keypoint of the wrists from the body and create a bit of a lag so that the planets had the effects of following the wrists, where in reality they were being offset from the keypoint of the wrist and the coordinates of the object.

From this project I got to explore this form of machine learning for the first time. Though it was not as refined as I wanted it to be (as much of the information was very new to me), I enjoyed looking at how computer vision operates and the things it can can do with augmenting reality.

Note: the camera will not work as the library needs to be linked with the html, download and open the source code in the zip file and just open the html file to get started!

 

Nina Yoo- Final Project

Instructions:

You can use keys from A-K to make animations appear. If you match the number of times you press the keys with characters from the same movie the background will show a pic of the movie along with playing a song from the movie.

This project has helped me understand more about the sound and loading images from imgur function as well as looping for animations.It was fun and exciting to see my animations come to life, but I was sadly unable to upload to the site because of my zip file being too big.  The hardest part of this project was figuring out how to make the animations appear and disappear by pressing the same key. To do this I created a function to track if numbers were odd or even and set a value for each time a key is pressed.

How to use:

You have to download all the following files and put it in the same folder. Also,  do not forget to open a local host file. The reason I have to do it this way is because the songs are really big files that are unable to be uploaded all at once. Archive contains the code, index, and animations.

Songs and Background from Studio Ghibli

Totoro

Spirited Away

Kiki’s Delivery Service

Howl’s Moving Castle

songs 2

songss

Archive

 

Audrey Zheng – Final Project

sketch

//Audrey Zheng
//Section A
//audreyz@andrew.cmu.edu




var cubex = 10;
var cubey = 20;
var cubeWidth = 20;

var cube;
var cube2;


var cx;
var cy;

var systems;


function setup() {
    createCanvas(300, 300);
    background(220);
   


    // osc = new p5.TriOsc();
    // osc.freq(880.0);
    // osc.amp(0.1);
    // osc.start();


    cx = width/2;
    cy = width/2;

    cube1 = new cube(200,30);
    cube2 = new cube(20,20);
    cube3 = new cube(150,150);

    
    systems = [];
    

}

function draw() {
    if (millis() > 2000) {
        //osc.stop();
        //noLoop();
    }

    //rect(cubex, cubey, cubeWidth, cubeWidth);

    cube1.display();
    cube2.display();
    cube3.display();

    for (i = 0; i <systems.length; i ++) {
        systems[i].display();
    }
    
    if (systems.length==0) {
        textAlign(CENTER);
        text("Click to add cubes", width/2, height/2);
    }

}

function cube(x,y) { //the cube
    this.x = x;
    this.y = y;

    this.width = 20;


    this.NW =[this.x, this.y];    
    this.NE = [x+this.width, this.y];

    this.SE = [this.x+this.width, y+this.width];

    this.SW = [this.x, y+this.width];

    this.larger = new square(x,y,this.width, this.width);
    this.smaller = new square(x + (cx -x) * 0.25, y + (cy - y) *0.25, this.width * 0.75, this.width * 0.75);


    this.NWs =[(this.x + (cx - this.x) * 0.20), this.y + (cy - this.y) * 0.20];
     
    this.NEs = [(this.x + (cx - this.x) * 0.20) + (this.width * 0.8), this.y + (cy - this.y) * 0.20];

    this.SEs = [(this.x + (cx - this.x) * 0.20) + (this.width * 0.8), this.y + (cy - this.y) * 0.20 + (this.width * 0.8)];

    this.SWs = [(this.x + (cx - this.x) * 0.20), this.y + (cy - this.y) * 0.20 +(this.width * 0.8)];




   
    this.display = function() {
        rect(this.x, this.y, this.width, this.width);
        rect(this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20, this.width * 0.8, this.width * 0.8);
        line(this.NW[0], this.NW[1], this.NWs[0], this.NWs[1]);
        line(this.NE[0], this.NE[1], this.NEs[0], this.NEs[1]);
        line(this.SE[0], this.SE[1], this.SEs[0], this.SEs[1]);

        line(this.SW[0], this.SW[1], this.SWs[0], this.SWs[1]);



    };

}

function square(x,y,w,h) {
    this.x = x;
    this.y = y;
    this.width = w;
    this.height = h;

    this.getCorners = function() {
        var NW =[x-w/2,y-h/2];
        //print(NW);
        var NE = [x+w/2, y-h/2];
        var SE = [x+w/2, y-h/2];
        var SW = [x-w/2, y+h/2];

        return [NW,NE,SE,SW];
    };
}


function mousePressed() {
    this.p = new cube(mouseX,mouseY);
    systems.push(p);
    print(systems);
}




function fillFront() {

}

function fillBottom() {

}

function fillTop() {

}

function fillLeft() {

}

function fillRight() {

}