Overview and Concept
For this OOP project, since I have never done this before, I just wanted to test if I understand the class, the constructor, the array, and how to push new items into an array, and so I decided to create some “atoms” that bounce around in the canvas.
They are called atoms, because my original concept that I wanted to make was atoms, that are red and are following a certain path on the screen but it got lost in translation, and started to look more like confetti, so I decided to leave it for that day.
I have astigmatism, which just means that especially in the dark light sources seem a little weird (the photo demonstrates it better) and weirdly, I got inspired by that on Saturday, when I was with a friend out at night. I think the balls in the end were just much easier to make than those lights that I usually see, but it just clicked something in my brain. So I moved on from my initial idea and started to work on something else.

The concept that I used in the end was kind of a mixture of the two: I made some ellipses that are going around but not on a predetermined route but randomly, and from my astigmatism came the idea to make them almost vibrating and very very colourful.
The Code
(click on the canvas as many times as you want)
So the code was very hard to do, and I was struggling a lot with it not working. To start with, I created the basics, I made an array to store my atoms in, and then in the draw function I made a for loop to loop that array and its elements. In the for loop, there are three other functions that I am going to explain later in the class.
let atoms = []; //setting the array
function setup() {
createCanvas(400, 400);
}
function draw() {
background('black');
//for loop goes throught the array, checks the index of each element and displays all of them
for (let i = 0; i < atoms.length; i++){
//called function from class, updates their position
atoms[i].atomMotion();
//called function from class, determining how the atoms look like
atoms[i].display();
//called function from class, recognising the borders of the screen
atoms[i].checkEdge();
}
}
After this, I made a mouseClicked function to add elements to my array. I tried to explain what it does inside of the code.
//when mouse is clicked a new atom will appear at the point of click, in the this.x and this.y the coordinates of the click get saved for that specific new atom as the mouseX and mouseY coordinated were given for the new one, and then the new atom gets pushed into the array with a new index (i)
function mouseClicked(){
atoms.push(new Atom(mouseX, mouseY));
}
And then I created the Atom class. I wanted to make it fun, so I added randomisation to quite a few attributes of the atoms, such as their diameter and how fast they will be moving around the screen. I decided to name their attributes only x and y because any other name just confused me, since these are referring to where the mouse was clicked and so where the atom formed.
class Atom{
//x and y are defined as the coordinates of center of the atom, the mouse position at the time of the click, and so each atoms gets assigned that value at the start
constructor(x, y){
this.x = x;
this.y = y;
//each atom gets assigned a random diameter
this.diameter = random(10, 80);
//each atom gets assigned a random speed
this.velocityX = random(-4, 4);
this.velocityY = random(-4, 4);
}
After this was the hardest part of the whole code, but also what I am most proud of because I wanted them to not move out of the canvas, so I had to make them bounce back from the walls. To do this I needed some videos explaining to me the “science behind it”, for example, how to change the atoms’ motion once they detect the sides of the canvas: in the end I ended up multiplied their current velocity with -1 to reverse them back once they detected the edge. I also had to understand HOW it can detect the edge, but once I saw a video about it I understood and made my own code.
Basically what I did, is I divided the (randomly) assigned diameter of each atom to get the radius of each. The this.x and this.y are the midpoints of the atoms, so I checked if their leftmost and top points (so the midpoint minus the radius) are < 0, so past the canvas’ borders. (this is the example of the left side’s code)
if (this.x - radius < 0) {
this.x = radius,
this.velocityX *= -1;
}
The second part of the if statement snaps the atoms back to the canvas in case they moved too fast and went a few pixels out of frame by putting their midpoint back at where they used to be. This was what took me a very long time, because sometimes they would just glitch into the wall. And lastly came the switching direction.
The else if statements do the exact same thing, with the only difference that they check the rightmost and the bottom parts, that is why here the radius is plus not minus.
Here is the full code of the bouncing:
checkEdge(){
let radius = this.diameter / 2;
//first it checks the LEFT side, if the leftmost edge of the ball (center minus its radius) reaches x = 0, so the left side of the screen, it snaps it back, and then reverses the direction
if (this.x - radius < 0) {
this.x = radius,
this.velocityX *= -1;
}
//first else if checks the RIGHT side the same way
else if (this.x + radius > width) {
this.x = width - radius;
this.velocityX *= -1;
console.log('this works');
}
//second if checks the TOP of the screen the same way
if (this.y - radius < 0) {
this.y = radius;
this.velocityY *= -1;
}
//second else if checks the BOTTOM of the screen the same way
else if (this.y + radius > height) {
this.y = height - radius;
this.velocityY *= -1;
console.log('this works too');
}
}
After this was relatively easy to finish the code. I am lying though a little, because I finished this earlier than I did the previous checkEdge part. But regardless, this part I was able to relatively quickly. Most of hówhat I did is explained in the code itself.
But just to add on a litte, I love playing with the random function, so I also decided to make the colours and oppacity of the atoms randomised, and so they no longer look like atoms but confetti. However, at this point I had too many functions and variables connected to and named atom that I didn’t dare change anything.
//this function updtaes the atoms' position after the click has happened, and the new atom is added to the array, its temporary position, so the one saved into the this.x and this.y parameters gets added to a randomised velocity value give above
atomMotion(){
this.x = this.x + this.velocityX;
this.y = this.y + this.velocityY;
}
//defines how the atoms actually look on the screen, and updates it every time
display(){
noStroke();
//fills in the circles, but the colours and the transparency is randomised
fill(random(0, 255), random(0, 255), random(0, 255), random(90, 200));
//actually drawing the ellipse or circle
ellipse(this.x, this.y, this.diameter, this.diameter);
}
}
And lastly here is the full code in one:
let atoms = []; //setting the array
function setup() {
createCanvas(400, 400);
}
function draw() {
background('black');
//for loop goes throught the array, checks the index of each element and displays all of them
for (let i = 0; i < atoms.length; i++){
//called function from class, updates their position
atoms[i].move();
//called function from class, determining how the atoms look like
atoms[i].show();
//called function from class, recognising the borders of the screen
atoms[i].checkEdge();
}
}
//when mouse is clicked a new atom will appear at the point of click, in the this.x and this.y the coordinates of the click get saved for that specific new atom as the mouseX and mouseY coordinated were given for the new one, and then the new atom gets pushed into the array with a new index (i)
function mouseClicked(){
atoms.push(new Atom(mouseX, mouseY));
}
class Atom{
//x and y are defined as the coordinates of center of the atom, the mouse position at the time of the click, and so each atoms gets assigned that value at the start
constructor(x, y){
this.x = x;
this.y = y;
//each atom gets assigned a random diameter
this.diameter = random(10, 80);
//each atom gets assigned a random speed
this.velocityX = random(-4, 4);
this.velocityY = random(-4, 4);
}
checkEdge(){
let radius = this.diameter / 2;
//first if checks the LEft side, if the leftmost edge if the ball (center minus its radius) reaches x = 0, so the left side of the screen, it snaps it back, and then reverses the direction
if (this.x - radius < 0) {
this.x = radius,
this.velocityX *= -1;
}
//first else if checks the RIGHT side the same way
else if (this.x + radius > width) {
this.x = width - radius;
this.velocityX *= -1;
console.log('this works');
}
//second if checks the TOP of the screen the same way
if (this.y - radius < 0) {
this.y = radius;
this.velocityY *= -1;
}
//second else if checks the BOTTOM of the screen the same way
else if (this.y + radius > height) {
this.y = height - radius;
this.velocityY *= -1;
console.log('this works too');
}
}
//this function updtaes the atoms' position after the click has happened, and the new atom is added to the array, its temporary position, so the one saved into the this.x and this.y parameters gets added to a randomised velocity value give above
move (){
this.x = this.x + this.velocityX;
this.y = this.y + this.velocityY;
}
//defines how the atoms actually look on the screen, and updates it every time
show (){
noStroke();
//fills in the circles, but the colours and the transparency is randomised
fill(random(0, 255), random(0, 255), random(0, 255), random(90, 200));
//actually drawing the ellipse or circle
ellipse(this.x, this.y, this.diameter, this.diameter);
}
}
Problems
Problems I ran into in the code was mainy with the bouncing: in the beginning it wouldn’t work, then it worked but only on two sides, then only on three and all atoms disappeared on the bottom, but in the end I did manage to make it all work. It also glitched sometimes into the wall.
I think I have already mentioned this, but the main problems I ran into were that I needed to catch up on the elements of a class, of OOP as a whole, and I didn’t realise this until AFTER I started working on the code, so I had to pause and watch some tutorials and explaining videos.
References:
I got the main idea from this video:
These two helped to understand the bouncing technique more:
Helped to understand how to push an object into array:
https://stackoverflow.com/questions/40250139/how-can-i-push-an-object-into-an-array