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.