Python Basics (15) -- Pygame game programming

1 Getting to know Pygame for the first time

        Pygame is an open source Python module dedicated to the development of multimedia applications (such as video games), which includes support for images, sounds, videos, events, collisions, etc. Pygame is built on the basis of SDL, which is a set of cross-platform multimedia development library, implemented in C language, and widely used in the development of games, simulators, players, etc. And Pygame makes game developers no longer bound by the underlying language, and can pay more attention to the functions and logic of the game.

        For the detailed usage of this module, please refer to: Pygame Detailed Explanation

        This section is about learning Pygame in the process of writing a game. You will first learn the basics of Pygame through the "jumping ball" game, and then apply Pygame to implement the Flappy Bird game.


2 Basic use

2.1 Common modules of Pygame

        Many modules related to low-level development are integrated in Pygame, such as accessing display devices, managing events, using fonts, etc. The commonly used modules of Pygame are shown in the figure below.

        Next, use the display module and event module of pygame to create a Pygame window, the code is as follows:

import sys
import pygame

pygame.init()
size = width, height = 320, 240             # 设置窗口
screen = pygame.display.set_mode(size)      # 显示窗口

# 执行死循环,确保窗口一直显示
while True:
    for event in pygame.event.get():        # 遍历所有事件
        if event.type == pygame.QUIT:       # 如果单击关闭窗口,则退出
            sys.exit()

pygame.quit()       # 退出pygame

3 Game development

        Create a game window first, and then create a small ball inside the window. Move the ball at a certain speed. When the ball hits the edge of the game window, the ball bounces back and continues to move. Follow the steps below to realize this function:

        (1) Create a game window with width and height set to 640*480, and add a small ball in the window. We first prepare a ball.pngpicture , then load the picture, and finally display the picture in the window, the specific code is as follows:

import sys
import pygame

pygame.init()                               # 初始化 pygame
size = width, height = 640, 480             # 设置窗口
screen = pygame.display.set_mode(size)      # 显示窗口
color = (0, 0, 0)

ball = pygame.image.load('ball.png')        # 加载图片
ballrect = ball.get_rect()                  # 获取矩形区域

# 执行死循环,确保窗口一直显示
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:       # 如果单击关闭窗口,则退出
            sys.exit()

    screen.fill(color)                      # 填充颜色
    screen.blit(ball, ballrect)             # 将图片画到窗口上
    pygame.display.flip()                   # 更新全部显示

pygame.quit()                               # 退出pygame

        In the above code, first import the pygame module, and then call init()the method to initialize the pygame module. Next, set the width and height of the window, and finally use the display module to display the form. Common methods of the display module are shown in the table below.

        In the above code, in order to keep the window displayed, you need to use while Trueto keep the program running. Also set close button, add polling event detection. pygame.event.get()Can get the event queue, use for ... inthe traversal event, and then judge the event type according to the type attribute. event.typeThe equal here pygame.QUITmeans that the event of closing the pygame window is detected, pygame.KEYDOWNit means the event of pressing the keyboard, pgame.MOUSEBUTTONDOWNit means the event of pressing the mouse, etc.

        In the above code, load()the method to load the image, and the return value ball is a Surface object. Surface is a pygame object used to represent pictures, and various operations such as painting, deformation, and copying can be performed on a Surface object. In fact, the screen is just a surface, pygame.display.set_modeso a screen Surface object is returned. If you want to draw the Surface object of ball to the screen Surface object, you need to use blit()the method , and finally use flip()the method of the display module to update the entire Surface object to be displayed on the screen. Common methods of the Surface object are shown in the figure below.

        Results as shown below:

        (2) Now it's time to make the ball move. ball.get_rect()The method return value balrect is a Rect object, which has a move()method can be used to move the rectangle. move(x,y)The function has two parameters, the first parameter is the moving distance of the X axis, and the second parameter is the moving distance of the Y axis. The coordinates of the upper left corner of the form are (0,0). In order to realize the non-stop movement of the ball, add move()the function to the while loop. The specific code is as follows:

import sys
import pygame

pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
color = (0, 0, 0)

ball = pygame.image.load('ball.png')
ballrect = ball.get_rect()

speed = [5, 5]              # 设置移动的X轴、Y轴距离
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    ballrect = ballrect.move(speed)         # 移动小球
    screen.fill(color)
    screen.blit(ball, ballrect)
    pygame.display.flip()

pygame.quit()

        (3) Run the above code and find that the ball flashes across the screen. At this time, the ball does not really disappear, but moves out of the window. At this time, the function of collision detection needs to be added. When the ball collides with any edge of the form, the moving direction of the ball is changed. The specific code is as follows:

import sys
import pygame

pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
color = (0, 0, 0)

ball = pygame.image.load('ball.png')
ball_rect = ball.get_rect()

speed = [5, 5]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:       # 如果单击关闭窗口,则退出
            sys.exit()
        
    ball_rect = ball_rect.move(speed)         # 移动小球
    # 碰到左右边缘
    if ball_rect.left < 0 or ball_rect.right > width:
        speed[0] = -speed[0]
    # 碰到上下边缘
    if ball_rect.top < 0 or ball_rect.bottom > height:
        speed[1] = -speed[1]

    screen.fill(color)                  # 填充颜色
    screen.blit(ball, ball_rect)        # 将图片画到窗口上
    pygame.display.flip()               # 更新全部显示

pygame.quit()

        In the above code, the collision detection function is added. If it touches the left and right edges, change the X-axis data to a negative number, and if it touches the top and bottom edges, change the Y-axis data to a negative number. The running result is shown in the figure below.

        (4) After running the above code, it seems that there are many small balls moving fast. This is because the time for running the above code is very short, which leads to the illusion of visual observation. Therefore, it is necessary to add a "clock" to control the running time of the program. At this time, you need to use the time module of Pygame. Before using the Pygame clock, you must first create an instance of the Clock object, and then set how often to run it in the while loop. The specific code is as follows:

import sys
import pygame

pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
color = (0, 0, 0)

ball = pygame.image.load('ball.png')
ball_rect = ball.get_rect()

speed = [5, 5]
clock = pygame.time.Clock()     # 设置时钟 

while True:
    clock.tick(60)              # 每秒执行60次
    for event in pygame.event.get():
        if event.type == pygame.QUIT:       # 如果单击关闭窗口,则退出
            sys.exit()
        
    ball_rect = ball_rect.move(speed)         # 移动小球
    # 碰到左右边缘
    if ball_rect.left < 0 or ball_rect.right > width:
        speed[0] = -speed[0]
    # 碰到上下边缘
    if ball_rect.top < 0 or ball_rect.bottom > height:
        speed[1] = -speed[1]

    screen.fill(color)                  # 填充颜色
    screen.blit(ball, ball_rect)        # 将图片画到窗口上
    pygame.display.flip()               # 更新全部显示

pygame.quit()

        So far, we have completed the ball jumping game.


4 Developing the Flappy Bird game

4.1 Game Introduction

        Flappy Bird is a bird flying game developed by indie game developer Dong Nguyen in Hanoi, Vietnam. In the FlappyBird game, players only need to use one finger to control, click and touch the phone screen, and the bird will fly up. Click the screen continuously, and the bird will continue to fly high; relax your fingers, and it will quickly descend. Players need to control the bird to fly forward and pay attention to avoid the uneven pipes on the way. If the bird hits an obstacle, the game ends. Each time a bird flies through a set of pipes, the player gets 1 point.

4.2 Game Analysis

        In the Flappy Bird game, there are two main objects: the bird and the pipe. You can create a Bird class and a Pincline class to represent these two objects, respectively. The bird can avoid the pipe by moving up and down, so create a bird_update()method to realize the bird's up and down movement. In order to reflect the characteristics of the bird flying forward, the pipe can be moved all the way to the left, so that it looks like the bird is flying forward in the window. Therefore, a method is also created in the Pineline class update_pipeline()to move the pipeline to the left. In addition, three functions are created: create_map()the function is used to draw the map; check_dead()the function is used to judge the life state of the bird; get_result()the function is used to obtain the final score. Finally, in the main logic, instantiate the class and call related methods to realize the corresponding functions.

4.3 Build the main frame

        Through the previous analysis, we can build the main framework of the Flappy Bird game. The Flappy Bird game has two objects: the bird and the pipe. Let's create these two classes first, and the specific methods in the class can be replaced by the pass statement first. Then create a function that draws the map create_map(). Finally, draw the background image in the main logic. The key code is as follows:

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    def __init__(self):
        """定义初始化方法"""
        pass

    def bird_update(self):
        pass


class Pipeline(object):
    """定义一个管道类"""
    def __init__(self):
        """定义初始化方法"""
        pass


    def update_pipeline(self):
        """管道水平移动"""
        pass

def create_map():
    """定义创建地图的方法"""
    screen.fill((255, 255, 255))        # 填充颜色
    screen.blit(back_ground, (0, 0))    # 填入到背景
    pygame.display.update()             # 更新显示


if __name__ == '__main__':
    """主程序"""
    pygame.init()                           # 初始化pygame
    size = width, height = 288, 512
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()                   # 实例化管道类
    Bird = Bird()                           # 实例化鸟类
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            
        back_ground = pygame.image.load('assets/bg_day.png')    # 加载背景图片
        create_map()            # 绘制地图
    pygame.quit()               # 退出

4.4 Create a small bird

        Let's create the little bird. This class needs to initialize many parameters, so a __init__()method to initialize various parameters, including several states of bird flight, flight speed, jump height, etc. Then define bird_update()the method , which is used to implement the jumping and falling of the bird. Next, add a keyboard press event or a mouse click event in the polling event of the main logic, such as pressing the mouse, making the bird go up, and so on. Finally, in create_map()the method , an image of the bird is displayed. The key code is as follows:

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    def __init__(self):
        """定义初始化方法"""
        self.bird_rect = pygame.Rect(65, 50, 50, 50)        # 鸟的矩形
        # 定义鸟的3种状态列表
        self.bird_status = [pygame.image.load('assets/bird0_0.png'),
                            pygame.image.load('assets/bird0_1.png'),
                            pygame.image.load('assets/bird0_2.png')]
        self.status = 0         # 默认飞行状态
        self.bird_x = 150       # 鸟所在的X轴坐标
        self.bird_y = 350       # 鸟所在的Y轴坐标,即上下飞行高度
        self.jump = False       # 默认情况小鸟自动降落
        self.jump_speed = 10    # 跳跃高度
        self.gravity = 5        # 重力
        self.dead = False       # 默认小鸟生命状态为活着

    def bird_update(self):
        if self.jump:
            # 小鸟跳跃
            self.jump_speed -= 1                # 速度递减,上升越来越慢
            self.bird_y -= self.jump_speed      # 鸟的Y轴坐标减小,小鸟上升
        else:
            # 小鸟坠落
            self.gravity += 0.2                 # 重力递增,下降越来越快
            self.bird_y += self.gravity         # 鸟的Y轴坐标增加,小鸟下降
        self.bird_rect[1] = self.bird_y         # 更改Y轴坐标


class Pipeline(object):
    """定义一个管道类"""
    def __init__(self):
        """定义初始化方法"""
        pass

    def update_pipeline(self):
        """管道水平移动"""
        pass


def create_map():
    """定义创建地图的方法"""
    screen.fill((255, 255, 255))        # 填充颜色
    screen.blit(back_ground, (0, 0))    # 填入到背景

    # 显示小鸟
    if Bird.dead:
        Bird.status = 2                 # 撞管道状态
    elif Bird.jump:
        Bird.status = 1                 # 起飞状态
    screen.blit(Bird.bird_status[Bird.status], (Bird.bird_x, Bird.bird_y))  # 设置小鸟坐标
    Bird.bird_update()                  # 鸟移动
    pygame.display.update()             # 更新显示


if __name__ == '__main__':
    """主程序"""
    pygame.init()                           # 初始化pygame
    size = width, height = 288, 512
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()                   # 实例化管道类
    Bird = Bird()                           # 实例化鸟类
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True        # 跳跃
                Bird.gravity = 2        # 重力
                Bird.jump_speed = 10    # 跳跃速度
            
        back_ground = pygame.image.load('assets/bg_day.png')    # 加载背景图片
        create_map()            # 绘制地图
    pygame.quit()               # 退出

        The above code sets bird_statusthe attribute . This attribute is a list of bird pictures. The list shows three flight states of the birds, and the corresponding pictures are loaded according to the different states of the birds. In bird_update()the method , in order to achieve a better animation effect, jump_speedthe gravitytwo are gradually changed. Run the above code to create a bird in the form, and the bird will keep falling by default. When you click the mouse or press the keyboard, the bird will jump and rise in height.

4.5 Create pipeline class

        After creating the bird, the next step is to create the pipeline class. Similarly, various parameters are initialized in __init__the method , including setting the coordinates of the pipeline, loading pictures of the upper and lower pipelines, etc. Then in update_pipeline()the method , define how fast the pipes move to the left, and when the pipes move off screen, redraw the next set of pipes. Finally, the pipeline is displayed in create_map()the function . The key code is as follows:

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    # 代码和前面一致,此处省略


class Pipeline(object):
    """定义一个管道类"""
    def __init__(self):
        """定义初始化方法"""
        self.wall_x = 288               # 管道所在X轴坐标
        self.pipe_up = pygame.image.load('assets/pipe_up.png')          # 加载上管道图片
        self.pipe_down = pygame.image.load('assets/pipe_down.png')      # 加载下管道图片

    def update_pipeline(self):
        """管道水平移动"""
        self.wall_x -= 5        # 管道X轴坐标递减,即管道向左移动
        # 当管道运行到一定位置,即小鸟飞跃管道,分数加1,并且重置管道
        if self.wall_x < -80:
            global score
            score += 1
            self.wall_x = 288

def create_map():
    """定义创建地图的方法"""
    screen.fill((255, 255, 255))        # 填充颜色
    screen.blit(back_ground, (0, 0))    # 填入到背景

    # 显示管道
    screen.blit(Pipeline.pipe_up, (Pipeline.wall_x, -200))      # 上管道坐标位置
    screen.blit(Pipeline.pipe_down, (Pipeline.wall_x, 400))     # 下管道坐标位置
    Pipeline.update_pipeline()          # 管道移动

    # 显示小鸟
    if Bird.dead:
        Bird.status = 2                 # 撞管道状态
    elif Bird.jump:
        Bird.status = 1                 # 起飞状态
    screen.blit(Bird.bird_status[Bird.status], (Bird.bird_x, Bird.bird_y))  # 设置小鸟坐标
    Bird.bird_update()                  # 鸟移动

    # 显示分数
    screen.blit(font.render('Score:'+str(score), -1, (255, 255, 255)), (100, 50))   # 设置颜色及坐标位置
    pygame.display.update()             # 更新显示


if __name__ == '__main__':
    """主程序"""
    # 代码和前面一致,此处省略
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True        # 跳跃
                Bird.gravity = 2        # 重力
                Bird.jump_speed = 10    # 跳跃速度
            
        back_ground = pygame.image.load('assets/bg_day.png')    # 加载背景图片
        create_map()            # 绘制地图
    pygame.quit()               # 退出

        In the above code, in create_map()the function , it is set to display the pipe first, and then display the bird. The purpose of this is to display the image of the bird on the upper layer and the image of the pipe on the bottom layer when the bird and the pipe image overlap.

4.6 Calculating the score

        When the bird flies through the pipe, the player's score is increased by 1. Here, the logic of flying over the pipe is simplified: when the pipe moves to a certain distance to the left of the window, the bird flies over the pipe by default, adding 1 to the score and displaying it on the screen. This function has been implemented in update_pipeline()the method , the code is as follows:

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    # 代码和前面一致,此处省略


class Pipeline(object):
    """定义一个管道类"""
    # 代码和前面一致,此处省略


    def update_pipeline(self):
        """管道水平移动"""
        self.wall_x -= 5        # 管道X轴坐标递减,即管道向左移动
        # 当管道运行到一定位置,即小鸟飞跃管道,分数加1,并且重置管道
        if self.wall_x < -80:
            global score
            score += 1
            self.wall_x = 288

def create_map():
    """定义创建地图的方法"""
    # 代码和前面一致,此处省略

    # 显示分数
    screen.blit(font.render('Score:'+str(score), -1, (255, 255, 255)), (100, 50))   # 设置颜色及坐标位置
    pygame.display.update()             # 更新显示


if __name__ == '__main__':
    """主程序"""
    pygame.init()                           # 初始化pygame
    pygame.font.init()                      # 初始化字体
    font = pygame.font.SysFont(None, 50)    # 设置默认字体和大小
    size = width, height = 288, 512
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()                   # 实例化管道类
    Bird = Bird()                           # 实例化鸟类
    score = 0
    while True:
        # 代码和前面一致,此处省略

4.7 Collision detection

        When the bird collides with the pipe, the color of the bird turns gray, the game ends, and the total score is displayed. In check_dead()the function pygame.Rect(), the rectangular area object of the bird and the rectangular area object of the pipe can be respectively obtained through , and the object has a collidcrect()method to determine whether two rectangular areas collide. If collided, set Bird.deadthe property to True. Also, set Bird.deadthe property . Finally, display the game score with two lines of text. The key code is as follows:

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    # 代码和前面一致,此处省略

class Pipeline(object):
    """定义一个管道类"""
    # 代码和前面一致,此处省略

def create_map():
    """定义创建地图的方法"""
    # 代码和前面一致,此处省略

def check_dead():
    # 上方管子的矩形位置
    up_rect = pygame.Rect(Pipeline.wall_x, -200, 
                          Pipeline.pipe_up.get_width() - 10,
                          Pipeline.pipe_up.get_height())
    down_rect = pygame.Rect(Pipeline.wall_x, 400, 
                            Pipeline.pipe_down.get_width() - 10,
                            Pipeline.pipe_down.get_height())
    # 检测小鸟与上下方管道是否碰撞
    if up_rect.colliderect(Bird.bird_rect) or down_rect.colliderect(Bird.bird_rect):
        Bird.dead = True
    # 检测小鸟是否飞出上下边界
    if not 0 < Bird.bird_rect[1] < height:
        Bird.dead = True
        return True
    else:
        return False


def get_result1():
    final_text1 = "Game Over"
    final_text2 = "Your final score is: " + str(score)
    ft1_font = pygame.font.SysFont('Arial', 40)             # 设置第一行文字字体
    ft1_surf = ft1_font.render(final_text1, 1, (243, 3, 36))    # 设置第一行文字颜色
    ft2_font = pygame.font.SysFont('Arial', 30)
    ft2_surf = ft2_font.render(final_text2, 1, (253, 177, 6))
    # 设置第一行文字显示位置
    screen.blit(ft1_surf, [screen.get_width()/2-ft1_surf.get_width()/2, 100])
    screen.blit(ft2_surf, [screen.get_width()/2-ft2_surf.get_width()/2, 200])
    pygame.display.flip()       # 更新整个待显示的Surface对象到屏幕上


if __name__ == '__main__':
    """主程序"""
    # 代码和前面一致,此处省略
    while True:
         # 代码和前面一致,此处省略
            
        back_ground = pygame.image.load('assets/bg_day.png')    # 加载背景图片
        if check_dead():            # 检测小鸟生命状态
            get_result1()           # 如果小鸟死亡,显示游戏总分数        
        else:
            create_map()            # 绘制地图
    pygame.quit()               # 退出

check_dead()In the method        of the above code , up_rect.colliderect(Bird.bird_rect)it is used to detect whether the rectangular area of ​​the bird collides with the rectangular area of ​​the pipeline above, and colliderect()the parameter of the function is another rectangular area object. The running result is shown in the figure below.

        Here is just the basic function of Flappy Bird, and you can continue to improve the difficulty of setting the game, including setting the height of the pipe, the flight speed of the bird, etc. Interested friends can try further.

The complete code is as follows:

# -*- encoding: utf-8 -*-
# @Author: CarpeDiem
# @Date: 230210
# @Version: 1.0
# @Description: 移动小球

import sys
import pygame
import random

class Bird(object):
    """定义一个鸟类"""
    def __init__(self):
        """定义初始化方法"""
        self.bird_rect = pygame.Rect(65, 50, 50, 50)        # 鸟的矩形
        # 定义鸟的3种状态列表
        self.bird_status = [pygame.image.load('assets/bird0_0.png'),
                            pygame.image.load('assets/bird0_1.png'),
                            pygame.image.load('assets/bird0_2.png')]
        self.status = 0         # 默认飞行状态
        self.bird_x = 150       # 鸟所在的X轴坐标
        self.bird_y = 350       # 鸟所在的Y轴坐标,即上下飞行高度
        self.jump = False       # 默认情况小鸟自动降落
        self.jump_speed = 10    # 跳跃高度
        self.gravity = 5        # 重力
        self.dead = False       # 默认小鸟生命状态为活着


    def bird_update(self):
        if self.jump:
            # 小鸟跳跃
            self.jump_speed -= 1                # 速度递减,上升越来越慢
            self.bird_y -= self.jump_speed      # 鸟的Y轴坐标减小,小鸟上升
        else:
            # 小鸟坠落
            self.gravity += 0.2                 # 重力递增,下降越来越快
            self.bird_y += self.gravity         # 鸟的Y轴坐标增加,小鸟下降
        self.bird_rect[1] = self.bird_y         # 更改Y轴坐标



class Pipeline(object):
    """定义一个管道类"""
    def __init__(self):
        """定义初始化方法"""
        self.wall_x = 288               # 管道所在X轴坐标
        self.pipe_up = pygame.image.load('assets/pipe_up.png')          # 加载上管道图片
        self.pipe_down = pygame.image.load('assets/pipe_down.png')      # 加载下管道图片


    def update_pipeline(self):
        """管道水平移动"""
        self.wall_x -= 5        # 管道X轴坐标递减,即管道向左移动
        # 当管道运行到一定位置,即小鸟飞跃管道,分数加1,并且重置管道
        if self.wall_x < -80:
            global score
            score += 1
            self.wall_x = 288

def create_map():
    """定义创建地图的方法"""
    screen.fill((255, 255, 255))        # 填充颜色
    screen.blit(back_ground, (0, 0))    # 填入到背景

    # 显示管道
    screen.blit(Pipeline.pipe_up, (Pipeline.wall_x, -200))      # 上管道坐标位置
    screen.blit(Pipeline.pipe_down, (Pipeline.wall_x, 400))     # 下管道坐标位置
    Pipeline.update_pipeline()          # 管道移动

    # 显示小鸟
    if Bird.dead:
        Bird.status = 2                 # 撞管道状态
    elif Bird.jump:
        Bird.status = 1                 # 起飞状态
    screen.blit(Bird.bird_status[Bird.status], (Bird.bird_x, Bird.bird_y))  # 设置小鸟坐标
    Bird.bird_update()                  # 鸟移动

    # 显示分数
    screen.blit(font.render('Score:'+str(score), -1, (255, 255, 255)), (100, 50))   # 设置颜色及坐标位置
    pygame.display.update()             # 更新显示

def check_dead():
    # 上方管子的矩形位置
    up_rect = pygame.Rect(Pipeline.wall_x, -200, 
                          Pipeline.pipe_up.get_width() - 10,
                          Pipeline.pipe_up.get_height())
    down_rect = pygame.Rect(Pipeline.wall_x, 400, 
                            Pipeline.pipe_down.get_width() - 10,
                            Pipeline.pipe_down.get_height())
    # 检测小鸟与上下方管道是否碰撞
    if up_rect.colliderect(Bird.bird_rect) or down_rect.colliderect(Bird.bird_rect):
        Bird.dead = True
    # 检测小鸟是否飞出上下边界
    if not 0 < Bird.bird_rect[1] < height:
        Bird.dead = True
        return True
    else:
        return False


def get_result1():
    final_text1 = "Game Over"
    final_text2 = "Your final score is: " + str(score)
    ft1_font = pygame.font.SysFont('Arial', 40)             # 设置第一行文字字体
    ft1_surf = ft1_font.render(final_text1, 1, (243, 3, 36))    # 设置第一行文字颜色
    ft2_font = pygame.font.SysFont('Arial', 30)
    ft2_surf = ft2_font.render(final_text2, 1, (253, 177, 6))
    # 设置第一行文字显示位置
    screen.blit(ft1_surf, [screen.get_width()/2-ft1_surf.get_width()/2, 100])
    screen.blit(ft2_surf, [screen.get_width()/2-ft2_surf.get_width()/2, 200])
    pygame.display.flip()       # 更新整个待显示的Surface对象到屏幕上


if __name__ == '__main__':
    """主程序"""
    pygame.init()                           # 初始化pygame
    pygame.font.init()                      # 初始化字体
    font = pygame.font.SysFont(None, 50)    # 设置默认字体和大小
    size = width, height = 288, 512
    screen = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    Pipeline = Pipeline()                   # 实例化管道类
    Bird = Bird()                           # 实例化鸟类
    score = 0
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
                Bird.jump = True        # 跳跃
                Bird.gravity = 2        # 重力
                Bird.jump_speed = 10    # 跳跃速度
            
        back_ground = pygame.image.load('assets/bg_day.png')    # 加载背景图片
        if check_dead():            # 检测小鸟生命状态
            get_result1()           # 如果小鸟死亡,显示游戏总分数        
        else:
            create_map()            # 绘制地图
    pygame.quit()               # 退出

reference

Guess you like

Origin blog.csdn.net/xq151750111/article/details/129285654