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');
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;
}
PHYSICS REFRESHER
Gravity, also called gravitation, in mechanics [is] the universal force of attraction acting between all matter.

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

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.

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;
}
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
}
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);
Next, I created the function animate which is responsible for the looping of the player object. How do I do this?
function animate() {
}
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();
}
In the above example, what do I need to pass into requestAnimationFrame if I want to create a moving object?
function animate() {
requestAnimationFrame(animate);
}
Now when I instantiate the function animate a looping effect will be created.
function animate() {
requestAnimationFrame(animate);
}
animate();
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();
}
})
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();
}
})
If you've been following along you should see something like the blue object below with similar animation.

Fin


Top comments (0)