Python基础篇(十五)-- Pygame游戏编程

news2024/11/15 20:04:19

1 初识Pygame

        Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上,SDL是一套跨平台的多媒体开发库,用C语言实现,被广泛的应用于游戏、模拟器、播放器等的开发。而Pygame让游戏开发者不再被底层语言束缚,可以更多的关注游戏的功能和逻辑。

        对于该模块的详细用法,可以参考:Pygame详解

        本节是在编写游戏的过程中学习Pygame。会先通过“跳跃的小球”的游戏学习 Pygame 基础知识,然后应用 Pygame 实现 Flappy Bird 游戏。


2 基本使用

2.1 Pygame常用模块

        Pygame中集成了很多和底层开发相关的模块,如访问显示设备、管理事件、使用字体等。Pygame常用模块如下图所示。

        下面,使用pygame的 display模块和 event 模块创建一个 Pygame 窗口,代码如下:

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 游戏开发

        先创建一个游戏窗口,然后在窗口内创建一个小球。以一定的速度移动小球,当小球碰到游戏窗口的边缘时,小球弹回,继续移动。按照如下步骤实现该功能:

        (1) 创建一个游戏窗口,宽和高设置为 640*480,并在窗口中添加小球。我们先准备好一张 ball.png 图片,然后加载该图片,最后将图片显示在窗口中,具体代码如下:

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

        上述代码中,首先导入pygame模块,然后调用 init() 方法初始化 pygame 模块。接下来,设置窗口的宽和高,最后使用 display 模块显示窗体。display模块的常用方法如下表所示。

        上述代码中,为了让窗口一直显示,需要使用 while True 让程序一直执行。同时设置关闭按钮,添加了轮询事件检测。pygame.event.get() 能够获取事件队列,使用for ... in遍历事件,然后根据type属性判断事件类型。这里的 event.type 等于 pygame.QUIT 表示检测到关闭 pygame 窗口事件,pygame.KEYDOWN 表示键盘按下事件,pgame.MOUSEBUTTONDOWN 表示鼠标按下事件等。

        上述代码中使用 image 模块的 load() 方法加载图片,返回值 ball 是一个 Surface 对象。Surface 是用来代表图片的 pygame 对象,可以对一个 Surface 对象进行涂画、变形、复制等各种操作。事实上,屏幕也只是一个 surface,pygame.display.set_mode就返回了一个屏幕 Surface 对象。如果将 ball 这个 Surface 对象画到 screen Surface 对象,需要使用 blit()方法,最后使用 display 模块的 flip() 方法更新整个待显示的 Surface 对象到屏幕上。Surface 对象的常用方法如下图所示。

        效果如下图所示:

        (2) 下面该让小球动起来了。ball.get_rect() 方法返回值balrect 是一个 Rect 对象,该对象有一个 move() 方法可以用于移动矩形。move(x,y) 函数有两个参数,第一个参数是 X 轴移动的距离,第二个参数是 Y 轴移动的距离。窗体左上角坐标为(0,0),为实现小球不停地移动,将 move() 函数添加到 while循环内,具体代码如下:

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) 运行上述代码,发现小球在屏幕中一闪而过,此时,小球并没有真正消失,而是移动到窗体之外,此时需要添加碰撞检测的功能。当小球与窗体任一边缘发生碰撞,则更改小球的移动方向。具体代码如下:

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()

        上述代码中,添加了碰撞检测功能。如果碰到左右边缘,更改 X 轴数据为负数,如果碰到上下边缘,更改 Y 轴数据为负数。运行结果如下图所示。

        (4) 运行上述代码发现好像有多个小球在飞快移动,这是因为运行上述代码的时间非常短,导致肉眼观察出现错觉,因此需要添加一个“时钟”来控制程序运行的时间。这时就需要使用 Pygame 的time 模块。使用 Pygame 时钟之前,必须先创建 Clock 对象的一个实例,然后在 while循环中设置多长时间运行一次。具体代码如下:

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()

        至此,我们完成了小球的跳跃游戏。


4 开发 Flappy Bird 游戏

4.1 游戏简介

        Flappy Bird 是一款鸟类飞行游戏,由越南河内独立游戏开发者阮哈东(Dong Nguyen)开发。在FlappyBird 这款游戏中,玩家只需要用一根手指来操控,单击触摸手机屏幕,小鸟就会往上飞。不断地单击屏幕,小鸟就会不断地往高处飞;放松手指,则会快速下降。玩家要控制小鸟一直向前飞行,并且注意躲避途中高低不平的管子。如果小鸟碰到了障碍物,游戏就会结束。每当小鸟飞过一组管道,玩家就会获得1分。

4.2 游戏分析

        在 Flappy Bird 游戏中,主要有两个对象:小鸟和管道。可以创建 Bird 类和 Pincline 类来分别表示这两个对象。小鸟可以通过上下移动来躲避管道,所以在 Bird 类中创建一个 bird_update()方法,实现小鸟的上下移动。为了体现小鸟向前飞行的特征,可以让管道一直向左侧移动,这样在窗口中就好像小鸟在向前飞行。所以,在 Pineline 类中也创建一个update_pipeline() 方法,实现管道的向左移动。此外,还创建了3个函数: create_map()函数用于绘制地图; check_dead()函数用于判断小鸟的生命状;get_result() 函数用于获攻最终分数。最后在主逻辑中,实例化类并调用相关方法,实现相应功能。

4.3 搭建主框架

        通过前面的分析,我们可以搭建起 Flappy Bird 游戏的主框架。Flappy Bird 游戏有两个对象:小鸟和管道。先来创建这两个类,类中具体的方法可以先使用pass语句代替。然后创建一个绘制地图的函数 create_map()。最后,在主逻辑中绘制背景图片。关键代码如下:

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 创建小鸟类

        下面来创建小鸟类。该类需要初始化很多参数,所以定义一个 __init__() 方法,用来初始化各种参数,包括鸟飞行的几种状态、飞行的速度、跳跃的高度等。然后定义 bird_update() 方法,该方法用于实现小鸟的跳跃和坠落。接下来,在主逻辑的轮询事件中添加键盘按下事件或鼠标单击事件,如按下鼠标,使小鸟上升等。最后,在 create_map() 方法中,显示小鸟的图像。关键代码如下:

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()               # 退出

        上述代码在 Bird 类中设置了 bird_status 属性,该属性是一个鸟类图片的列表,列表中显示鸟类3种飞行状态,根据小鸟的不同状态加载相应的图片。在 bird_update() 方法中,为了达到较好的动画效果,使 jump_speedgravity 两个属性逐渐变化。运行上述代码,在窗体内创建一只小鸟,默认情况小鸟会一直下降。当单击一下鼠标或按一下键盘,小鸟会跳跃一下,高度上升。

4.5 创建管道类

        创建完鸟类后,接下来创建管道类。同样,在 __init__ 方法中初始化各种参数,包括设置管道的坐标,加载上下管道图片等。然后在 update_pipeline() 方法中,定义管道向左移动的速度,并且当管道移出屏幕时,重新绘制下一组管道。最后,在 create_map() 函数中显示管道。关键代码如下:

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()               # 退出

        上述代码中,在 create_map() 函数内,设置先显示管道,再显示小鸟。这样傲的目的是为了当小鸟与管道图像重合时,小鸟的图像显示在上层,而管道的图像显示在底层。

4.6 计算得分

        当小鸟飞过管道时,玩家得分加1。这里对于飞过管道的逻辑做了简化处理:当管道移动到窗体左侧一定距离后,默认为小鸟飞过管道,使分数加1,并显示在屏幕上。在 update_pipeline() 方法中已实现该功能,代码如下:

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 碰撞检测

        当小鸟与管道相撞时,小鸟颜色变为灰色,游戏结束,并且显示总分数。在 check_dead() 函数中通过 pygame.Rect() 可以分别获取小鸟的矩形区域对象和管道的矩形区域对象,该对象有一个 collidcrect() 方法可以判断两个矩形区域是否相撞。如果相撞,设置 Bird.dead 属性为 True。此外,当小鸟飞出窗体时,也设置 Bird.dead 属性为True。最后,用两行文字显示游戏得分。关键代码如下:

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() 方法中,up_rect.colliderect(Bird.bird_rect) 用于检测小鸟的矩形区域是否与上面的管道的矩形区域相撞, colliderect()函数的参数是另一个矩形区域对象。运行结果如下图所示。

        这里只是实现了 Flappy Bird 的基本功能,还可以继续完善设置游戏的难度,包括设置管道的高度、小鸟的飞行速度等,感兴趣的朋友可以进一步尝试。

完整代码如下:

# -*- 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()               # 退出

参考

  • Pygame教程:http://c.biancheng.net/pygame/
  • PYGAME主页:https://www.osgeo.cn/pygame/
  • Pygame详解:https://blog.csdn.net/qq_41556318/category_9283450.html
  • PyGame模块的所有功能函数详解:https://blog.51cto.com/u_15274949/2922576

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/381629.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

39万字完整版智能矿山项目建设整体解决方案

本资料来源网络&#xff0c;仅做知识分享&#xff0c;请勿商用。完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 1.1 总体技术要求 1.1.1 核心业务架构 智能矿山业务架构是在统一的标准与规范及安全运维保障体系下&#xff0c;按分层设计模式&#xff0c;分为设备层、…

QML鼠标事件

QML中常用的事件有&#xff1a; 鼠标事件键盘事件拖拽事件定时器MouseArea&#xff08;鼠标区域&#xff09; MouseArea是一个不可见的项目&#xff0c;同、通常用来和一个可见的项目配合使用来为其提供鼠标处理。鼠标处理的逻辑可以包含在MouseArea项目中 常用的属性&#xff…

【设计模式】原型模式与建造者模式

原型模式 原型模式是指通过原型实例指定创建对象的种类&#xff0c;然后通过拷贝的方式创建新的对象。属于创建型模式 原型模式的核心在于拷贝原型对象&#xff0c;主要用于对对象的复制。当你需要通过一大段get/set方法去构建对象的时候&#xff0c;就可以考虑使用原型模式了…

手牵手教Docker部署Springboot+vue ,全过程十分详细,轻松完成项目部署(简单,高效,通用)

手把手教Docker部署Springbootvue &#xff0c;详细全过程&#xff0c;轻松完成项目部署&#xff08;简单&#xff0c;高效&#xff09; 上线前准备 腾讯云的服务器&#xff0c;服务器安装好docker 和docker-compose 最好事先了解技术 nginxdocker-compose 整体编排 后端部…

【C++】Visual Studio C++ 配置并使用gtest(不好用你捶我)

文章目录 相信大家都能感受到Visual Studio C 编辑器链接 lib 或 dll文件是一件非常头疼的事情。配置gooleTest的过程也不例外。 市面上很多教程&#xff0c;要么就不全&#xff0c;要么就缺少一些细节&#xff0c;导致我自己再配置的过程中&#xff0c;踩了很多坑。今天就记录…

用不同的思路实现括号匹配(java)

给定一个只包括 (&#xff0c;) 的字符串&#xff0c;判断字符串是否有效。 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 以上就是题目要求 利用替换的思想 ()()()()()()()(())例如需要判断例子中的括号是否有效&#xff0c;用替换的思想具体就是 将字…

力扣sql简单篇练习(二十一)

力扣sql简单篇练习(二十一) 1 使用唯一标识符替换员工ID 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # Write your MySQL query statement below SELECT e2.unique_id,e1.name FROM Employees e1 LEFT JOIN EmployeeUNI e2 ON e1.ide2.id1.3 运行…

使用netlify实现自动化部署前端项目(无服务器版本)

介绍 本文以 github仓库进行介绍关联netlify的无服务前端自动化部署。用途&#xff1a;个人网站设计、小游戏等当然这只是让你入门~具体细节等待你自己去探索 实现 打开官方网站 如果没有注册过的账户&#xff0c;你需要使用 github 去进行登录。注册完成后会自动给你提示填…

有关Windows域信任关系的一系列知识

简单的总结了一下来自这篇文章的知识点 https://www.kroll.com/-/media/kroll/pdfs/publications/rootedcon2019-pentesting-active-directory-forests-carlos-garcia.pdf 视频录像为 https://www.youtube.com/watch?v6aV5tZlQ2EQ&t10s&themeRefresh1 森林 域是由树和…

项目管理的工作内容有哪些?

首先&#xff0c;什么是项目管理&#xff1f; 项目管理是为了交付项目成果&#xff0c;包括“规划&#xff08;尤其关注估算&#xff09;——实施——确保成功”。项目管理可以用在所有事情上&#xff0c;当然&#xff0c;这个定义听起来可能还不够清晰&#xff0c;但它的好处…

华为机试题:HJ91 走方格的方案数(python)

文章目录&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;Python3实现&#xff08;3&#xff09;知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…

剑指offer06.从尾到头打印链表

题目描述 解题思路 遍历链表&#xff0c;依次将元素压入栈中。然后依次弹出栈顶元素&#xff0c;存入数组返回。程序 class Solution { public:vector<int> reversePrint(ListNode* head) {ListNode *phead;stack<int> s1;while(p!NULL) //遍历链表&#xff0c;元…

jetson-Linux上 python 部署yolov5报错总结

第一个问题&#xff1a;python报错 illegal instruction报错先上图这报错&#xff0c;emmmmm&#xff0c;我是小白&#xff0c;多谢大佬的笔记&#xff0c;帮我解决了&#xff0c;虽然我也没搞懂。。。。嘿嘿具体解决办法就是&#xff1a;临时运行代码&#xff1a;1-在运文件前…

优雅停止 SpringBoot 服务,拒绝 kill -9 暴力停止

在使用 SpringBoot 的时候&#xff0c;都要涉及到服务的停止和启动&#xff0c;当我们停止服务的时候&#xff0c;很多时候大家都是kill -9 直接把程序进程杀掉&#xff0c;这样程序不会执行优雅的关闭。而且一些没有执行完的程序就会直接退出。 我们很多时候都需要安全的将服…

SAP 采购定价过程字段解析

下面我们针对每一个字段进行解释和用途分析 &#xff1a; 1、 步骤&#xff1a;代表了创建PO时&#xff0c;哪个条件类型放到前面&#xff0c;哪个放到后面&#xff0c;如果步骤号相同&#xff0c;那就以谁先选择出来谁就在前面。 2、 计数&#xff1a;没有任何实际意义&a…

web,h5海康视频接入监控视频流记录二(后台node取流)

首先将自己的appkey,secret以及对应参数填上&#xff0c;看看是否能够取流成功。 ws取流是需要开通559端口的&#xff0c;可以联系海康技术开放&#xff0c;以及mgc需要升级版本。 普通模式的话 需要升级mgc到5.13.102版本&#xff0c;可以找下现场技术帮你升级&#xff0c;先…

Java | IO 模式之 JavaBIO 应用

文章目录IO模型Java BIOJava NIOJava AIO&#xff08;NIO.2&#xff09;BIO、NIO、AIO的使用场景BIO1 BIO 基本介绍2 BIO 的工作机制3 BIO 传统通信实现3.1 业务需求3.2 实现思路3.3 代码实现4 BIO 模式下的多发和多收消息4.1 业务需求4.2 实现思路4.3 代码实现5 BIO 模式下接收…

大V龚文祥造谣董明珠恋情被禁言

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 因造谣董明珠与王自如恋情&#xff0c;知名大V龚文祥老师被今日头条禁言。龚文祥说&#xff0c;69岁的董明珠&#xff0c;找了一个小自己34岁的男友&#xff0c;引的网友议论纷纷。 2月26日&#…

使用Python和OpenCV制作电影般的截屏相册!

目录 简介&#xff1a; 实现步骤&#xff1a; 代码说明&#xff1a; 报错error&#xff1a; 问题所在&#xff1a; 解决方法&#xff1a; 1&#xff09;卸载&#xff1a; 2&#xff09;重新安装&#xff1a; 3&#xff09;安装成功&#xff1a; 效果如下&#xff1a; 简…

DockQuery 天狼 v1.2.0 正式发布

DockQuery 天狼经过 2022 年的孵化&#xff0c;于 2022 年年底发布了第一个版本。 在春回大地万象更新之际&#xff0c;DockQuery 发布了 1.2.0 版本&#xff0c;也是我们公开招募第一批产品体验官的版本。 在这个版本中&#xff0c;DockQuery 主要专注以下几个主题&#xff…