Week 2: Corner Contact (Production)

 

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

Author: Hubert Chang

NYUAD Class of 2027

Leave a Reply