(You can wait until it hits the corner naturally or hold Mouse1 to Speed it Up)
Before what I have here, this project started with me really curious to experiment with 3D objects, but the WEBGL system got terribly confusing with all sorts of new functions and ways I had to approach drawing shapes. I gave up on that and decided to first focus on 2D for this assignment.
I had a real tough time coming up with an idea after that. I thought about it over the weekend and I landed on the idea that I wanted whatever I made to feel satisfying, so I started thinking of things that are visually satisfying. This reminded me of a YouTube short I recently saw about how the DVD screensaver can ever only touch two opposite corners and NEVER the corner adjacent to them. This fact really lived in my head rent-free for a bit but it also made me wonder if I could create simple physics in p5js to recreate a DVD screensaver with the little JavaScript that I understood.
I started with just a ball and a simple if statement that detected whether the x position of the ball was greater than the width minus the radius, essentially allowing me to cause things to happen when the borders of the ball touched the edge. Once I had both the X and Y movements done, I needed to check for corner contacts.
function edgeBounce(i) {
if (xPos[i] > width - radius[i] || xPos[i] < radius[i]) {
xSpeed[i] *= -1;
}
if (yPos[i] > height - radius[i] || yPos[i] < radius[i]) {
ySpeed[i] *= -1;
}
}
Also, I know these are two dimensional circles but I will continue to refer to them as balls.
The time it would take for the ball to hit one of the corners took a really long time so I wanted to add the ability to speed up the ball animation! At first I tried to use the while() to detect when mouseIsPressed but after a lot of confusion I realized it had to be and if() function instead. However, I learned two important things today: the first was that while-else() was not a thing like if-else() is, and how to return variables from a function. It was such a natural way of learning through trial and error and it felt quite satisfying.
I eventually figured out how to do it by assigning a function, speedUp(), to return a value straight into the multiplier variable.
//somewhere in draw()
for (let i = 0; i < xPos.length; i++) {
// move ball
multiplier = speedUp(i);
//..lots of code inbetween
function speedUp(i){
if (mouseIsPressed){
return timeMultiplier;
} else{
return 1;
}
}
While I was here, I felt like the background looked a little bland at first so I decided to have a faint text in the background that would say the current speed multiplier. I made sure to have it drawn first so it’s always layered underneath the circles.
//MULTIPLIER TEXT
textSize(400);
textAlign(CENTER,CENTER);
noStroke();
fill(multiplierColor);
text(speedUp() + "x", width/2, height/2);
And of course the main highlight of this assignment was to use loops. I was actually quite proud of how quickly I got the hang of the for loops and using arrays to take advantage of each loop.
for (let i = 0; i < xPos.length; i++) {
// move ball
multiplier = speedUp(i);
xPos[i] += xSpeed[i] * multiplier;
yPos[i] += ySpeed[i] * multiplier;
edgeBounce(i); //checks for edge touch
cornerBounce(i) //checks for corner touch, creates a new ball if successful
// draw ball
let c = ballColors[i];
fill(c[0], c[1], c[2]); //RGB values of c
stroke(c[0]-20, c[1]-20, c[2]-20); //-20 shifts it a little darker
strokeWeight(8);
ellipse(xPos[i], yPos[i], radius[i] * 2);
}//end of for loop
Difficulties Endured
A lot of tutorials I followed would introduce things I was not familiar with at all so I did workarounds that were probably a lot less efficient.
But most importantly, I crashed so many times and had to redo so much of my work so many times.
I originally wanted to have the new balls come out from the corner that the “motherball” contacted but when I tested my code it ended up spawning an infinite number of balls and caused my tab to completely crash and required me to redo almost 20 minutes of work.
I remember I had to write and rewrite the cornerBounce() function twice and it was really frustrating especially because of how long the if() statement was.
function cornerBounce(i){
if ((xPos[i] <= radius[i] || xPos[i] >= width - radius[i]) &&
(yPos[i] <= radius[i] || yPos[i] >= height - radius[i])) {
console.log("Corner Contact Confirmed")
if(ballCount < maxBallCount){
console.log("Ball #" + xPos.length + " was Created")
xPos.push(width/2); //PUSH adds to an array
yPos.push(height/2); //if spawn in the corner it creates infinite balls
xSpeed.push(random(-8, 8));
ySpeed.push(random(-8, 8));
//assigns a random color
let newColor = random(colorOptions);
ballColors.push(newColor);
radius.push(50);
ballCount += 1;
} else if (ballCount == maxBallCount){
console.log("Max Ball Count Reached")
}//ends the ballcount if()
}//ends the if()
}
Conclusion
Even thought my web editor crashed half a dozen times and disheartened me throughout the process, the trial and error felt like a satisfying loop of learning that will certainly help me navigate JavaScript a little more easily with each passing week.