Final Project: Survive the Particles

For my final project, I create a particle game in which the player attempts to avoid an increasing amount of particles which follow the cursor. The circular cursor is controlled by the mouse and is the direction in which all the particles move individually towards. A timer tracks the number of red particles on the screen and acts as a scoreboard which halts when the cursor makes contact with a particle. This game is based off one of my favorite iPhone apps which I discuss in my project priors and precursors.

The main source code comes from the Flock Particle Mutual Interactions example from our class notes. Overall, I was able to execute my original proposal. There were some features that I found worked better than others which was the main difference between my proposal and my final project.

 

sketch

//Kyle Lee
//Section C
//kdlee@andrew.cmu.edu
//Final Project

function particleUpdate() {
    if (this.bFixed == false) {
        this.vx *= this.damping;
        this.vy *= this.damping;

        this.px += this.vx;
        this.py += this.vy;
    }
    if (this.px + particleDiameter/2 > width ||
        this.px - particleDiameter/2 < 0){
        this.vx = -this.vx;
    }
    if (this.py + particleDiameter/2 > height ||
        this.py - particleDiameter/2 < 0){
        this.vy = -this.vy;
    }
}

var particleDiameter = 8;
function particleDraw() {
    fill("#FA4E44");//red
    ellipse(this.px, this.py, particleDiameter, particleDiameter);
}

// add a force to the particle using F = mA
function particleAddForce(fx, fy) {
    var ax = fx / this.mass;
    var ay = fy / this.mass;
    this.vx += ax;
    this.vy += ay;
}


// make a new particle
function makeParticle(x, y, dx, dy) {
    var p = {px: x, py: y, vx: dx, vy: dy,
             mass: 1.0, damping: 0.9,
             bFixed: false,
             addForce: particleAddForce,
             update: particleUpdate,
             draw: particleDraw
            }
    return p;
}

var seekFactor = 0.0010;
function seek(p) {
    var desiredX = mouseX - p.px;
    var desiredY = mouseY - p.py;
    p.addForce(desiredX * seekFactor, desiredY * seekFactor);
}

//attempt to implement a restart without reloading page.
//Unable to empty array and restart time
// function keyPressed() {
//     loop();
//     background();
//     time = 0;
//     myParticles.push(time);
// }

var myParticles = [];
var nParticles = 1000;
var follow = true;
var cursorD = 30;
var x = 200;
var y = 200;
var diffx = 0;
var diffy = 0;

function setup() {
    createCanvas(400, 400);
    for (var i = 0; i < nParticles; i++) {
        var rx = random(width);
        var ry = random(height);
        var p = makeParticle(rx, ry, 0, 0);
        p.bElasticBoundaries = false;
        p.damping = 0.99;
        myParticles[i] = p;
    }
    frameRate(25);
    noStroke();
}

function draw() {
    background(250);
    var time = ceil(frameCount/10);
    var xConstrain = constrain(x, cursorD/2, width - cursorD/2);//mouse boundary
    var yConstrain = constrain(y, cursorD/2, height - cursorD/2);//mouse boundary
    for (var i = 0; i < time; i++) {
        var ithParticle = myParticles[i];
        ithParticle.fx = 0;
        ithParticle.fy = 0;
        if (follow) seek(ithParticle);
    }

    fill("#FA9998");
    textAlign(CENTER);
    textStyle(BOLD);
    textSize(36);
    text(time, width/2, 100);//displays time/score

    fill("#2A3447");
    ellipseMode(CENTER);
    diffx = mouseX - x;
    diffy = mouseY - y;
    x = x + 0.2*diffx;
    y = y + 0.2*diffy;
    ellipse(xConstrain, yConstrain, cursorD, cursorD);//draws cursor/player

    for (var i = 0; i < time; i++) {
        var p = myParticles[i]
        var length = dist(xConstrain, yConstrain, p.px, p.py);
        p.update(); // update all locations
        p.draw(); // draw all particles

        if (length < cursorD/2){//stops game
            textStyle(BOLD);
            textSize(48);
            fill("#FA4E44");
            text("Game Over", width/2, height/2);

            textStyle(NORMAL);
            textSize(14);
            fill(0);
            text("reload to restart", width/2, height/2 + 20);
            noLoop();
        }
    }
}

Leave a Reply