Tutorial 1 of 4

Physics Basics: Velocity, Acceleration & Gravity

20 min read Intermediate JavaScript + Canvas

What You'll Learn

Physics is what makes games feel real. Without it, your characters float unnaturally, balls don't bounce, and nothing feels satisfying to interact with.

In this tutorial, you'll learn:

Velocity: The Foundation of Movement

Velocity is simply "how fast something moves and in what direction". In 2D games, we represent it with two values: vx (horizontal) and vy (vertical).

position = position + velocity
or: x += vx; y += vy;
ball-velocity.js
const ball = {
    x: 100,
    y: 100,
    vx: 3,   // Moving right at 3 pixels per frame
    vy: 2    // Moving down at 2 pixels per frame
};

function update() {
    // Apply velocity to position
    ball.x += ball.vx;
    ball.y += ball.vy;
}

function gameLoop() {
    update();
    render();
    requestAnimationFrame(gameLoop);
}
Pro Tip

Velocity values can be negative! A negative vx means moving left, and a negative vy means moving up.

Acceleration: Changing Velocity

Acceleration is the rate at which velocity changes. Just like velocity changes position, acceleration changes velocity.

velocity = velocity + acceleration
then: position = position + velocity

This is what makes a car speed up, a ball fall faster, or a rocket lift off. The key insight: acceleration affects velocity, velocity affects position.

ball-acceleration.js
const ball = {
    x: 100,
    y: 100,
    vx: 0,
    vy: 0,
    ax: 0.1,  // Accelerating right
    ay: 0     // No vertical acceleration
};

function update() {
    // Apply acceleration to velocity
    ball.vx += ball.ax;
    ball.vy += ball.ay;
    
    // Apply velocity to position
    ball.x += ball.vx;
    ball.y += ball.vy;
}

Gravity: Constant Downward Acceleration

Gravity is just acceleration that always pulls downward. In games, we typically use a constant value like 0.5 or 0.98.

Physics Insight

Real gravity is 9.8 m/s². In games, we use smaller values because we're measuring in pixels per frame, not meters per second.

gravity.js
const GRAVITY = 0.5;  // Downward acceleration

const ball = {
    x: 200,
    y: 50,
    vx: 2,
    vy: 0,    // Starts with no vertical velocity
    radius: 15
};

function update() {
    // Apply gravity (constant downward acceleration)
    ball.vy += GRAVITY;
    
    // Apply velocity
    ball.x += ball.vx;
    ball.y += ball.vy;
}

Notice how GRAVITY is added to vy every frame. This means:

Bouncing: Reversing Velocity

When a ball hits the ground, its velocity reverses. But in the real world, bouncing loses energy. We simulate this with a bounce factor.

velocity = -velocity × bounce
where bounce is typically 0.7 to 0.9
bounce.js
const GRAVITY = 0.5;
const BOUNCE = 0.8;   // 80% energy retained on bounce
const GROUND = 350;   // Y position of the ground

function update() {
    // Apply gravity
    ball.vy += GRAVITY;
    
    // Apply velocity
    ball.y += ball.vy;
    
    // Check ground collision
    if (ball.y + ball.radius > GROUND) {
        ball.y = GROUND - ball.radius;  // Reset position
        ball.vy = -ball.vy * BOUNCE;    // Reverse and reduce velocity
    }
}

Interactive Demo

See all these concepts in action! Click "Reset" to drop a new ball.

Bouncing Ball Simulation
Velocity Y: 0 Position Y: 0 Bounces: 0

Complete Code

Here's the full bouncing ball simulation you can copy and use:

complete-bouncing-ball.js
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// Physics constants
const GRAVITY = 0.5;
const BOUNCE = 0.8;
const FRICTION = 0.99;

// Ball object
const ball = {
    x: canvas.width / 2,
    y: 50,
    vx: 3,
    vy: 0,
    radius: 20,
    color: '#00FFFF'
};

function update() {
    // Apply gravity
    ball.vy += GRAVITY;
    
    // Apply friction (air resistance)
    ball.vx *= FRICTION;
    
    // Update position
    ball.x += ball.vx;
    ball.y += ball.vy;
    
    // Ground collision
    if (ball.y + ball.radius > canvas.height) {
        ball.y = canvas.height - ball.radius;
        ball.vy = -ball.vy * BOUNCE;
    }
    
    // Wall collisions
    if (ball.x - ball.radius < 0 || ball.x + ball.radius > canvas.width) {
        ball.vx = -ball.vx * BOUNCE;
        ball.x = Math.max(ball.radius, Math.min(ball.x, canvas.width - ball.radius));
    }
}

function render() {
    // Clear canvas
    ctx.fillStyle = '#0A0A12';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    // Draw ball with glow effect
    ctx.shadowColor = ball.color;
    ctx.shadowBlur = 20;
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
    ctx.fillStyle = ball.color;
    ctx.fill();
    ctx.shadowBlur = 0;
}

function gameLoop() {
    update();
    render();
    requestAnimationFrame(gameLoop);
}

gameLoop();

Challenge: Try These Modifications

  1. Multiple Balls: Create an array of balls with random starting positions
  2. Mouse Click: Spawn a new ball where the user clicks
  3. Variable Gravity: Use arrow keys to change gravity direction
  4. Ceiling Bounce: Make balls also bounce off the top
Next Steps

In the next tutorial, we'll learn about Collision Response – how to make objects push each other and react realistically when they collide!