Assignment 3: OOP

Inspiration

For this assignment, I was inspired by the  Tron movies.  While I was too young to watch the originals, I loved how cool the light cycles were and wanted to make a piece of art that was based on collections of lines moving independently.

The idea I had was to have a collection of random lines bounce off of the walls and off of each other. For added effect, I wanted the lines that bounced off of each other to swap colors, and the background of the piece was to be the color of the line with most bounces.

Implementation

I began writing the class for the Lines. Each had to have a stroke weight, initial X&Y position, a current X&Y position, a dy and dx, a current color, and a list of past colors and X&Y positions. Here’s the code for the constructor I used.

class BouncyLine{
  constructor(dx, dy, radius, posX, posY){
    this.color = color(random(255), random(255), random(255));
    this.dx = dx;
    this.dy = dy;
    this.radius = radius;
    this.posX = posX;
    this.posY = posY;
    this.initposX = posX;
    this.initposY = posY;
    this.numcollisions = 0;
    this.pastlist = [];
  }
}

I would have to update the current posX and posY based on dx and dy, and account for collisions along the wall. I would also have to push a previous line with the current initposX and initposY to the array I had, and then update initposX and Y to the current posX and posY.

updateList(){
  this.pastlist.push([this.initposX, this.initposY, this.posX, this.posY, this.color]);
    this.initposX = this.posX;
    this.initposY = this.posY
}
update(){
  this.posX += this.dx;
  this.posY += this.dy;
  if(this.posX > width-this.radius || this.posX<this.radius){
    this.dx*=-1;
    this.updateList();
  }
  if(this.posY > height-this.radius || this.posY<this.radius){
    this.dy*=-1
    this.updateList();
  }
}

Then, to draw the line, I would have to take the strokeWeight of the line, draw each line in the array, then draw the current one.

draw(){
    strokeWeight(this.radius*2);
    for(let i=0; i<this.pastlist.length; i++){
      stroke(this.pastlist[i][4])
      line(this.pastlist[i][0],this.pastlist[i][1],this.pastlist[i][2],this.pastlist[i][3]);
    }
    stroke(this.color);
    line(this.initposX, this.initposY, this.posX, this.posY);
  }

To simplify, I created a run() method that ran both draw() and update():

//method to draw the circle and update its position
run(){
  this.draw();
  this.update();
}

For the setup() function, I had to initialize all of the lines in an array, making sure that none of them started inside of each other.

let randradius;
let linelist = [];
let maxradius;
let xoffset;
let maxdx;
let maxdy;
let bg;

function setup() {
  createCanvas(500, 500);
  bg = color(220,220,220)
  xoffset = 30;
  maxradius = 3;
  maxdx = 3;
  maxdy = 3;
  for(let i=0; i<width/(xoffset+maxradius)-1; i++){
    randradius = random(maxradius);
    linelist.push(new BouncyLine(
      random(maxdx),
      random(maxdy),
      randradius,
      (i+1)*xoffset,
      random(randradius,height-randradius),
    ));
  }
}

I then had to account for collisions, which was done by checking the Euclidean distance between 2 lines. If a collision was detected, I would find the opposite of the dx and dy for both, and swap their colors after updating the lists for both lines. I would also note the number of collisions they have with each other by incrementing numcollisions for both.

checkCollision(otherHead){
    if(sqrt((otherHead.posX-this.posX)**2+(otherHead.posY-this.posY)**2)<(this.radius+otherHead.radius)){
      this.dx*=-1;
      this.dy*=-1;
      this.updateList();
      otherHead.updateList();
      otherHead.dx*=-1;
      otherHead.dy*=-1;
      let otherColor = otherHead.color;
      otherHead.color = this.color;
      this.color = otherColor;
      this.numcollisions +=1;
      otherHead.numcollisions+=1;
    }
  }

To draw them, I ran the run() method for everything in the linelist, and had a nested for loop to check each combination of lines if there was a collision.

function draw(){
  background(bg);
  for(let i=0; i < linelist.length; i++){
    linelist[i].run();
  }
  for(let i=0; i < linelist.length-1; i++){
    for(let j=i+1; j < linelist.length; j++){
      linelist[i].checkCollision(linelist[j])
    }
  }

Finally, I added a global function that compared the number of collisions, and extracted the color of the line with most collisions. I then set this to the bg variable, which updated each time.

function getMostCollisions(linelist){
  let maxcollisions = 0;
  let maxcollisioncolor;
  for(let i=0; i < linelist.length; i++){
    if(linelist[i].numcollisions>maxcollisions){
      maxcollisions = linelist[i].numcollisions;
      maxcollisioncolor = linelist[i].color;
    }
  }
  return maxcollisioncolor||bg;
}

My piece was complete, and looks like this:

Reflection

I really liked how OOP modularized everything and added to reusability. I would like to keep thinking about how I can best format my code for readability, as the page was pretty cluttered by the end. I would also like to think about expanding my class to handle a list of lines, so that the code would be even more organized.

Leave a Reply