Hey there, aspiring game developers and Python enthusiasts! Have you ever wanted to create your own game, even a super simple one? Today, we’re going to dive into the exciting world of game development by recreating a classic: Pong!
Pong is one of the very first video games ever made, and it’s surprisingly simple to build with Python. It’s a fantastic project for beginners because it covers many fundamental concepts of game programming like drawing shapes, handling user input, making things move, and detecting collisions.
We’ll be using Python’s built-in turtle module, which is perfect for drawing graphics and making simple animations. It’s like having a friendly robot artist at your command!
What You’ll Learn
By the end of this tutorial, you’ll have:
* A basic understanding of how games work.
* Experience with Python’s turtle module.
* Knowledge of how to handle user input for game controls.
* How to make objects move and bounce around.
* How to detect when two objects collide.
* The satisfaction of building your very own game!
Before We Start: What You Need
Don’t worry, you don’t need much!
- Python: Make sure you have Python installed on your computer (version 3.6 or newer is great). You can download it from python.org.
- A Text Editor: Any text editor will do, like VS Code, Sublime Text, or even Notepad++.
- Basic Python Knowledge: Knowing about variables, functions, and
whileloops will be helpful, but we’ll explain everything along the way!
That’s it! The turtle module comes pre-installed with Python, so no extra downloads are needed.
Step 1: Setting Up the Game Window
First, let’s create the screen where our game will be played.
import turtle
wn = turtle.Screen() # 'wn' is a common abbreviation for 'window'
wn.title("Pong by Your Name") # Set the title of the window
wn.bgcolor("black") # Set the background color to black
wn.setup(width=800, height=600) # Set the dimensions of the window (800 pixels wide, 600 pixels tall)
wn.tracer(0) # This stops the screen from updating automatically, which speeds up our game animation.
# We'll manually update it later inside our game loop.
Supplementary Explanation:
* import turtle: This line brings in the turtle module, making all its functions and classes available for us to use.
* turtle.Screen(): This creates a new window (the game screen) and assigns it to the variable wn.
* wn.tracer(0): This is a bit special. By default, turtle updates the screen every time something moves, which can make animations look choppy. Setting tracer(0) turns off these automatic updates. We’ll manually tell the screen to update only when we need it, making our game much smoother!
Step 2: Creating the Paddles and Ball
Now, let’s create the objects for our game: two paddles and a ball. We’ll use the turtle module’s “turtle” object for this. Think of a turtle object as a pen that can draw shapes and move around the screen.
paddle_a = turtle.Turtle() # Create a turtle object
paddle_a.speed(0) # Set the animation speed to the maximum possible (0 is fastest).
# This isn't the paddle's movement speed, but how fast it draws itself.
paddle_a.shape("square") # Give the paddle a square shape
paddle_a.color("white") # Set its color to white
paddle_a.shapesize(stretch_wid=5, stretch_len=1) # Stretch the square to be a rectangle.
# It will be 5 times wider (vertically) and 1 time longer (horizontally) than its default size.
paddle_a.penup() # Lift the pen up so it doesn't draw a line when it moves.
paddle_a.goto(-350, 0) # Move the paddle to its starting position (left side, center).
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.penup()
paddle_b.goto(350, 0) # Move to the right side, center.
ball = turtle.Turtle()
ball.speed(0)
ball.shape("circle") # Give the ball a circular shape
ball.color("white")
ball.penup()
ball.goto(0, 0) # Start the ball in the center of the screen.
ball.dx = 2 # 'dx' stands for 'delta x', how much the ball moves in the x-direction each frame.
# 2 means it moves 2 pixels to the right.
ball.dy = 2 # 'dy' stands for 'delta y', how much the ball moves in the y-direction each frame.
# 2 means it moves 2 pixels upwards.
Supplementary Explanations:
* turtle.Turtle(): This creates an actual “turtle” object that we can command.
* speed(0): This makes the turtle draw itself as fast as possible. It doesn’t affect the game’s movement speed.
* shape("square"), shape("circle"): These change the visual form of our turtle object.
* shapesize(stretch_wid=5, stretch_len=1): This customizes the size of our shape. For a square that’s 20×20 pixels by default, stretch_wid=5 makes it 5 times taller (100 pixels), and stretch_len=1 keeps its width the same (20 pixels), effectively making it a tall rectangle.
* penup(): When a turtle moves, it normally draws a line. penup() lifts its “pen” so it moves without drawing. We only want to see the shape itself.
* goto(x, y): This moves the turtle object to a specific coordinate on the screen. The center of the screen is (0, 0). Positive x is right, negative x is left. Positive y is up, negative y is down.
* ball.dx, ball.dy: These are custom attributes we’re adding to our ball object to control its movement speed and direction. dx for horizontal (x-axis) movement, dy for vertical (y-axis) movement.
Step 3: Moving the Paddles
We need functions to tell our paddles to move up and down based on key presses.
def paddle_a_up():
y = paddle_a.ycor() # Get the current y-coordinate of paddle A.
y += 20 # Add 20 pixels to the current y-coordinate.
paddle_a.sety(y) # Set paddle A's new y-coordinate.
def paddle_a_down():
y = paddle_a.ycor()
y -= 20 # Subtract 20 pixels to move down.
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
Supplementary Explanations:
* paddle_a.ycor(): This function returns the current vertical (y) coordinate of paddle_a.
* paddle_a.sety(y): This function sets the vertical (y) coordinate of paddle_a to the new value y.
Step 4: Keyboard Bindings
Now, we need to tell our game to listen for key presses and call the appropriate functions.
wn.listen() # Tell the window to listen for keyboard input.
wn.onkey(paddle_a_up, "w") # When the 'w' key is pressed, call the paddle_a_up function.
wn.onkey(paddle_a_down, "s") # When the 's' key is pressed, call the paddle_a_down function.
wn.onkey(paddle_b_up, "Up") # When the 'Up' arrow key is pressed, call paddle_b_up.
wn.onkey(paddle_b_down, "Down") # When the 'Down' arrow key is pressed, call paddle_b_down.
Supplementary Explanations:
* wn.listen(): This command tells the game window to start listening for keyboard input. Without this, pressing keys won’t do anything.
* wn.onkey(function_name, "key_name"): This is how we bind a key to a function. When the specified key_name is pressed, the function_name will be executed. Note that for arrow keys, you use “Up”, “Down”, “Left”, “Right”.
Step 5: The Main Game Loop (Making Things Move!)
This is the heart of our game. Everything that happens continuously (like ball movement, score updates, collision checks) will go inside an infinite while True loop.
score_a = 0
score_b = 0
pen = turtle.Turtle() # Create another turtle for writing text
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle() # We don't want to see the turtle itself, just the text it writes.
pen.goto(0, 260) # Position the scoreboard near the top center of the screen.
pen.write("Player A: 0 Player B: 0", align="center", font=("Courier", 24, "normal"))
while True:
wn.update() # Manually update the screen here (because we set wn.tracer(0) earlier).
# This shows all the changes that happened since the last update.
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking for the ball
# Top border
if ball.ycor() > 290: # If the ball hits the top edge (screen height is 600, so half is 300. Ball is 20px, so 290)
ball.sety(290) # Set its position exactly at the edge
ball.dy *= -1 # Reverse its vertical direction (bounce down)
# Bottom border
if ball.ycor() < -290: # If the ball hits the bottom edge
ball.sety(-290)
ball.dy *= -1 # Reverse its vertical direction (bounce up)
# Right border (Player A scores)
if ball.xcor() > 390: # If the ball goes past the right edge
ball.goto(0, 0) # Reset ball to the center
ball.dx *= -1 # Reverse direction so it goes towards player A
score_a += 1 # Increment Player A's score
pen.clear() # Clear the old score
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=("Courier", 24, "normal"))
# Left border (Player B scores)
if ball.xcor() < -390: # If the ball goes past the left edge
ball.goto(0, 0) # Reset ball to the center
ball.dx *= -1 # Reverse direction so it goes towards player B
score_b += 1 # Increment Player B's score
pen.clear() # Clear the old score
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=("Courier", 24, "normal"))
# Paddle and ball collisions
# Right paddle collision
# Check if ball is close to the right paddle AND within its vertical range
if (ball.xcor() > 340 and ball.xcor() < 350) and \
(ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50):
ball.setx(340) # Push the ball back to avoid getting stuck
ball.dx *= -1 # Reverse horizontal direction
# Left paddle collision
# Check if ball is close to the left paddle AND within its vertical range
if (ball.xcor() < -340 and ball.xcor() > -350) and \
(ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50):
ball.setx(-340) # Push the ball back
ball.dx *= -1 # Reverse horizontal direction
Supplementary Explanations:
* while True:: This creates an infinite loop. The code inside this loop will run over and over again until you manually close the window or stop the program.
* wn.update(): This is crucial! Because we used wn.tracer(0), we need to call wn.update() inside our loop to show any changes we’ve made to the objects on the screen.
* ball.xcor(): Returns the ball’s current horizontal (x) coordinate.
* ball.setx(value): Sets the ball’s horizontal (x) coordinate.
* ball.dx *= -1: This is a shorthand for ball.dx = ball.dx * -1. It effectively flips the sign of ball.dx, making the ball move in the opposite horizontal direction.
* pen.clear(): Erases the previous text written by the pen turtle.
* pen.write(...): Writes new text on the screen.
* align="center": Centers the text.
* font=("Courier", 24, "normal"): Sets the font family, size, and style.
* Collision Logic: This part might look a bit complex, but it’s just checking conditions:
1. Is the ball horizontally (x-coordinate) within the paddle’s area? (e.g., ball.xcor() > 340 and ball.xcor() < 350)
2. Is the ball vertically (y-coordinate) within the paddle’s area? (e.g., ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50)
If both are true, it means the ball hit the paddle! We then reverse its horizontal direction. The +50 and -50 come from the paddle being 100 pixels tall (5 * 20 pixels default square size).
Full Code Together
Here’s the complete code for your simple Pong game:
import turtle
wn = turtle.Screen()
wn.title("Pong by Your Name")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.penup()
paddle_a.goto(-350, 0)
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.penup()
paddle_b.goto(350, 0)
ball = turtle.Turtle()
ball.speed(0)
ball.shape("circle")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 2 # Ball movement speed in x-direction
ball.dy = 2 # Ball movement speed in y-direction
score_a = 0
score_b = 0
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: 0 Player B: 0", align="center", font=("Courier", 24, "normal"))
def paddle_a_up():
y = paddle_a.ycor()
if y < 250: # Don't let paddle go off-screen (top boundary)
y += 20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
if y > -240: # Don't let paddle go off-screen (bottom boundary)
y -= 20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
if y < 250:
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
if y > -240:
y -= 20
paddle_b.sety(y)
wn.listen()
wn.onkey(paddle_a_up, "w")
wn.onkey(paddle_a_down, "s")
wn.onkey(paddle_b_up, "Up")
wn.onkey(paddle_b_down, "Down")
while True:
wn.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking for the ball
# Top border
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
# Bottom border
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
# Right border (Player A scores)
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1 # Reverse direction
score_a += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=("Courier", 24, "normal"))
# Left border (Player B scores)
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1 # Reverse direction
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=("Courier", 24, "normal"))
# Paddle and ball collisions
# Right paddle collision
if (ball.xcor() > 340 and ball.xcor() < 350) and \
(ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50):
ball.setx(340)
ball.dx *= -1
# Left paddle collision
if (ball.xcor() < -340 and ball.xcor() > -350) and \
(ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50):
ball.setx(-340)
ball.dx *= -1
Conclusion
Congratulations! You’ve just created a functional Pong game using Python and the turtle module. You’ve learned about setting up a game window, drawing shapes, handling user input, animating objects, detecting collisions, and keeping score.
This is just the beginning! Here are a few ideas to expand your game:
* Increase Difficulty: Make the ball speed up after each paddle hit.
* Sounds: Add sound effects when the ball hits a paddle or a wall.
* Start Screen: Create a simple start screen before the game begins.
* AI Opponent: Replace one of the player paddles with a simple AI that tries to follow the ball.
Have fun experimenting and making your game even better!
Leave a Reply
You must be logged in to post a comment.