Pong Game Code in Python (Turtle, Full Program)

You can write Pong game code in Python with just the built-in turtle module: two stretched squares for paddles, a circle for the ball, keyboard bindings, and a loop that moves the ball and checks for bounces. No installs needed:

import turtle
screen = turtle.Screen()
screen.tracer(0)        # draw frames yourself for smooth motion

I ran the full game below on Python 3.12.5 on Windows; the screenshot is the real game window at the end of a match.

We’ll build the window, paddles and ball, add keyboard controls, handle bounces and scoring, test the collision logic, and add a simple computer opponent.

Pong game code in Python (full program)

Save this as pong.py and run it. Player A uses W and S, Player B uses the Up and Down arrows, and the first to 3 points wins:

import time
import turtle

WIDTH, HEIGHT = 800, 600
WINNING_SCORE = 3

screen = turtle.Screen()
screen.title("Pong")
screen.bgcolor("black")
screen.setup(WIDTH, HEIGHT)
screen.tracer(0)                               # we redraw manually for smooth movement

def make(shape, x, stretch_len=1, stretch_wid=1):
    t = turtle.Turtle(shape)
    t.color("white")
    t.penup()
    t.shapesize(stretch_wid=stretch_wid, stretch_len=stretch_len)
    t.goto(x, 0)
    return t

left = make("square", -350, stretch_wid=5)     # paddles are stretched squares
right = make("square", 350, stretch_wid=5)
ball = make("circle", 0)
ball.dx, ball.dy = 4, 3

pen = turtle.Turtle(visible=False)
pen.color("white")
pen.penup()
pen.goto(0, 250)
score = {"left": 0, "right": 0}

def draw_score():
    pen.clear()
    pen.write(f"Player A: {score['left']}    Player B: {score['right']}", align="center", font=("Courier", 20, "normal"))

def move(paddle, dy):
    y = paddle.ycor() + dy
    paddle.sety(max(-250, min(250, y)))        # keep the paddle on screen

screen.listen()
screen.onkeypress(lambda: move(left, 25), "w")
screen.onkeypress(lambda: move(left, -25), "s")
screen.onkeypress(lambda: move(right, 25), "Up")
screen.onkeypress(lambda: move(right, -25), "Down")

draw_score()
while max(score.values()) < WINNING_SCORE:
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    if abs(ball.ycor()) > 290:                 # bounce off top and bottom
        ball.dy *= -1
    for paddle, side in ((right, 1), (left, -1)):
        if 330 < ball.xcor() * side < 350 and abs(ball.ycor() - paddle.ycor()) < 50:
            ball.dx = -abs(ball.dx) * side     # bounce back toward the other player
    if abs(ball.xcor()) > 390:                 # someone missed
        score["left" if ball.xcor() > 0 else "right"] += 1
        print(f"Point! A {score['left']} - B {score['right']}")
        ball.goto(0, 0)
        ball.dx *= -1
        draw_score()

    screen.update()
    time.sleep(1 / 120)

winner = "A" if score["left"] == WINNING_SCORE else "B"
pen.goto(0, 0)
pen.write(f"Player {winner} wins!", align="center", font=("Courier", 28, "bold"))
turtle.done()

Output:

Point! A 1 - B 0
Point! A 1 - B 1
Point! A 2 - B 1
Point! A 2 - B 2
Point! A 3 - B 2
Turtle graphics window of a Python Pong game with two white paddles, a ball, the score at the top and a winner message
The game window at the end of a match. Close it, or let turtle.done() keep it open until you do.

The console also prints each point as it happens, which I find handy for debugging the scoring.

How the Pong game works

  • screen.tracer(0) turns off automatic redraws, and screen.update() draws each frame once. Without this, the ball flickers and crawls.
  • Paddles are square turtles stretched to five times their height with shapesize().
  • The ball moves by dx and dy each frame; flipping the sign of one reverses that direction.
  • onkeypress() and listen() connect keys to the paddle-moving functions.
  • time.sleep(1 / 120) caps the speed at about 120 frames per second.

The main loop is a while loop that ends when a player reaches the winning score; see infinite loops in Python for other ways to structure game loops.

Testing the Pong ball and paddle collisions

In my experience, bounce bugs are the most common Pong problem you’ll hit. Pull the checks into small functions and test them without opening a window:

def wall_bounce(y, dy, limit=290):
    return -dy if abs(y) > limit else dy

def paddle_hit(ball_x, ball_y, paddle_y, side):
    """side = 1 for the right paddle, -1 for the left one."""
    return 330 < ball_x * side < 350 and abs(ball_y - paddle_y) < 50

tests = [
    ("ball at top wall", wall_bounce(295, 3) == -3),
    ("ball mid-screen keeps going", wall_bounce(100, 3) == 3),
    ("right paddle hit", paddle_hit(340, 20, 0, 1)),
    ("right paddle miss (too high)", not paddle_hit(340, 80, 0, 1)),
    ("left paddle hit", paddle_hit(-345, -30, -10, -1)),
    ("ball near left paddle but past it", not paddle_hit(-360, 0, 0, -1)),
]
for name, ok in tests:
    print(f"{'PASS' if ok else 'FAIL'}  {name}")

Output:

PASS  ball at top wall
PASS  ball mid-screen keeps going
PASS  right paddle hit
PASS  right paddle miss (too high)
PASS  left paddle hit
PASS  ball near left paddle but past it
Command Prompt output of tests for a Python Pong game's wall bounce and paddle collision functions, all passing
Six quick checks cover wall bounces, hits, near misses and a ball that’s already past the paddle.

You’ll notice the paddle check only fires in a thin strip in front of the paddle. That stops the ball from “sticking” and bouncing back and forth inside it.

How do you add a computer player to Pong?

Move the computer’s paddle toward the ball each frame, but cap its speed so it can miss. That cap is your difficulty setting:

def ai_paddle(paddle_y, ball_y, speed=6):
    """Move the computer paddle toward the ball, but no faster than `speed` per frame."""
    gap = ball_y - paddle_y
    return paddle_y + max(-speed, min(speed, gap))

paddle_y = 0
for frame, ball_y in enumerate([0, 30, 60, 90, 120, 120, 120, 100], start=1):
    paddle_y = ai_paddle(paddle_y, ball_y)
    print(f"frame {frame}: ball y {ball_y:>4} | paddle y {paddle_y:>4}")

Output:

frame 1: ball y    0 | paddle y    0
frame 2: ball y   30 | paddle y    6
frame 3: ball y   60 | paddle y   12
frame 4: ball y   90 | paddle y   18
frame 5: ball y  120 | paddle y   24
frame 6: ball y  120 | paddle y   30
frame 7: ball y  120 | paddle y   36
frame 8: ball y  100 | paddle y   42
Command Prompt output of a simple Python Pong computer paddle following the ball with a maximum speed per frame
The paddle closes the gap 6 pixels per frame, so a fast ball can still beat it.

To use it, you’d replace Player B’s key bindings with right.sety(ai_paddle(right.ycor(), ball.ycor())) inside the main loop.

Ideas to improve your Pong game

  • Speed the ball up a little after every paddle hit.
  • Add sound with winsound.Beep() on Windows.
  • Change the bounce angle based on where the ball hits the paddle.
  • Rebuild it in Pygame for sprites, sound and a steadier frame rate.

If you liked this, try these other Python game projects:

Frequently asked questions

How do I make a Pong game in Python?

Use the turtle module: create paddle and ball turtles, bind keys with onkeypress(), and move the ball in a loop that checks for bounces and scores.

Do I need Pygame for Pong?

No. The built-in turtle module is enough for a simple version. Pygame is better if you want sound, sprites and smoother timing.

Why is my turtle Pong game slow or flickering?

Call screen.tracer(0) once and screen.update() every frame.

Why don’t my paddle keys work?

You need screen.listen(), and the game window must have focus. Click it once if needed.

How do I make the ball faster over time?

Multiply ball.dx and ball.dy by something like 1.05 after each paddle hit.

Where is the turtle module documented?

See turtle in the Python docs.