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.