Pong is one of the first computer games ever created, way back in 1972. If you have never heard of Pong, you can think of it as a kind of “tennis” game. There are two paddles, on each side of the screen. They move up and down. The goal is to bounce a ball between the two paddles. If you miss the ball, your opponent scores a point.
Atari created Pong and put it in arcades. The name of the game is derived from the game of ping-pong. Pong has been remade many times, with different features and gameplay elements added or removed.
Want to know more? Get the Book!
You will use Anthropic’s Claude AI to create this game in Python using the pygame package.
Let’s get started!
Creating the Game
Prompt: Please create the pong videogame using Python and pygame. Give the user a way to start a new game and keep score.
I’ll create a classic Pong game for you using Python and pygame. This will include two paddles, a ball, scoring, and the ability to start new games.
import pygame
import sys
import random
# Initialize Pygame
pygame.init()
# Constants
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PADDLE_WIDTH = 15
PADDLE_HEIGHT = 90
BALL_SIZE = 15
PADDLE_SPEED = 7
BALL_SPEED_X = 6
BALL_SPEED_Y = 6
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
class Paddle:
def __init__(self, x, y):
self.rect = pygame.Rect(
x, y, PADDLE_WIDTH, PADDLE_HEIGHT)
self.speed = PADDLE_SPEED
def move_up(self):
if self.rect.top > 0:
self.rect.y -= self.speed
def move_down(self):
if self.rect.bottom < SCREEN_HEIGHT:
self.rect.y += self.speed
def draw(self, screen):
pygame.draw.rect(screen, WHITE, self.rect)
class Ball:
def __init__(self):
self.rect = pygame.Rect(
SCREEN_WIDTH // 2,
SCREEN_HEIGHT // 2,
BALL_SIZE,
BALL_SIZE)
self.reset_ball()
def reset_ball(self):
self.rect.center = (SCREEN_WIDTH // 2,
SCREEN_HEIGHT // 2)
self.speed_x = BALL_SPEED_X * random.choice([-1, 1])
self.speed_y = BALL_SPEED_Y * random.choice([-1, 1])
def move(self):
self.rect.x += self.speed_x
self.rect.y += self.speed_y
# Bounce off top and bottom walls
if (self.rect.top <= 0
or self.rect.bottom >= SCREEN_HEIGHT):
self.speed_y = -self.speed_y
def draw(self, screen):
pygame.draw.rect(screen, WHITE, self.rect)
class PongGame:
def __init__(self):
self.screen = pygame.display.set_mode(
(SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pong Game")
self.clock = pygame.time.Clock()
# Create game objects
self.left_paddle = Paddle(
30, SCREEN_HEIGHT // 2 - PADDLE_HEIGHT // 2)
self.right_paddle = Paddle(
SCREEN_WIDTH - 30 - PADDLE_WIDTH,
SCREEN_HEIGHT // 2 - PADDLE_HEIGHT // 2)
self.ball = Ball()
# Scores
self.left_score = 0
self.right_score = 0
self.font = pygame.font.Font(None, 74)
self.small_font = pygame.font.Font(None, 36)
# Game state
self.game_state = "menu" # "menu", "playing", "paused"
def handle_collision(self):
# Ball collision with paddles
if self.ball.rect.colliderect(self.left_paddle.rect):
# Only bounce if moving toward paddle
if self.ball.speed_x < 0:
self.ball.speed_x = -self.ball.speed_x
# Add some variation based on where ball hits paddle
hit_pos = (self.ball.rect.centery - self.left_paddle.rect.centery
) / (PADDLE_HEIGHT / 2)
self.ball.speed_y += hit_pos * 2
if self.ball.rect.colliderect(self.right_paddle.rect):
# Only bounce if moving toward paddle
if self.ball.speed_x > 0:
self.ball.speed_x = -self.ball.speed_x
# Add some variation based on where ball hits paddle
hit_pos = (self.ball.rect.centery - self.right_paddle.rect.centery
) / (PADDLE_HEIGHT / 2)
self.ball.speed_y += hit_pos * 2
# Limit ball speed
max_speed = 12
if abs(self.ball.speed_y) > max_speed:
self.ball.speed_y = max_speed if self.ball.speed_y > 0 else -max_speed
def check_scoring(self):
# Check if ball went off screen
if self.ball.rect.left <= 0:
self.right_score += 1
self.ball.reset_ball()
elif self.ball.rect.right >= SCREEN_WIDTH:
self.left_score += 1
self.ball.reset_ball()
def handle_input(self):
keys = pygame.key.get_pressed()
if self.game_state == "playing":
# Left paddle controls (W/S)
if keys[pygame.K_w]:
self.left_paddle.move_up()
if keys[pygame.K_s]:
self.left_paddle.move_down()
# Right paddle controls (UP/DOWN arrows)
if keys[pygame.K_UP]:
self.right_paddle.move_up()
if keys[pygame.K_DOWN]:
self.right_paddle.move_down()
def draw_menu(self):
self.screen.fill(BLACK)
title_text = self.font.render("PONG", True, WHITE)
title_rect = title_text.get_rect(
center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(title_text, title_rect)
start_text = self.small_font.render(
"Press SPACE to Start", True, WHITE)
start_rect = start_text.get_rect(
center=(SCREEN_WIDTH // 2, 250))
self.screen.blit(start_text, start_rect)
controls_text = [
"Controls:",
"Left Player: W (Up) / S (Down)",
"Right Player: Arrow Keys",
"Press R to restart during game",
"Press ESC to return to menu"
]
for i, text in enumerate(controls_text):
rendered_text = self.small_font.render(
text, True, GRAY if i == 0 else WHITE)
text_rect = rendered_text.get_rect(
center=(SCREEN_WIDTH // 2, 320 + i * 40))
self.screen.blit(rendered_text, text_rect)
def draw_game(self):
self.screen.fill(BLACK)
# Draw center line
for i in range(0, SCREEN_HEIGHT, 20):
if i % 40 == 0:
pygame.draw.rect(
self.screen,
WHITE,
(SCREEN_WIDTH // 2 - 2, i, 4, 10))
# Draw paddles and ball
self.left_paddle.draw(self.screen)
self.right_paddle.draw(self.screen)
self.ball.draw(self.screen)
# Draw scores
left_score_text = self.font.render(
str(self.left_score), True, WHITE)
right_score_text = self.font.render(
str(self.right_score), True, WHITE)
self.screen.blit(left_score_text, (SCREEN_WIDTH // 4, 50))
self.screen.blit(
right_score_text,
(3 * SCREEN_WIDTH // 4 - right_score_text.get_width(),
50))
# Draw instructions
instruction_text = self.small_font.render(
"Press ESC for menu, R to restart", True, GRAY)
instruction_rect = instruction_text.get_rect(
center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 30))
self.screen.blit(instruction_text, instruction_rect)
def reset_game(self):
self.left_score = 0
self.right_score = 0
self.ball.reset_ball()
self.left_paddle.rect.y = (SCREEN_HEIGHT // 2 -
PADDLE_HEIGHT // 2)
self.right_paddle.rect.y = (SCREEN_HEIGHT // 2 -
PADDLE_HEIGHT // 2)
def run(self):
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_SPACE
and self.game_state == "menu"):
self.game_state = "playing"
self.reset_game()
elif event.key == pygame.K_ESCAPE:
self.game_state = "menu"
elif (event.key == pygame.K_r
and self.game_state == "playing"):
self.reset_game()
if self.game_state == "menu":
self.draw_menu()
elif self.game_state == "playing":
self.handle_input()
self.ball.move()
self.handle_collision()
self.check_scoring()
self.draw_game()
pygame.display.flip()
self.clock.tick(60)
pygame.quit()
sys.exit()
if __name__ == "__main__":
game = PongGame()
game.run()
I’ve created a complete Pong game in Python using pygame! Here are the key features:
Game Features:
- Classic Pong gameplay with two paddles and a bouncing ball
- Score tracking for both players
- Menu system with game start option
- Ability to restart games and return to menu
Controls:
- Left Player: W (up) / S (down)
- Right Player: Arrow keys (up/down)
- SPACE: Start new game from menu
- R: Restart current game
- ESC: Return to main menu
Game Mechanics:
- Ball bounces off top/bottom walls and paddles
- Ball speed varies slightly based on where it hits the paddle
- Scores increase when ball goes off either side
- Ball resets to center after each score
To run the game:
- Make sure you have pygame installed:
pip install pygame - Save the code to a
.pyfile (e.g.,pong.py) - Run it with:
python pong.py
The game includes a clean menu system, smooth 60 FPS gameplay, and responsive controls. The ball physics include some randomization to keep gameplay interesting, and the paddle collisions add a bit of strategy by allowing players to influence the ball’s trajectory based on where they hit it.
Prompt: Can you explain how the code works?
I’ll break down how the Pong game code works, explaining each major component and how they work together.
Code Structure Overview
The code is organized using object-oriented programming with three main classes:
Paddle– represents the player paddlesBall– handles the bouncing ballPongGame– manages the overall game logic and flow
1. Initialization and Constants
pygame.init() # Constants define game dimensions and speeds SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 PADDLE_SPEED = 7
The game starts by initializing pygame and defining constants for screen size, object dimensions, and movement speeds. Using constants makes the code easier to modify and maintain.
2. The Paddle Class
class Paddle:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y, PADDLE_WIDTH, PADDLE_HEIGHT)
Each paddle is represented as a pygame.Rect object, which provides built-in collision detection and positioning. The paddle has methods to:
move_up()andmove_down()– handle movement with boundary checkingdraw()– renders the paddle as a white rectangle
The boundary checking ensures paddles can’t move off-screen:
if self.rect.top > 0: # Don't go above screen if self.rect.bottom < SCREEN_HEIGHT: # Don't go below screen
3. The Ball Class
class Ball:
def reset_ball(self):
self.speed_x = BALL_SPEED_X * random.choice([-1, 1])
self.speed_y = BALL_SPEED_Y * random.choice([-1, 1])
The ball maintains its position and velocity. Key features:
reset_ball()– centers the ball and gives it a random directionmove()– updates position and handles wall bouncing- Wall collision detection flips the Y velocity:
self.speed_y = -self.speed_y
4. Main Game Class Structure
The PongGame class manages everything:
Game States
self.game_state = "menu" # "menu", "playing", "paused"
The game uses states to control what’s displayed and what input is accepted.
Game Loop
def run(self):
while running:
# Handle events (keyboard, quit)
# Update game logic based on current state
# Draw everything
# Control frame rate (60 FPS)
5. Collision Detection
The most complex part handles ball-paddle collisions:
def handle_collision(self):
if self.ball.rect.colliderect(self.left_paddle.rect):
# Only bounce if moving toward paddle
if self.ball.speed_x < 0:
self.ball.speed_x = -self.ball.speed_x
Key points:
- Uses pygame’s built-in
colliderect()for collision detection - Checks ball direction to prevent multiple bounces
- Adds spin based on where the ball hits the paddle:
hit_pos = (self.ball.rect.centery -
self.left_paddle.rect.centery
) / (PADDLE_HEIGHT / 2)
self.ball.speed_y += hit_pos * 2
6. Input Handling
def handle_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.left_paddle.move_up()
The game checks which keys are currently pressed each frame, allowing for smooth continuous movement. Different keys are handled based on the game state.
7. Scoring System
def check_scoring(self):
if self.ball.rect.left <= 0: # Ball went off left side
self.right_score += 1
self.ball.reset_ball()
Scoring is checked every frame by seeing if the ball has moved past the screen edges.
8. Rendering System
The game uses different drawing functions for different states:
draw_menu()– shows title and instructionsdraw_game()– renders paddles, ball, scores, and game elements
The center dashed line is drawn using a loop:
for i in range(0, SCREEN_HEIGHT, 20):
if i % 40 == 0: # Only draw every other dash
pygame.draw.rect(
self.screen,
WHITE,
(SCREEN_WIDTH // 2 - 2, i, 4, 10))
9. Game Flow
- Initialization: Create paddles, ball, set up pygame
- Main Loop:
- Process input events
- Update game logic (if playing)
- Draw current state
- Maintain 60 FPS with clock.tick(60)
- State Management: Switch between menu and gameplay based on user input
Key Programming Concepts Used
- Object-Oriented Design: Separate classes for different game elements
- Event-Driven Programming: Responding to keyboard and quit events
- Game Loop Pattern: Continuous update-draw cycle
- State Management: Different behaviors based on current game state
- Collision Detection: Using pygame’s rectangle collision methods
- Vector Math: Ball movement with X/Y velocity components
The code is structured to be easily extensible – you could add features like AI opponents, power-ups, or different game modes by building on this foundation.
Running Pong
Now that you have the code and understand how to use it, you are ready to run the code. You can run your code in your Python IDE or on the command line like this:
python pong.py
When you first launch your game, you will see the following welcome screen:

If you press the SPACE key, you will see the actual game, which will look something like this:

Grab a friend or play against yourself. The game works pretty well, although playing solo can be rather challenging.
Pong is a fun little game. Much like ping-pong or table tennis, the game is designed to be played with someone else. Technically, you could also create a computer opponent, but you usually play Pong between two people instead.
You should play the game with a friend or family member. You can also study the code to discover how it works. Then, when you are ready, you can start improving the game.
Get the Book
This article is from my latest Python book, Vibe Coding Video Games with Python.
You can get Vibe Coding Video Games with Python at the following websites:
