Task:
Create a generative art that utilizes object-oriented programming concept and interactivity with mouse and/or keyboard.
Final Product:
Progress:
I started by creating a class called spark, basically a object that displays as an ellipse. Created a simple physics system where the balls location is updated according to its velocity and acceleration which are all variables unique to every object.
Initial code:
var array = [];
function setup() {
createCanvas(400, 400);
array[0] = new Spark(1,200,0,1,0);
}
function draw() {
background(220);
for (var i = 0;i < array.length;i +=1){
array[i].gravity();
array[i].motion();
array[i].show();
}
}
class Spark {
constructor(iteration,posx,posy,vx,vy){
this.iteration = iteration;
this.posx = posx;
this.posy = posy;
this.vx = vx;
this.vy = vy;
}
gravity(){
this.vy += 1;
}
motion(){
this.posx +=this.vx;
this.posy +=this.vy;
if(this.posx <= 0){
this.vx*=-1;
}
if(this.posx >= 400){
this.vx*=-1;
}
if(this.posy <= 0){
this.vy*=-1;
}
if(this.posy >= 400){
this.vy*=-1;
}
}
show(){
fill(255,0,0);
ellipse(this.posx,this.posy,40/this.iteration);
}
}
Then I wrote a function called burst(), where the ball will split into two upon collision with walls.
The code instantly crashed, and I lost all my work because I haven’t saved on the web editor. At first I thought it was because splitting was too much calculation for the computer, but it turned out I was creating a new spark object within the spark class, which is problematic. So I created a function called burstt() outside of the class, and use the inner burst to exchange information for the outer function to perform the actual bursting operation.
After getting the splitting to work, I added parameters to the spark class, with a iteration variable indicating which generation the spark is currently at. I had the sparks change color and shrink in size according to its current generation, and also set up conditions for the sparks that are greater than a certain iteration to stop updating.
Finally I decided to add more interactivity to the sketch by switching the burst function from triggering upon collision to triggering upon mouse click. I also changed the direction of gravity from pointing down to pointing towards the mouse. Which ended up looking very visually pleasing and fun to interact with using the mouse.
Video:
Final Code:
var lastLoc = [];
var array = [];
var maxN = 100000;
var counter = 0;
function setup() {
createCanvas(500, 500);
array[0] = new Spark(1,200,0,1,0);
}
function draw() {
background(20);
for (var i = 0;i < array.length;i +=1){
if (array[i].alive()){
array[i].gravity();
array[i].motion();
array[i].show();
}
else{
}
}
}
function mousePressed(){
//spawn new spark
//lastLoc = [];
//array = [];
//maxN = 1000;
//counter = 0;
//append(array,new Spark(1,200,0,1,0));
var temp = array.length;
for (var i = 0;i < temp;i +=1){
if (array[i].alive()){
burstt(array[i]);
}
}
}
function burstt(obj){
//console.log(lastLoc,counter);
if (counter < maxN){
obj.burst();
append(array,new Spark(counter+1,lastLoc[0],lastLoc[1],random(-60,60),random(-60,60)));
counter += 1;
}
}
class Spark {
constructor(iteration,posx,posy,vx,vy){
this.iteration = iteration;
this.posx = posx;
this.posy = posy;
this.vx = vx;
this.vy = vy;
this.color = [(random(250)/iteration),random(255),random(50)*iteration]
}
burst(){
//console.log(“hi”);
lastLoc = [this.posx,this.posy,this.vx,this.vy];
this.iteration+=1;
this.color = [(random(239)),random(255),10+random(8)*this.iteration]
this.vx = random(-4,4);
//append(array,new Spark(this.iteration +1,this.posx,this.posy,1,1));
}
gravity(){
this.vx *= 0.99;
this.vy *= 0.99;
if(this.posy < mouseY){
this.vy += 2;
}
else if (this.posy > mouseY){
this.vy -=2;
}
if(this.posx < mouseX){
this.vx += 2;
}
else if (this.posx > mouseX){
this.vx -=2;
}
}
motion(){
this.posx +=this.vx;
this.posy +=this.vy;
if(this.posx <= 0){
this.vx*=-1;
this.posx=1;
}
if(this.posx >= width){
this.vx*=-1;
this.posx=width-1;
}
if(this.posy <= 0){
this.vy*=-1;
this.posy=1;
//burst(this);
}
if(this.posy >= height){
this.vy*=-1;
this.posy=height-1;
if (this.iteration < 23){
//burst(this);
}
}
}
show(){
if (this.iteration < 23){
fill(this.color[0],this.color[1],this.color[2]);
ellipse(this.posx,this.posy,100- 4*this.iteration);
}
}
alive(){
return this.iteration <= 22;
}
}
Reflection:
I really like the concept of OOP, as it is a great way to organize code and is really convenient to work with for the purpose of creating things such as generative arts, or video games.
The biggest challenge I had during this project was having the program crash every time I try to split the object, the program does not treat it as an syntax error, it just keeps running and crashes.
I think the idea of changing the direction of gravity according to mouse position was a very nice change, it was really easy to implement since I have already created the physics system, and it looks very visually good. Because it somewhat follows the physics of real life, but it is at the same time impossible in real life because nothing has such a strong gravity like the one I gave the mouse. So the interaction feels really natural but new at the same time.