


Creating interactive games with Python 3 and Pygame: Part 4
Overview
This is the fourth in a five-part tutorial series on making games with Python 3 and Pygame. In Part Three, we delved into the core of Breakout, learned how to handle events, looked at the main Breakout classes, and saw how to move different game objects.
In this part, we'll learn how to detect collisions and what happens when the ball hits various objects such as paddles, bricks, walls, ceilings, and floors. Finally, we'll review important topics of game UI, specifically how to create menus with our own custom buttons.
Impact checking
In the game, things collide with each other. Breakthrough is no exception. Most of the time it's the ball hitting something. The handle_ball_collisions()
method has a nested function called intersect()
that tests whether the ball hits an object and where it hits the object. If the ball misses an object, returns "Left", "Right", "Up", "Down", or "None".
def handle_ball_collisions(self): def intersect(obj, ball): edges = dict( left=Rect(obj.left, obj.top, 1, obj.height), right=Rect(obj.right, obj.top, 1, obj.height), top=Rect(obj.left, obj.top, obj.width, 1), bottom=Rect(obj.left, obj.bottom, obj.width, 1)) collisions = set(edge for edge, rect in edges.items() if ball.bounds.colliderect(rect)) if not collisions: return None if len(collisions) == 1: return list(collisions)[0] if 'top' in collisions: if ball.centery >= obj.top: return 'top' if ball.centerx < obj.left: return 'left' else: return 'right' if 'bottom' in collisions: if ball.centery >= obj.bottom: return 'bottom' if ball.centerx < obj.left: return 'left' else: return 'right'
hit the ball with a racket
When the ball hits the racket, it bounces away. If it hits the top of the paddle, it will bounce back but maintain the same horizontal velocity component.
However, if it hits one side of the paddle, it will bounce to the other side (left or right) and continue its downward motion until it hits the floor. This code uses the intersect function().
# Hit paddle s = self.ball.speed edge = intersect(self.paddle, self.ball) if edge is not None: self.sound_effects['paddle_hit'].play() if edge == 'top': speed_x = s[0] speed_y = -s[1] if self.paddle.moving_left: speed_x -= 1 elif self.paddle.moving_left: speed_x += 1 self.ball.speed = speed_x, speed_y elif edge in ('left', 'right'): self.ball.speed = (-s[0], s[1])
Landing
When the racket misses the ball on its way down (or the ball hits the side of the racket), the ball will continue to fall and eventually hit the floor. At this point, the player loses a life and the ball is recreated so the game can continue. The game ends when the player runs out of lives.
# Hit floor if self.ball.top > c.screen_height: self.lives -= 1 if self.lives == 0: self.game_over = True else: self.create_ball()
Hit the ceiling and walls
When the ball hits a wall or ceiling, it just bounces back.
# Hit ceiling if self.ball.top < 0: self.ball.speed = (s[0], -s[1]) # Hit wall if self.ball.left < 0 or self.ball.right > c.screen_width: self.ball.speed = (-s[0], s[1])
Brick Break
When the ball hits a brick, this is a major event in Breakout - the brick disappears, the player gets a point, the ball bounces back, and a few other things happen (sound effects, and possibly special effects ), which I will discuss later.
To determine if a brick was hit, the code checks to see if any bricks intersect the ball:
# Hit brick for brick in self.bricks: edge = intersect(brick, self.ball) if not edge: continue self.bricks.remove(brick) self.objects.remove(brick) self.score += self.points_per_brick if edge in ('top', 'bottom'): self.ball.speed = (s[0], -s[1]) else: self.ball.speed = (-s[0], s[1])
Programming the Game Menu
Most games have some kind of user interface. Breakout has a simple menu with two buttons, "PLAY" and "QUIT." This menu appears when the game starts and disappears when the player clicks "Start". Let's see how buttons and menus are implemented and how they integrate with the game.
Create button
Pygame does not have a built-in UI library. There are third party extensions, but I decided to build my own button for the menu. Buttons are game objects with three states: normal, hover, and pressed. The normal state is when the mouse is not over the button, and the hover state is when the mouse is over the button but the left mouse button is not pressed. The pressed state is when the mouse is over the button and the player presses the left mouse button.
The button is implemented as a rectangle with a background color and text displayed on it. The button also receives an on_click function (defaults to a noop lambda function), which is called when the button is clicked.
import pygame from game_object import GameObject from text_object import TextObject import config as c class Button(GameObject): def __init__(self, x, y, w, h, text, on_click=lambda x: None, padding=0): super().__init__(x, y, w, h) self.state = 'normal' self.on_click = on_click self.text = TextObject(x + padding, y + padding, lambda: text, c.button_text_color, c.font_name, c.font_size) def draw(self, surface): pygame.draw.rect(surface, self.back_color, self.bounds) self.text.draw(surface)
Buttons handle their own mouse events and change their internal state based on those events. When the button is pressed, the MOUSEBUTTONUP
event is received, indicating that the player clicked the button, and the on_click()
function is called.
def handle_mouse_event(self, type, pos): if type == pygame.MOUSEMOTION: self.handle_mouse_move(pos) elif type == pygame.MOUSEBUTTONDOWN: self.handle_mouse_down(pos) elif type == pygame.MOUSEBUTTONUP: self.handle_mouse_up(pos) def handle_mouse_move(self, pos): if self.bounds.collidepoint(pos): if self.state != 'pressed': self.state = 'hover' else: self.state = 'normal' def handle_mouse_down(self, pos): if self.bounds.collidepoint(pos): self.state = 'pressed' def handle_mouse_up(self, pos): if self.state == 'pressed': self.on_click(self) self.state = 'hover'
The back_color
property used to draw the background rectangle always returns a color that matches the button's current state, so the player can clearly see that the button is active:
@property def back_color(self): return dict(normal=c.button_normal_back_color, hover=c.button_hover_back_color, pressed=c.button_pressed_back_color)[self.state]
Create Menu
create_menu()
Function creates a menu with two buttons containing the text "PLAY" and "QUIT". It has two nested functions named on_play()
and on_quit()
which are fed to the corresponding buttons. Each button is added to the objects
list (to be drawn) and the menu_buttons
field.
def create_menu(self): for i, (text, handler) in enumerate((('PLAY', on_play), ('QUIT', on_quit))): b = Button(c.menu_offset_x, c.menu_offset_y + (c.menu_button_h + 5) * i, c.menu_button_w, c.menu_button_h, text, handler, padding=5) self.objects.append(b) self.menu_buttons.append(b) self.mouse_handlers.append(b.handle_mouse_event)
When the PLAY button is clicked, on_play() is called, which removes the button from the objects
list so that they are no longer drawn. Additionally, the boolean fields is_game_running
and start_level
that trigger the start of the game are set to True.
When the exit button is clicked, is_game_running
is set to False
(effectively pausing the game) and game_over
is set to True, triggering the final game sequence.
def on_play(button): for b in self.menu_buttons: self.objects.remove(b) self.is_game_running = True self.start_level = True def on_quit(button): self.game_over = True self.is_game_running = False
Show and hide game menu
Showing and hiding menus is implicit. When the buttons are in the objects
list, the menu is visible; when they are removed, it is hidden. It's that easy.
It's possible to create a nested menu with its own surface that renders subcomponents like buttons and then just add/remove that menu component, but this simple menu doesn't need it.
in conclusion
In this part, we cover collision detection and what happens when the ball hits various objects such as paddles, bricks, walls, ceilings, and floors. Additionally, we created our own menu with custom buttons that hide and show based on commands.
In this final part of the series, we'll look at the final game, paying close attention to scores and lives, sound effects, and music.
We will then develop a complex special effects system to add interest to the game. Finally, we discuss future directions and potential improvements.
The above is the detailed content of Creating interactive games with Python 3 and Pygame: Part 4. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Solution to permission issues when viewing Python version in Linux terminal When you try to view Python version in Linux terminal, enter python...

When using Python's pandas library, how to copy whole columns between two DataFrames with different structures is a common problem. Suppose we have two Dats...

How to teach computer novice programming basics within 10 hours? If you only have 10 hours to teach computer novice some programming knowledge, what would you choose to teach...

How to avoid being detected when using FiddlerEverywhere for man-in-the-middle readings When you use FiddlerEverywhere...

Regular expressions are powerful tools for pattern matching and text manipulation in programming, enhancing efficiency in text processing across various applications.

How does Uvicorn continuously listen for HTTP requests? Uvicorn is a lightweight web server based on ASGI. One of its core functions is to listen for HTTP requests and proceed...

The article discusses popular Python libraries like NumPy, Pandas, Matplotlib, Scikit-learn, TensorFlow, Django, Flask, and Requests, detailing their uses in scientific computing, data analysis, visualization, machine learning, web development, and H

In Python, how to dynamically create an object through a string and call its methods? This is a common programming requirement, especially if it needs to be configured or run...
