Python基础篇(十五)-- Pygame游戏编程
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 pygamepygame.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 pygamepygame.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 pygamepygame.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 pygamepygame.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 pygamepygame.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 randomclass Bird(object):"""定义一个鸟类"""def __init__(self):"""定义初始化方法"""passdef bird_update(self):passclass Pipeline(object):"""定义一个管道类"""def __init__(self):"""定义初始化方法"""passdef update_pipeline(self):"""管道水平移动"""passdef create_map():"""定义创建地图的方法"""screen.fill((255, 255, 255)) # 填充颜色screen.blit(back_ground, (0, 0)) # 填入到背景pygame.display.update() # 更新显示if __name__ == '__main__':"""主程序"""pygame.init() # 初始化pygamesize = width, height = 288, 512screen = 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 randomclass 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):"""定义初始化方法"""passdef update_pipeline(self):"""管道水平移动"""passdef 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() # 初始化pygamesize = width, height = 288, 512screen = 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_speed
和 gravity
两个属性逐渐变化。运行上述代码,在窗体内创建一只小鸟,默认情况小鸟会一直下降。当单击一下鼠标或按一下键盘,小鸟会跳跃一下,高度上升。
4.5 创建管道类
创建完鸟类后,接下来创建管道类。同样,在 __init__
方法中初始化各种参数,包括设置管道的坐标,加载上下管道图片等。然后在 update_pipeline()
方法中,定义管道向左移动的速度,并且当管道移出屏幕时,重新绘制下一组管道。最后,在 create_map()
函数中显示管道。关键代码如下:
import sys
import pygame
import randomclass 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 scorescore += 1self.wall_x = 288def 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 randomclass Bird(object):"""定义一个鸟类"""# 代码和前面一致,此处省略class Pipeline(object):"""定义一个管道类"""# 代码和前面一致,此处省略def update_pipeline(self):"""管道水平移动"""self.wall_x -= 5 # 管道X轴坐标递减,即管道向左移动# 当管道运行到一定位置,即小鸟飞跃管道,分数加1,并且重置管道if self.wall_x < -80:global scorescore += 1self.wall_x = 288def create_map():"""定义创建地图的方法"""# 代码和前面一致,此处省略# 显示分数screen.blit(font.render('Score:'+str(score), -1, (255, 255, 255)), (100, 50)) # 设置颜色及坐标位置pygame.display.update() # 更新显示if __name__ == '__main__':"""主程序"""pygame.init() # 初始化pygamepygame.font.init() # 初始化字体font = pygame.font.SysFont(None, 50) # 设置默认字体和大小size = width, height = 288, 512screen = pygame.display.set_mode(size)clock = pygame.time.Clock()Pipeline = Pipeline() # 实例化管道类Bird = Bird() # 实例化鸟类score = 0while True:# 代码和前面一致,此处省略
4.7 碰撞检测
当小鸟与管道相撞时,小鸟颜色变为灰色,游戏结束,并且显示总分数。在 check_dead()
函数中通过 pygame.Rect()
可以分别获取小鸟的矩形区域对象和管道的矩形区域对象,该对象有一个 collidcrect()
方法可以判断两个矩形区域是否相撞。如果相撞,设置 Bird.dead
属性为 True。此外,当小鸟飞出窗体时,也设置 Bird.dead
属性为True。最后,用两行文字显示游戏得分。关键代码如下:
import sys
import pygame
import randomclass 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 = Truereturn Trueelse:return Falsedef 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 randomclass 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 scorescore += 1self.wall_x = 288def 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 = Truereturn Trueelse:return Falsedef 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() # 初始化pygamepygame.font.init() # 初始化字体font = pygame.font.SysFont(None, 50) # 设置默认字体和大小size = width, height = 288, 512screen = pygame.display.set_mode(size)clock = pygame.time.Clock()Pipeline = Pipeline() # 实例化管道类Bird = Bird() # 实例化鸟类score = 0while 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
相关文章:
Python基础篇(十五)-- Pygame游戏编程
1 初识Pygame Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上,SDL是一套跨平台的多媒体开发库,用C语言实…...
LeetCode 热题 HOT 100 Java 题解 -- Part 2
练习地址 Part 1 : https://blog.csdn.net/qq_41080854/article/details/128829494 LeetCode 热题 HOT 100 Java 题解 -- Part 236. 二叉树的中序遍历 9437. 不同的二叉搜索树 9638. 验证二叉搜索树 9839. 对称二叉树 10140. 二叉树的层序遍历 10241. 二叉树的最大深度 10442.…...
【项目实战】IDEA常用快捷键汇总
一、修改为Eclipse的快捷键 相信很多朋友跟我一样, 都是习惯了eclipse的快捷键,没错,习惯这东西真的很难改!IDEA非常强大,支持我们修改IDEA中的keymap为Eclipse的快捷键!友好又贴心,有没有&…...
更新 TKK 失败,请检查网络连接。谷歌翻译 translation插件不能用解决办法 亲测有效
谷歌翻译无法使用,谷歌回应解释是,谷歌翻译使用率过低,所以选择停止服务。网上也有说法,指出根本原因为,提供API接口的googleapis被墙,这导致js文件和字体资源无法加载。 这里提供两种解决办法 方案一 修…...
SpringBoot整合MybatisPlus多数据源
相信在很多使用MybatisPlus框架的小伙伴都会遇到多数据源的配置问题,并且官网也给出了推荐使用多数据源 (dynamic-datasource-spring-boot-starter) 组件来实现。由于最近项目也在使用这个组件来实现多数据源切换,因此想了解一下该组件是如何运行的&…...
【教程】如何使用Java生成PDF文档?
在如今数字化时代,越来越多的人使用PDF文档进行信息传递和共享。而使用Java生成PDF文档也成为了一个非常重要的技能,因为Java作为一种通用的编程语言,可以在不同的操作系统和平台上运行。下面,我们将为您介绍如何使用Java生成PDF文…...
I.MX6ULL内核开发13:pinctrl子系统和gpio子系统-led实验
目录 一、pinctrl子系统 1.1 pinctrl子系统编写格式以及引脚属性介绍 1.1.1 iomux节点介绍 1.1.2 pinctrl子节点编写格式 1.1.3 引脚配置信息介绍 1.2 将RGB灯引脚添加到pinctrl子系统 1.2.1 查找RGB灯使用的引脚 1.2.2找到引脚宏定义 1.2.3 设置引脚属性 1.2.4 在…...
Linux系列 使用vi文本编辑器
作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页 目录 前言 一.vi文本编辑器 1.使用vi文本编辑器 2.vi编辑器的工作模式 3.命令模式中的…...
【java基础】接口(interface)
文章目录基础介绍接口的定义关于接口字段和方法的说明使用接口抽象类和接口接口方法冲突的一些说明方法相同名称和参数,返回值相同方法名称相同,参数不同,返回值相同方法返回值不同,名称参数相同方法完全相同,一个有默…...
ChatGPT(GPT3.5) OpenAI官方API正式发布
OpenAI社区今天凌晨4点多发送的邮件,介绍了ChatGPT官方API的发布。官方介绍文档地址为“OpenAI API”和“OpenAI API”。 ChatGPT(GPT3.5)官方API模型名称为“gpt-3.5-turbo”和“gpt-3.5-turbo-0301”。API调用价格比GPT text-davinci-003模型便宜10倍。调用费用为…...
CAD中如何将图形对象转换为三维实体?
有些小伙伴在CAD绘制完图纸后,想要将图纸中的某些图形对象转换成三维实体,但却不知道该如何操作,其实很简单,本节CAD绘图教程就和小编一起来了解一下浩辰CAD软件中将符合条件的对象转换为三维实体的相关操作步骤吧! 将…...
【K8S笔记】Kubernetes 集群架构与组件介绍
K8S 官方文档 https://kubernetes.io/zh/docs/home ##注重关注 概念和任务 板块。 K8S 集群架构 K8S也是运用了分布式集群架构: 管理节点/Master 整个集群的管理,任务协作。工作节点/Node 容器运行、删除。 K8S 组件介绍 管理节点/Master 相关组件 …...
9 怎么登录VNC
1)首先在ssh登录后启动vncserver。登陆后输入下面的指令来创建自己的VNC。 命令vncserver :16 –geometry 1900x1000 其中:16是分配的端口号,1900x1000是分辨率。如果没有响应,建议执行下面操作后再次重复上面操作。 命令…...
MPI ubuntu安装,mpicc,mpicxx,mpif90的区别
介绍 MPI是并行计算的一个支持库,支持对C、C、fortran语言进行并行计算。 安装基础环境 ubuntu进行gcc/g/gfortran的安装: gcc: ubuntu下自带gcc编译器。可以通过gcc -v命令来查看是否安装。 g: sudo apt-get install buil…...
移动端笔记
目录 一、移动端基础 二、视口 三、二倍图/多倍图 四、移动端开发 (一)开发选择 (二)常见布局 (三)移动端技术解决方案 五、移动WEB开发之flex布局 六、移动WEB开发之rem适配布局 #END(…...
操作系统笔记、面试八股(一)—— 进程、线程、协程
文章目录1. 进程、线程、协程1.1 进程1.1.1 进程间的通信方式1.1.2 进程同步方式1.1.3 进程的调度算法1.1.4 优先级反转1.1.5 进程状态1.1.6 PCB进程控制块1.1.7 进程的创建和撤销过程1.1.8 为什么要有进程1.2 线程1.2.1 为什么要有线程1.2.2 线程间的同步方式1.3 协程1.3.1 什…...
Python每日一练(20230302)
目录 1. 字符串统计 2. 合并两个有序链表 3. 下一个排列 附录 Python字典内置方法 增 删 改 查 其它 1. 字符串统计 从键盘输入一个包含有英文字母、数字、空格和其它字符的字符串,并分别实现下面的功能:统计字符串中出现2次的英文字母&#…...
Numpy课后练习
Numpy课后练习 文章目录 Numpy课后练习一、前言二、题目及答案一、前言 答案仅供参考,谢谢大家! 二、题目及答案 导入Numpy包并设置随机数种子为666 import numpy as np np.random.seed(666)创建并输出一个包含12个元素的随机整数数组r1,元素的取值范围在[30,100)之间 r1 …...
动态规划dp中的子序列、子数组问题总结
目录 定义dp数组 初始化dp数组 状态转移方程 最终结果 题目 定义dp数组 这类问题的共性是会提供两个数组,寻找他们共同的子序列、子数组。设第一个数组为s,第二个数组为t。则可以设二维dp数组,其大小为len(s + 1)*len(t + 1) dp[i][j]表示 s 前 i 个长度,...
Zookeeper3.5.7版本——Zookeeper的概述、工作机制、特点、数据结构及应用场景
目录一、Zookeeper的概述二、Zookeeper的工作机制三、Zookeeper的特点四、Zookeeper的数据结构五、Zookeeper的应用场景5.1、统一命名服务5.2、统一配置管理5.3、统一集群管理5.4、服务器动态上下线5.5、软负载均衡一、Zookeeper的概述 Zookeeper 是一个开源的分布式的&#x…...
安卓逆向学习及APK抓包(二)--Google Pixel一代手机的ROOT刷入面具
注意:本文仅作参考勿跟操作,root需谨慎,本次测试用的N手Pixel,因参考本文将真机刷成板砖造成的损失与本人无关 1 Google Pixel介绍 1.1手机 google Pixel 在手机选择上,优先选择谷歌系列手机,Nexus和Pixel系列&…...
线程池的基本认识与使用
线程池的基本认识与使用线程池线程池工作原理:优点:传统的创建线程方式线程池创建线程使用线程池 池化思想:线程池、字符串常量池、数据库连接池可以提高资源的利用率 线程池工作原理: 预先创建多个线程对象 放入线程池种&#…...
小家电品牌私域增长解决方案来了
小家电品牌的私域优势 01、行业线上化发展程度高 相对于大家电动辄上千上万元的价格,小家电的客单价较低。而且与大家电偏刚需属性不同的是,小家电的消费需求侧重场景化,用户希望通过购买小家电来提高自身的生活品质。这就决定了用户的决策…...
什么是让ChatGPT爆火的大语言模型(LLM)
什么是让ChatGPT爆火的大语言模型(LLM) 更多精彩内容: https://www.nvidia.cn/gtc-global/?ncidref-dev-876561 文章目录什么是让ChatGPT爆火的大语言模型(LLM)大型语言模型有什么用?大型语言模型如何工作?大型语言模型的热门应用在哪里可以找到大型语言…...
【监控】Linux部署postgres_exporter及PG配置(非Docker)
目录一、下载及部署二、postgres_exporter配置1. 停止脚本stop.sh2. 启动脚本start.sh3. queries.yaml三、PostgreSQL数据库配置1. 修改postgresql.conf配置文件2. 创建用户、表、扩展等四、参考一、下载及部署 下载地址 选一个amd64下载 上传至服务器,解压 tax…...
基于Java+SpringBoot+Vue+Uniapp(有教程)前后端分离健身预约系统设计与实现
博主介绍:✌全网粉丝3W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战✌ 博主作品:《微服务实战》专栏是本人的实战经验总结,《Spring家族及…...
【2023】DevOps、SRE、运维开发面试宝典之Redis相关面试题
文章目录 1、redis主从复制原理2、redis哨兵模式的原理3、reids集群原理4、Redis 哈希表进行的触发时机是什么?5、Redis 的 RDB 和 AOF 机制各自的优缺点是什么?这两种机制是否可以混合使用?6、Redis 经常被称为单线程的系统,你如何理解 Redis 的单线程模型7、redis 的事务…...
十五、MyBatis使用PageHelper
1.limit分页 limit分页原理 mysql的limit后面两个数字: 第一个数字:startIndex(起始下标。下标从0开始。) 第二个数字:pageSize(每页显示的记录条数) 假设已知页码pageNum,还有每页…...
【MySQL】B+ 树索引
一、索引是什么 ? 为什么需要索引 ? 索引就是目录,目录就是索引。 索引从 InnoDB 存储引擎数据存储结构上来看,就是为各个页建立的目录。保证我们在查询时,可以通过二分法快速定位到页,再在页内通过二分法…...
Android Gradle Plugin Version 和 Gradle Version 的对应关系
官网参考 以下是插件版本和Gradle 版本对应关系: 插件版本所需的最低 Gradle 版本Android Gradle Plugin VersionGradle Version1.0.0 - 1.1.32.2.1 - 2.31.2.0 - 1.3.12.2.1 - 2.91.5.02.2.1 - 2.132.0.0 - 2.1.22.10 - 2.132.1.3 - 2.2.32.14.1 - 3.52.3.03.33.0…...
临沂网站建设制作/网络营销推广方案策划书
[20191227]别把数据库当作垃圾场.txt--//最近一直在我一个项目的优化工作,看到开发写的模式有时候真心无语!!xxxxx> select count(*) from BBB_QQQQ_FFFFF_TTTTTT;COUNT(*)----------1xxxxx> select count(*) from BBB_QQQQ_FFFFF_TTTTTT;COUNT(*)----------0--//可以发现…...
网站策划书格式/全网品牌推广
Elasticsearch.安装(单节点) 环境Linux 7.x jdk 1.8 elasticsearch 5.x 环境目录结构(根目录多了两个文件夹): /resources /** 存放下载的文件 **/ /u01/app /** 安装elasticsearch的目录. **/ 在linux的终端执行指令: …...
青海省住房和建设厅网站首页/市场调研与分析
https://mp.weixin.qq.com https://mp.weixin.qq.com/s?__bizMzI3NzE0NjcwMg...
在那些网站可以接兼职做/seo排名关键词点击
background: linear-gradient(to bottom, #000000 0%,#ffffff 100%);(标准)linear-gradient 在 ie9 以下是不支持的,所以对于 ie6 - ie8 我们可以使用滤镜来解决。如下代码:filter: progid:DXImageTransform.Microsoft.gradient(s…...
软件开发包含网站开发/网站域名费一年多少钱
SPI全名Service Provider Interface(服务提供者接口),SPI的主要目的是实现服务的热插拔效果,主要应对的场景是设计者提供一个接口,这个接口的具体实现由不同厂商提供,设计者只要引入厂商提供的实现jar包就可…...
建筑工程网签合同周末可以签吗/seo是什么
本文已迁移至:https://blog.csdn.net/COCO56/article/details/89382093 原标题:VS各版本下载与密钥(从2008到2017),VS老版本在官网如何下载(解决下载老版本时提示抱歉,我们找不到适合您的下载内容的问题&a…...