Skip to main content

Paddle Collision - Making Contact Matter

Now for the most important part - making the ball bounce off the paddles! This is what makes Pong actually playable.

Understanding Paddle Collision

For the ball to hit a paddle, we need to check:

  1. Horizontal overlap - Is the ball at the paddle's X position?
  2. Vertical overlap - Is the ball touching the paddle's Y range?

If both are true = COLLISION! 💥

Step 1: Check Left Paddle Collision

Add this code after the ball movement but before the reset check:

  // Bounce off top and bottom walls
if (ballY <= ballSize / 2 || ballY >= height - ballSize / 2) {
ballSpeedY = ballSpeedY * -1;
}

// Check collision with left paddle
if (ballX - ballSize / 2 <= 20 + paddleWidth) {
if (ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) {
ballSpeedX = abs(ballSpeedX); // Make positive (go right)
ballX = 20 + paddleWidth + ballSize / 2; // Push ball away from paddle
}
}

// Reset ball if it goes off left or right edge
if (ballX < 0 || ballX > width) {

Breaking it down

  • ballX - ballSize / 2 <= 20 + paddleWidth

    • ballX - ballSize / 2 is the ball's LEFT edge
    • 20 + paddleWidth is the paddle's RIGHT edge (20 + 10 = 30)
    • Checks if ball's left edge reached paddle's right edge
  • ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight

    • ballY >= leftPaddleY - Ball is below paddle's top
    • ballY <= leftPaddleY + paddleHeight - Ball is above paddle's bottom
    • Both must be true for ball to be in paddle's vertical range
  • ballSpeedX = abs(ballSpeedX)

    • abs() makes the number positive
    • If speed was -5 (going left), becomes 5 (going right)
    • Ensures ball always bounces away from left paddle toward the right
  • ballX = 20 + paddleWidth + ballSize / 2

    • Prevents ball from getting stuck inside paddle
    • Positions ball just outside paddle's right edge
    • 20 + 10 + 7.5 = 37.5 pixels from left

Test it: Move the left paddle to hit the ball - it should bounce back!

Step 2: Check Right Paddle Collision

Now add collision for the right paddle:

  // Check collision with left paddle
if (ballX - ballSize / 2 <= 20 + paddleWidth) {
if (ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) {
ballSpeedX = abs(ballSpeedX);
ballX = 20 + paddleWidth + ballSize / 2;
}
}

// Check collision with right paddle
if (ballX + ballSize / 2 >= 770) {
if (ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight) {
ballSpeedX = -abs(ballSpeedX); // Make negative (go left)
ballX = 770 - ballSize / 2; // Push ball away from paddle
}
}

Breaking it down

  • ballX + ballSize / 2 >= 770

    • ballX + ballSize / 2 is the ball's RIGHT edge
    • 770 is the paddle's LEFT edge
    • Checks if ball's right edge reached paddle's left edge
  • ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight

    • Same vertical check as left paddle
    • Ball must be within paddle's height
  • ballSpeedX = -abs(ballSpeedX)

    • Makes the speed negative
    • If speed was 5 (going right), becomes -5 (going left)
    • Ensures ball bounces away from right paddle toward the left
  • ballX = 770 - ballSize / 2

    • Positions ball just outside paddle's left edge
    • 770 - 7.5 = 762.5 pixels from left

Test it: Both paddles should now bounce the ball!

Step 3: Add Angle Variation Based on Hit Location

Let's make it more interesting - where you hit the ball on the paddle affects the angle:

  // Check collision with left paddle
if (ballX - ballSize / 2 <= 20 + paddleWidth) {
if (ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) {
ballSpeedX = abs(ballSpeedX);
ballX = 20 + paddleWidth + ballSize / 2;

// Change angle based on where ball hit paddle
let hitPos = (ballY - leftPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

// Check collision with right paddle
if (ballX + ballSize / 2 >= 770) {
if (ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight) {
ballSpeedX = -abs(ballSpeedX);
ballX = 770 - ballSize / 2;

// Change angle based on where ball hit paddle
let hitPos = (ballY - rightPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

Breaking it down

  • let hitPos = (ballY - leftPaddleY) / paddleHeight

    • Calculates where on the paddle the ball hit
    • Returns a value from 0 (top) to 1 (bottom)
    • Example: If ball hits middle, hitPos = 0.5
  • ballSpeedY = (hitPos - 0.5) * 10

    • Converts hit position to vertical speed
    • Top half (hitPos < 0.5) makes negative speed (ball goes up)
    • Bottom half (hitPos > 0.5) makes positive speed (ball goes down)
    • Middle (hitPos = 0.5) gives 0 (ball stays level)
    • Multiplied by 10 for noticeable angle changes

How it works:

  • Hit top of paddle → Ball angles upward
  • Hit middle of paddle → Ball stays level
  • Hit bottom of paddle → Ball angles downward
  • This gives players control over ball direction!

Test it: Hit the ball with different parts of the paddle - watch the angle change!

Step 4: Increase Ball Speed Slightly on Each Hit

Make the game progressively harder:

  // Check collision with left paddle
if (ballX - ballSize / 2 <= 20 + paddleWidth) {
if (ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) {
ballSpeedX = abs(ballSpeedX) * 1.05; // Increase speed by 5%
ballX = 20 + paddleWidth + ballSize / 2;

let hitPos = (ballY - leftPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

// Check collision with right paddle
if (ballX + ballSize / 2 >= 770) {
if (ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight) {
ballSpeedX = -abs(ballSpeedX) * 1.05; // Increase speed by 5%
ballX = 770 - ballSize / 2;

let hitPos = (ballY - rightPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

Breaking it down

  • ballSpeedX = abs(ballSpeedX) * 1.05
    • Multiplies speed by 1.05 (increases by 5%)
    • Each hit makes ball slightly faster
    • Creates escalating difficulty
    • Still uses abs() to ensure correct direction

Test it: Play for a while - notice the ball getting faster with each rally!

Complete Collision Code

Here's the complete game with collision detection:

// Left paddle
let leftPaddleY = 200;
let paddleWidth = 10;
let paddleHeight = 80;
let paddleSpeed = 5;

// Right paddle
let rightPaddleY = 200;

// Ball
let ballX = 400;
let ballY = 200;
let ballSize = 15;
let ballSpeedX = 5;
let ballSpeedY = 3;

function setup() {
createCanvas(800, 400);

ballSpeedX = random() > 0.5 ? 5 : -5;
ballSpeedY = random(-3, 3);
}

function draw() {
background(0);

// Draw center line
stroke(255);
strokeWeight(2);
for (let i = 0; i < height; i += 20) {
line(width / 2, i, width / 2, i + 10);
}
noStroke();

// Left paddle movement
if (keyIsDown(87)) {
leftPaddleY -= paddleSpeed;
}
if (keyIsDown(83)) {
leftPaddleY += paddleSpeed;
}
leftPaddleY = constrain(leftPaddleY, 0, height - paddleHeight);

// Right paddle movement
if (keyIsDown(UP_ARROW)) {
rightPaddleY -= paddleSpeed;
}
if (keyIsDown(DOWN_ARROW)) {
rightPaddleY += paddleSpeed;
}
rightPaddleY = constrain(rightPaddleY, 0, height - paddleHeight);

// Move the ball
ballX += ballSpeedX;
ballY += ballSpeedY;

// Bounce off top and bottom walls
if (ballY <= ballSize / 2 || ballY >= height - ballSize / 2) {
ballSpeedY = ballSpeedY * -1;
}

// Check collision with left paddle
if (ballX - ballSize / 2 <= 20 + paddleWidth) {
if (ballY >= leftPaddleY && ballY <= leftPaddleY + paddleHeight) {
ballSpeedX = abs(ballSpeedX) * 1.05;
ballX = 20 + paddleWidth + ballSize / 2;

let hitPos = (ballY - leftPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

// Check collision with right paddle
if (ballX + ballSize / 2 >= 770) {
if (ballY >= rightPaddleY && ballY <= rightPaddleY + paddleHeight) {
ballSpeedX = -abs(ballSpeedX) * 1.05;
ballX = 770 - ballSize / 2;

let hitPos = (ballY - rightPaddleY) / paddleHeight;
ballSpeedY = (hitPos - 0.5) * 10;
}
}

// Reset ball if it goes off left or right edge
if (ballX < 0 || ballX > width) {
ballX = width / 2;
ballY = height / 2;
ballSpeedX = random() > 0.5 ? 5 : -5;
ballSpeedY = random(-3, 3);
}

// Draw left paddle
fill(255);
rect(20, leftPaddleY, paddleWidth, paddleHeight);

// Draw right paddle
rect(770, rightPaddleY, paddleWidth, paddleHeight);

// Draw ball
circle(ballX, ballY, ballSize);
}

What You Learned

In this step, you:

  • ✅ Detected collision between ball and paddles
  • ✅ Made ball bounce in the correct direction
  • ✅ Prevented ball from getting stuck in paddles
  • ✅ Added angle variation based on hit location
  • ✅ Increased ball speed gradually for difficulty
  • ✅ Created realistic Pong physics!

What's Next?

You now have a fully playable Pong game! But we're missing one crucial element - keeping score. Next, we'll add a scoring system so players know who's winning.

Coming up: Score tracking and display!


Next Step: Scoring System - Tracking Points