DEV Community

reyes2981
reyes2981

Posted on

what i learned last week: how to make a bouncing object using vanillajs part 2 animation

Welcome to part 2 of how to make a bouncing object using vanillajs! As you may recall, I'm creating a clone of Flappy Bird and I want the player to be controlled with the spacebar. This means that within my program I need to model physics!

CODE SO FAR

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const x = canvas.width / 2;
const y = canvas.height / 2;

Class Player {
  constructor(x, y, radius, color) { 
        this.x = x
        this.y = y
        this.radius = radius 
        this.color = color 
  }

  draw() {
        ctx.beginPath()
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
        ctx.fillStyle = this.color
        ctx.fill()
  }

}

const player = new Player(100, 100, 30, 'blue');
Enter fullscreen mode Exit fullscreen mode

PLAYER IN BROWSER
player object

The first thing I did is add a gravity, velocity and lift property to the constructor of my Player class. The reason why I'm adding these properties is because I want my player object to be affected by physics like they would in the real world.

Class Player {
  constructor(x, y, radius, color, gravity, velocity, lift) { 
        this.x = x;
        this.y = y;
        this.radius = radius; 
        this.color = color; 
        this.gravity = gravity;
        this.velocity = velocity;
        this.lift - lift;
  }
Enter fullscreen mode Exit fullscreen mode

PHYSICS REFRESHER

Gravity, also called gravitation, in mechanics [is] the universal force of attraction acting between all matter.
gravity

Velocity [is the] distance traveled per unit time in one direction.
velocity

Lift occurs when a moving flow of gas is turned by a solid object. The flow is turned in one direction, and the lift is generated in the opposite direction, according to Newton's Third Law of action and reaction. Because air is a gas and the molecules are free to move about, any solid surface can deflect a flow. For an aircraft wing, both the upper and lower surfaces contribute to the flow turning. Neglecting the upper surface's part in turning the flow leads to an incorrect theory of lift.
lift

Next, I created the up class method which runs every time the user presses the spacebar. To create a "bouncing" effect I added the players velocity plus lift and saved it to this.lift.

  up() {
    this.velocity = this.velocity + this.lift;
  }
Enter fullscreen mode Exit fullscreen mode

Alrighty, next I created the class method -- update. This is where I compare Player properties versus where I'm actually manipulating the property on the screen

update() {
   // Update the state of the world for the elapsed time since last render
}
Enter fullscreen mode Exit fullscreen mode

For each frame within our animation loop I'm going to set the velocity of player to this.gravity and the y coordinate to this.velocity.

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const x = canvas.width / 2;
const y = canvas.height / 2;

Class Player {
  constructor(x, y, radius, color, gravity, velocity, lift) { 
        this.x = x;
        this.y = y;
        this.radius = radius; 
        this.color = color; 
        this.gravity = gravity;
        this.velocity = velocity;
        this.lift = lift;
  }

  draw() {
        ctx.beginPath()
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
        ctx.fillStyle = this.color
        ctx.fill()
  }

  update() {
        this.velocity += this.gravity;
        this.y += this.velocity; 
  }

}

const player = new Player(100, 100, 30, 'blue', 0.6, 0, -15);
Enter fullscreen mode Exit fullscreen mode

Next, I created the function animate which is responsible for the looping of the player object. How do I do this?

function animate() {

}
Enter fullscreen mode Exit fullscreen mode

Inside of animate I'm using the requestAnimationFrame method which tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.

function animate() {  
  requestAnimationFrame();
}
Enter fullscreen mode Exit fullscreen mode

In the above example, what do I need to pass into requestAnimationFrame if I want to create a moving object?

function animate() {  
  requestAnimationFrame(animate);
}
Enter fullscreen mode Exit fullscreen mode

Now when I instantiate the function animate a looping effect will be created.

function animate() {  
  requestAnimationFrame(animate);
}

animate();
Enter fullscreen mode Exit fullscreen mode

Lastly, I need to add an EventListener so that the user can control the player by pressing on the spacebar. The first argument I pass in is keyup. The second argument is a callback function that runs the class method up everytime the user presses spacebar

addEventListener('keyup', event => {
    if (event.code === 'Space') {
      player.up();
    }

})
Enter fullscreen mode Exit fullscreen mode

VOILA!

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const x = canvas.width / 2;
const y = canvas.height / 2;

Class Player {
  constructor(x, y, radius, color, gravity, velocity, lift) { 
        this.x = x;
        this.y = y;
        this.radius = radius; 
        this.color = color; 
        this.gravity = gravity;
        this.velocity = velocity;
        this.lift = lift;

  }
  draw() {
        ctx.beginPath()
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
        ctx.fillStyle = this.color
        ctx.fill()
  }
  up() {
    this.velocity += this.lift;
    console.log(this.velocity); 
  }
  update() {
        this.velocity += this.gravity;
        this.y += this.velocity; 
  }
}

const player = new Player(100, 100, 30, 'blue', 0.6, 0, -15);

function animate() {  
  requestAnimationFrame(animate);
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  player.draw();
  player.update();
}

animate();

addEventListener('keyup', event => {
    if (event.code === 'Space') {
      console.log('Space pressed');
      player.up();
    }

})
Enter fullscreen mode Exit fullscreen mode

If you've been following along you should see something like the blue object below with similar animation.

Fin

Top comments (0)