(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.