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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 = [];
}
}
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 = []; } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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();
}
}
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(); } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
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); }
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():

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//method to draw the circle and update its position
run(){
this.draw();
this.update();
}
//method to draw the circle and update its position run(){ this.draw(); this.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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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),
));
}
}
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), )); } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
}
}
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; } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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])
}
}
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]) } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
}
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; }
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