Tutorials › Game Physics JS Mode

Game Physics

Learn how real-seeming motion works in games: velocity, gravity, friction, and collision detection — the building blocks of every platformer and arcade game.

1

Velocity: Speed with Direction

In games, we don't just move things by saying "go right." We use velocity — a number that says how fast something moves AND which direction. A positive vx moves right, a negative vx moves left. Same for vy: positive goes down, negative goes up. Each frame, we add the velocity to the position.
0 / 32 lines
Loading editor...
let vx = 2, vy = -1; function setup() { size(400, 300); } function draw() { background("midnightblue"); // Add velocity to position each frame x += vx; y += vy; // Wrap around edges if (x > width) x = 0; if (x < 0) x = width; if (y > height) y = 0; if (y < 0) y = height; // Draw the ball fill("gold"); noStroke(); circle(x, y, 15); // Show the velocity fill("white"); textSize(14); text("vx = " + vx + " (moving right)", 10, 20); text("vy = " + vy + " (moving up!)", 10, 40); text("Position: (" + Math.round(x) + ", " + Math.round(y) + ")", 10, 280); }
Try it!

Change vx to -3 and vy to 2. Which direction does the ball go now? Try (0, 3) for straight down!

2

Gravity: Acceleration That Pulls Down

Gravity isn't a speed — it's an acceleration. That means it changes the velocity over time. Each frame, we add a small gravity value to vy. The ball starts slow, then falls faster and faster — just like in real life! This is how every platformer game works.
0 / 35 lines
Loading editor...
let vy = 0; let gravity = 0.3; function setup() { size(400, 300); } function draw() { background("midnightblue"); // Gravity increases vy each frame vy += gravity; // Velocity moves the ball y += vy; // Reset when it falls off screen if (y > height + 20) { y = 0; vy = 0; } // Draw the ball fill("tomato"); noStroke(); circle(x, y, 20); // Show what's happening fill("white"); textSize(14); text("vy = " + vy.toFixed(1), 10, 20); text("gravity adds " + gravity + " to vy each frame", 10, 40); text("The ball gets FASTER as it falls!", 10, 280); }
Try it!

Try changing gravity to 0.1 (moon gravity!) or 1.0 (super heavy). How does it feel different?

3

Bouncing Off the Floor

When a ball hits the floor, we need to reverse its vy to make it go up. But in real life, bounces lose energy — the ball doesn't bounce back to the same height. We simulate this by multiplying vy by something like -0.8. The minus flips direction, and the 0.8 reduces the speed by 20%.
0 / 44 lines
Loading editor...
let vy = 0; let gravity = 0.4; function setup() { size(400, 300); } function draw() { background("midnightblue"); // Apply gravity vy += gravity; y += vy; // Bounce off the floor! if (y > height - 15) { y = height - 15; vy = vy * -0.8; // Reverse AND lose 20% energy } // Draw the ball fill("gold"); noStroke(); circle(x, y, 15); // Draw the "floor" stroke("white"); strokeWeight(2); line(0, height - 1, width, height - 1); // Info noStroke(); fill("white"); textSize(14); text("vy = " + vy.toFixed(1), 10, 20); text("Each bounce loses 20% energy", 10, 40); text("Click to reset!", 10, 280); } function mousePressed() { y = 30; vy = 0; }
Try it!

Change -0.8 to -1.0 for a perfect bounce (no energy loss). Try -0.5 for a heavy, dead bounce.

4

Friction: Slowing Down

Friction makes things slow down over time. Instead of subtracting speed, we multiply vx by a number close to 1, like 0.99. Each frame, the speed drops a tiny bit. Over many frames, it adds up! This is how you make things slide to a stop. Let's add arrow keys so you can push the ball around.
0 / 48 lines
Loading editor...
let vx = 0, vy = 0; let friction = 0.98; let gravity = 0.3; function setup() { size(400, 300); } function draw() { background("midnightblue"); // Arrow keys add velocity (thrust!) if (keyIsDown("ArrowLeft")) vx -= 0.5; if (keyIsDown("ArrowRight")) vx += 0.5; if (keyIsDown("ArrowUp")) vy -= 0.5; // Gravity pulls down vy += gravity; // Friction slows horizontal movement vx *= friction; // Move the ball x += vx; y += vy; // Bounce off walls if (x < 12) { x = 12; vx *= -0.7; } if (x > width - 12) { x = width - 12; vx *= -0.7; } // Bounce off floor if (y > height - 12) { y = height - 12; vy *= -0.7; vx *= 0.95; // Floor friction too! } // Draw fill("mediumseagreen"); noStroke(); circle(x, y, 12); fill("white"); textSize(14); text("Arrow keys to push!", 10, 20); text("vx: " + vx.toFixed(2), 10, 280); }
Try it!

Change friction from 0.98 to 0.90 — it stops much faster! Try 1.0 for no friction (ice!).

5

Circle vs Circle Collision

How do you know if two circles are touching? Measure the distance between their centers using dist(). If the distance is less than the sum of their radii, they're overlapping! Here, the ball gets pushed away from a mouse-controlled circle.
0 / 60 lines
Loading editor...
let vx = 0, vy = 0; let ballR = 15; let cursorR = 25; let gravity = 0.2; function setup() { size(400, 300); } function draw() { background("midnightblue"); // Apply gravity and friction vy += gravity; vx *= 0.99; // Move the ball ballX += vx; ballY += vy; // Floor bounce if (ballY > height - ballR) { ballY = height - ballR; vy *= -0.75; } // Wall bounce if (ballX < ballR) { ballX = ballR; vx *= -0.8; } if (ballX > width - ballR) { ballX = width - ballR; vx *= -0.8; } // COLLISION: check distance between centers let d = dist(mouseX, mouseY, ballX, ballY); let minDist = cursorR + ballR; if (d < minDist && d > 0) { // Push the ball away from the cursor let pushX = (ballX - mouseX) / d; let pushY = (ballY - mouseY) / d; vx += pushX * 3; vy += pushY * 3; } // Draw cursor circle noFill(); stroke("dodgerblue"); strokeWeight(2); circle(mouseX, mouseY, cursorR); // Draw the ball fill(d < minDist ? "tomato" : "gold"); noStroke(); circle(ballX, ballY, ballR); // Info fill("white"); textSize(13); text("Distance: " + Math.round(d) + "px", 10, 20); text("Colliding: " + (d < minDist ? "YES!" : "no"), 10, 40); text("Push the ball around with your mouse!", 10, 280); }
6

Multiple Balls with Physics

Let's bring it all together! An array of balls, each with its own position and velocity. Every frame: apply gravity, move, bounce off walls, and check collisions with the mouse. This is the foundation of how real game physics engines work.
0 / 66 lines
Loading editor...
function setup() { size(400, 300); for (let i = 0; i < 8; i++) { balls.push({ x: random(30, 370), y: random(30, 100), vx: random(-2, 2), vy: 0, r: random(8, 18), color: "hsl(" + (i * 45) + ", 75%, 60%)" }); } } function draw() { background("midnightblue"); for (let i = 0; i < balls.length; i++) { let b = balls[i]; // Gravity b.vy += 0.25; // Friction b.vx *= 0.999; // Move b.x += b.vx; b.y += b.vy; // Bounce off walls if (b.x < b.r) { b.x = b.r; b.vx *= -0.8; } if (b.x > width - b.r) { b.x = width - b.r; b.vx *= -0.8; } // Bounce off floor if (b.y > height - b.r) { b.y = height - b.r; b.vy *= -0.8; b.vx *= 0.95; } // Mouse push let d = dist(mouseX, mouseY, b.x, b.y); if (d < 30 + b.r && d > 0) { b.vx += (b.x - mouseX) / d * 2; b.vy += (b.y - mouseY) / d * 2; } // Draw fill(b.color); noStroke(); circle(b.x, b.y, b.r); } fill("white"); textSize(14); text("Move your mouse to push the balls!", 80, 20); noFill(); stroke("white"); strokeWeight(1); circle(mouseX, mouseY, 30); }
Try it!

Try changing the gravity to 0 for a zero-gravity space scene! Or add more balls by changing 8 to 20.

What to try next

  • Add a ceiling bounce so balls can't fly off the top of the screen
  • Make balls collide with EACH OTHER — check dist() between every pair of balls
  • Add a click-to-launch feature: click anywhere to spawn a new ball with velocity toward the mouse
  • Build a simple platformer character: arrow keys for left/right, up to jump (only when on the ground!)