Ellan Suder – Final Project

I wanted to make something visually appealing and interesting to play around with. I first started with the white dot and kept building to it every few days, like the glowing colors, the grid background, and eventually some floating particles.

The spacebar control was actually a mistake I made when I was trying to put in the attraction behavior, but I ended up liking it so I added it to the final program.

Controls: Control the dot with your mouse. Press A to attract, hold dot to repel. Hold spacebar to stop and control particles with mouse. Press X to delete the text.

(Holding the dot while pressing A looks pretty cool!)

sketch

/*
Ellan Suder
15104 1 D
esuder@andrew.cmu.edu
Final Project
*/

// variables for main body
var t = 0;
var r = 0;
var xLoc = 250;
var yLoc = 250;
var diffx = 0;
var diffy = 0;
var targetX = 250;
var targetY = 250;
var diameter = 20;
var opacity = 0;
var dragging = false;

// variables for grid + dots
var freq = 0.001;
var dotColor = 35;

// variables for particles
var particles = [];
var numP = 30;
var particleColor = 255;
var capturedP = 0;
var particleCaptured = false;
var stop = false;
var attract = false;
var diffxP = 0;
var diffyP = 0;

// variable for showing text
var showText = true;
  
function setup() {
    createCanvas(500, 500);
    noCursor();
  
    // make particles
    for (var i = 0; i < numP; i++) {
        var p = makeParticle(random(width), random(height),
                             random(-0.1, 0.1), random(-0.1, 0.1));
        particles.push(p);
    }
}

// drawing the grid, 
// the main white dot, 
// the particles,
// and the instructions text.
function draw() {
    background(0,20);
    noStroke();
    
    // make grid pattern using for loop
    for(var q = 0; q < height/20; q++)
    {
      for(var w = 0; w < width/20; w++)
      {
           // I measured distance from each rect to the center
           // to create subtle gradient. smaller dist = lighter
           dGrid = dist(w*20,q*20,width/2,height/2);
           fill(30 - dGrid/10);
           rectMode(CENTER);
           rect(w*20+10,
                q*20+10,
                15,15);
        
           // creates dot if random number < freq
           // when mouse is pressed, freq increases and
           // chance of making dot increases
           e = random(0,1);
           if(e < freq) {
             fill(dotColor);
             ellipse(w*20+20,
                     q*20+20,
                     5,5);
           }
      }
    }
  
    diffx = mouseX - xLoc;
    diffy = mouseY - yLoc;
    r += 0.1;
    xLoc += 0.05*diffx + sin(r/20)/10;
    yLoc += 0.05*diffy + cos(r/20)/10;
  
    t += 0.01;
    randomColor = color(noise(t)*255,noise(t)*255,noise(t+60)*255, opacity);
    
    // main body (white dot controlled by mouseX and mouseY
    // with some easing for aesthetic purposes)
    fill(255);
    ellipse(xLoc, yLoc, diameter/2, diameter/2);
    // layers of colored circles
    opacity = 10;
    fill(randomColor);
    ellipse(xLoc + sin(r)/2, yLoc + cos(r)/2, diameter*2, diameter*2);
    ellipse(xLoc + sin(r)/2, yLoc + cos(r)/2, diameter*3, diameter*3);
    ellipse(xLoc + sin(r)/2, yLoc + cos(r)/2, diameter*5, diameter*5);
    ellipse(xLoc + sin(r)/2, yLoc + cos(r)/2, diameter*8, diameter*8);

    // when dragging == true, the main dot goes to the mouse
    // and spins faster
    if (dragging) {
        xLoc = mouseX + sin(r*50)*5;
        yLoc = mouseY + cos(r*50)*5;
    }
   
    // draw particles
    for (var i = 0; i < particles.length; i++) {
      var p = particles[i];
      p.step();
      p.draw();
    }
   
    if (showText) {
      let words = 'control the dot with your mouse.       press A to attract, hold dot to repel.  hold spacebar to stop and control particles with mouse.';
      textSize(28);
      strokeWeight(1);
      fill(255,100);
      text(words, width/2, height/2, 
                  width/2+30, height/2+80);
      textSize(15);
      text('press x to remove message.', 2*width/5, 3*height/4);
    }
}

// controlling the behavior of the particles
function particleStep() {
    if (stop) {
        // when space is pressed, particle motion halts
        // and you can control them with the mouse
        this.x += 0.05*diffx;
        this.y += 0.05*diffy;
        this.dx = 0;
        this.dy = 0;
    } else if (attract) {
        // when 'a' or 'A' is pressed, particles are drawn
        // to the mouse
        diffxP = mouseX - this.x;
        diffyP = mouseY - this.y;
        this.x += 0.05*diffxP;
        this.y += 0.05*diffyP;
    } else {
        // if no keys are pressed
        this.x += this.dx;
        this.y += this.dy + cos(r)/5;
    }
    
    // bounce off right
    if (this.x > width) {
        this.x = width - (this.x - width);
        this.dx = -this.dx;
    // bounce off left
    } else if (this.x < 0) {
        this.x = -this.x;
        this.dx = -this.dx;
    }
    // bounce off bottom
      if (this.y > height) {
        this.y = height - (this.y - height);
        this.dy = -this.dy;
    // bounce off top
    } else if (this.y < 0) {
        this.y = -this.y;
        this.dy = -this.dy;
    }
  
    // If mouse gets close to a particle, particle becomes captured
    // and the number of captured particles increases.
    // Size of orbit is fixed, but the modifier of the angle is
    // randomized so that each particle's orbit speed is different.
    if (dist(this.x, this.y, xLoc, yLoc) < 20) {
      this.particleCaptured = true;
      capturedP += 1;
      this.orbit += capturedP;
      this.modifier = random(-1,1);
    }
  
    // This controls what a captured particle does
    // captured particles orbit the mouse.
    // I keep track of number of captured particles
    // because each newly captured particle's orbit
    // increases slightly so they don't overlap.
    if (this.particleCaptured) {
      this.x = xLoc + this.orbit*sin(r*this.modifier);
      this.y = yLoc + this.orbit*cos(r*this.modifier);
    }
   
    // Captured particles get launched outwards when dragging == true
    // Reset orbit of all captured particles
    if (dragging & this.particleCaptured) {
      this.particleCaptured = false;
      this.orbit = 5;
      this.dx = random(-5,5);
      this.dy = random(-5,5);
      this.x += this.dx;
      this.y += this.dy;
    }
}

function particleDraw() {
    stroke(255,150);
    strokeWeight(3);
    point(this.x, this.y);
}

// when mouse is pressed close to the main white dot, 
// freq of grid dots increases, 
// dragging == true,
// and # of captured particles resets
function mousePressed() {
    if (dist(xLoc, yLoc, mouseX, mouseY) < 3*diameter) {
        dragging = true;
        capturedP = 0;
        freq = 0.006;
        dotColor = 60;
    }
}

function mouseReleased() {
    dragging = false;
    freq = 0.001;
    dotColor = 35;
} 

// when keys are pressed, 
// variables become true and the program changes the behavior
// in the particleStep function.
// spacebar -> stop particles and control them
// a or A -> particles attracted to mouse
function keyPressed() {
  if (key == ' ') {
      stop = true;
  }
  if (key == 'a' || key == 'A') {
      attract = true;
  }
  if (key == 'x' || key == 'X') {
      showText = false;
  }
}  

function keyReleased() {
  if (key == ' ') {
      stop = false;
  }
  
  if (key == 'a' || key == 'A') {
      attract = false;
  }
}

function makeParticle(px, py, pdx, pdy) {
    p = {x: px, y: py,
         dx: pdx, dy: pdy,
         particleCaptured: false,
         orbit: 5,
         modifier: 1,
         step: particleStep,
         draw: particleDraw
        }
    return p;
}

Leave a Reply