Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
91: Building a Pong Game with Turtle
When you first start building a game in Turtle, your instinct is probably to just tell the turtle to move, and let the library handle the drawing. For a simple drawing program, that's perfect. But for a game like Pong, where you have a ball bouncing and two paddles sliding, the default behavior of Turtle is actually your biggest enemy.
The Stuttering Screen Problem
If you write your movement logic by simply calling paddle.sety(paddle.ycor() + 20) inside a loop, you'll notice something frustrating: the screen flickers. Or worse, the ball seems to "crawl" across the screen because Turtle is trying to animate every single single-pixel movement in real-time. I've seen a lot of beginners try to fix this by adding time.sleep() calls, thinking they can just slow the game down to match the animation. All that does is make the game feel unresponsive; your input lag will skyrocket, and the game will feel like it's running through molasses.
# The "naive" way that leads to flickering
while game_is_on:
ball.goto(ball.xcor() + ball.x_move, ball.ycor() + ball.y_move)
# The screen updates automatically here, causing a stutter
The problem is that Turtle's default setting is to update the screen every time a turtle moves. In Pong, you have three different objects moving simultaneously. If the screen refreshes three times per frame, you get that jarring strobe effect.
Manual Control with Tracer and Update
To get a smooth, professional feel, you have to take the steering wheel away from Turtle. We do this using screen.tracer(0). This essentially tells Python, "Stop drawing everything immediately. Just keep track of where the objects are in the background, and don't show me anything until I specifically ask for it."
Once you've turned off the automatic animation, your screen will go completely blank when you run the code. That's where the screen.update() method comes in. By placing this call at the very end of your while loop, you're telling Python to render the final positions of the ball and both paddles all at once. It's the difference between watching someone draw a picture line-by-line and just seeing the finished frame appear instantly.
# The professional way to handle game frames
screen.tracer(0) # Turn off animation
while game_is_on:
screen.update() # Refresh the screen once per loop
ball.goto(ball.xcor() + ball.x_move, ball.ycor() + ball.y_move)
# Update paddles and check collisions here...
There is a trade-off here: you are now responsible for the "frame rate" of your game. Since the loop is running as fast as your CPU allows, the ball might fly across the screen in a millisecond. You'll likely want to introduce a small, controlled delay using time.sleep(), but now it serves a purpose—controlling the game speed—rather than trying to mask the library's animation lag.
Handling Input Without Freezing
Another trap you might fall into is using input() or blocking functions to move your paddles. If the code is waiting for a user to press a key, the ball stops moving. That's not a game; that's a turn-based slideshow. To solve this, we use screen.listen() combined with screen.onkeypress(). This sets up "event listeners" that run in the background. When you hit the 'W' key, it triggers a specific function to move the paddle, but it doesn't stop the while loop from continuing to bounce the ball. It's a simple implementation of asynchronous behavior that makes the game feel fluid.
📋 Practical Task
Exercise: Implementing the Ball-Paddle Collision Logic
You have the game loop running and the paddles moving, but the ball currently flies right through the paddles as if they weren't there. Your task is to implement the collision detection logic.
Using the ball and paddle objects, write a conditional statement inside the game loop that checks if the ball's x-coordinate is within a few pixels of the paddle's x-coordinate, and if the ball's y-coordinate is within the vertical range of the paddle. When a collision is detected, you must reverse the ball's x_move value to make it bounce back in the opposite direction.
Requirements:
- The ball must bounce off both the left and right paddles.
- Ensure the ball doesn't get "stuck" inside the paddle by making sure the bounce logic only triggers when the ball is moving toward the paddle.
- Test that the ball continues to move smoothly after the collision without causing the screen to flicker.
There are no comments for now.