目录
- 一、初始化pygame环境
- (一)在pycharm中新建一个工程
- (二)安装pygame
- (三)测试安装是否成功
- 二、pygame基础
- (一)pygame初始化
- (二)设置显示界面
- (三)定义事件循环
- (四)事件实例
一、初始化pygame环境
(一)在pycharm中新建一个工程
(二)安装pygame
(三)测试安装是否成功
在pycharm终端中输入
python -m pygame --version
在pycharm运行演示程序。
在pycharm终端中输入:python -m pygame.examples.aliens
二、pygame基础
(一)pygame初始化
导入pygame
import pygame # 导入pygame
pygame初始化
pygame.init()
将pygame.init()赋值给一个变量,并打印它。
n = pygame.init()
print(n)
n返回一个元组,(5,0)中的5个模块初始化成功,0个模块初始化失败
(二)设置显示界面
pygame绘图思路
1.设置窗口尺寸
我们使用pygame.display.set_mode(size,flags,depth)来初始化窗口并将其传递给变量,将获得一个surface对象。size是一对元组,用以表示宽度和高度。
screen = pygame.display.set_mode((400,400)) # 第一个400是宽度,单位是像素,第二个400是高度
flags用于设置主窗口样式
pygame.FULLSCREEN 创建一个全屏窗口。
pygame.HWSURFACE 创建一个硬件加速窗口,必须和 FULLSCREEN 同时使用。
pygame.OPENGL 创建一个 OPENGL 渲染窗口。
pygame.RESIZABLE 创建一个可以改变大小的窗口。
pygame.DOUBLEBUF 创建一个双缓冲区窗口,建议在 HWSURFACE 或者 OPENGL 时使用。
pygame.NOFRAME 创建一个没有边框的窗口。
2.设置窗口标题
设置窗口的标题,即游戏名称
pygame.display.set_caption('hello world')
3.更新画面
我们可以将显示界面理解为电影中的画面。在电影中随着时间的推进,画面会不断发生变化。为了将每一幅图像显示到画面上,需要不断的更新页面上显示的内容。
更新屏幕方法一
pygame.display.flip()
pygame.display.flip()的作用是更新整个屏幕的内容。
Update the full display Surface to the screen
在完成以上代码,点击运行会有一闪而过的画面,原因是没有设置任何动作。
下面,我们通过定义事件循环及动作捕获。
完整代码:
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption('hello world')
while True:
for event in pygame.event.get():
pass
pygame.display.flip()
更新屏幕方法二:
pygame.display.update()
与flip()的区别是可以通过传递rect值指定更新的区域,如果不传递参数其效果和flip()一样。
如果仅仅是几个物体在移动,那么他只重绘其中移动的部分,没有变化的部分,并不进行重绘。update比flip速度更快。因此在一般的游戏中,如果不是场景变化非常频繁的时候,我们建议使用update函数,而不是flip函数。
4.设置背景
现在的窗口默认使用的是黑色背景,我们可以通过以下两种方式来设置背景样式。
(1)为画面添加一个纯色背景
# 设置背景
screen.fill((255,209,220))
# 或者
screen.fill('pink')
(2)设置图片背景
background = pygame.image.load('./image/plane/background.png').convert_alpha()
screen.blit(background, (0, 0))
blit(source, dest, area=None, special_flags = 0) -> Rect
Surface对象的blit方法,是将一个surface对象绘制在另一个surface对象的上面,就想油画一样,上面的颜色将把下面的颜色盖住。
source为放在上层的Surface对象;
dest是放置的坐标元组(left,top);如果left和top都为0,则图片的左上角点与背景的左上角点重合;
area:是一个可选参数,通过该参数可设置矩形区域。若设置的矩形区域小于source所设置Surface对象的区域,那么仅绘制Surface对象的部分内容。
5.添加文字
pygame.font.SysFont()。使用系统字体。
name字体名称,size字体大小,bold是否加粗,italic是否斜体
create a Font object from the system fonts
SysFont(name, size, bold=False, italic=False) -> Font
系统可用字体使用以下语句查询,将获得所有可用字体的列表。
print(pygame.font.get_fonts())
使用下面语句将获得一个字体对象
# 设置字体样式
scores_font = pygame.font.SysFont('仿宋gb_2312', 25)
在pygame中使用render方法将文本变成一个贴图,然后再将图片贴到背景上显示。
draw text on a new Surface
render(text, antialias, color, background=None) -> Surface
text是需要插入的字符串;
antialias设置抗锯齿;
值为True或False;
color是文字的颜色;
background是背景的颜色,默认为无背景。
#
scores_caption = scores_font.render(f'得分{score}', True, (255, 255, 255), (0, 0, 0))
使用和之前贴背景图片一样的方法blit,将文字surface贴上去。
screen.blit(scores_capiton,(100,100))
(三)定义事件循环
前面为了让游戏窗口正常显示,我们定义一个while循环。
while True:
# 循环获取事件,监听事件状态
for event in pygame.event.get():
pass
pygame.display.update()
pygame.event.get()函数用于捕获用户使用键盘、鼠标设备的任何操作。
在for循环中只有一个pass语句,没有设置任何实际动作。
通过添加一个print(event),我们可以观察到捕捉了哪些动作。
while True:
# 循环获取事件,监听事件状态
for event in pygame.event.get():
print(event)
pygame.display.update()
实际上,我们目前的代码一直有一个Bug,就是在程序运行后,没办法通过点击窗口坐上角的x来关闭窗口。接下来我们对程序进行一些改动来解决这个问题。
while True:
# 循环获取事件,监听事件状态
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
event.type用以返回事件的类型,在pygame中定义了以下基础事件类型。
pygame.QUIT用以判断是否按下了窗口坐上方的x按钮。如果“是”的话,则会执行pygame.quit(),它与pygame.init()的作用相反,用于停止Pygame库的工作,之后再执行sys.exit()关闭程序。
QUIT none
ACTIVEEVENT gain, state
KEYDOWN key, mod, unicode, scancode
KEYUP key, mod, unicode, scancode
MOUSEMOTION pos, rel, buttons, touch
MOUSEBUTTONUP pos, button, touch
MOUSEBUTTONDOWN pos, button, touch
JOYAXISMOTION joy (deprecated), instance_id, axis, value
JOYBALLMOTION joy (deprecated), instance_id, ball, rel
JOYHATMOTION joy (deprecated), instance_id, hat, value
JOYBUTTONUP joy (deprecated), instance_id, button
JOYBUTTONDOWN joy (deprecated), instance_id, button
VIDEORESIZE size, w, h
VIDEOEXPOSE none
USEREVENT code
再举例说明:KEYDOWN、KEYUP分别指的是键盘按钮的按下和释放两种状态;MOUSEMOTION指的是鼠标的移动;JOYAXISMOTION手柄移动;JOYBALLMOTION手柄滚球移动;VIDEORESIZE窗口缩放。
然而,以上只是事件类型的冰山一角,在后面的实例中我们还将丰富对这一部分的了解。你也可以在pygame官网文档查询更多的内容:https://www.pygame.org/docs/ref/event.html
(四)事件实例
实例1:在窗口中显示动态时间
如下图所示在窗口中动态显示时间
游戏初始化
import pygame
import sys
import time
pygame.init() # pygame初始化
fpsclock = pygame.time.Clock() # 创建一个对象用于追踪时间
screen = pygame.display.set_mode((400, 400)) # 初始化一个屏幕用以显示
pygame.display.set_caption('hello world') # 设置窗口标题
background = pygame.image.load('./image/plane/background.png').convert_alpha() # 载入背景图片
screen.blit(background, (0, 0)) # 将背景图片放到屏幕上
clock_font = pygame.font.SysFont('仿宋gb_2312', 25) # 创建一个文字对象
设置更新动作
def clock_update():
clock = time.strftime("%Y-%m-%d %H-%M-%S", time.localtime()) # 将本地时间按照年-月-日 时:分:秒的格式存入clock
clock_caption = clock_font.render(f'现在时间:{clock}', True, (255, 0, 0), (0, 0, 0)) # 将文本绘制到一个新的Surface对象上
clock_caption_rect = clock_caption.get_rect() # 获得文本所在Surface对象的rect
clock_caption_rect.center = screen.get_rect().center # 将文本Surface对象的rect中心与屏幕的中心对齐
screen.blit(clock_caption, clock_caption_rect.topleft) # 将文本Surface绘制到屏幕上
设置循环事件
while True:
fpsclock.tick(60) # 调用时间对象的tick方法设置屏幕刷新屏幕,每秒循环的次数
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
clock_update() # 调用时间更新事件
pygame.display.update() # 更新屏幕,实现动态显示
实例2:键盘操作移动图片到指定位置
如下图所示,程序运行后,小汽车位于窗口的左上角,通过键盘的上下左右按键操作小汽车移动,当小汽车移动到红色框框,屏幕提示“well done”。
1.游戏初始化
import pygame
import sys
pygame.init() # pygame初始化
screen = pygame.display.set_mode((500,500)) # 设置窗口大小width,height都为500
pic = pygame.image.load('./image/driver/car1.png').convert_alpha() # 插入小车图片
pic = pygame.transform.scale(pic, (50, 50)) # 将图片大小缩放为width,height都为50
pic_rect = pic.get_rect() # 获得图片的rect对象
screen.blit(pic, (0, 0)) # 设置pic初始位置,(0,0)也可以缺省。如果不提供,默认就是插入到(0,0)
speed = 10 # 移动速度
fpsticks = pygame.time.Clock() # 创建一个时间对象
font = pygame.font.SysFont('仿宋gb_2312', 25) # 创建一个系统字体对象
msg = font.render('Go to the target...', True, (255, 255, 255)) # 生成文本Surface
msg_rect = msg.get_rect() # 获得msg的rect
msg_rect.topleft = (100, 100) # 设置msg信息的位置
pygame.Rect
Rect对象是pygame用于存储矩形坐标的对象,它决定了游戏中图像的位置和大小,是pygame中非常核心的内容。
pygame object for storing rectangular coordinates
Rect(left, top, width, height) -> Rect
Rect((left, top), (width, height)) -> Rect
Rect(object) -> Rect
Rect对象有许多虚拟属性用于移动和与对齐其他的Rect。
The Rect object has several virtual attributes which can be used to move and align the Rect
以下是Rect对象具有的属性
x,y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h
print(pic_rect)
# 当输出pic_rect时,将获得pic的rect值,(0, 0, 50, 50)
print(pic_rect.center)
# 同样,当输出pic_rect.center时,将获得这个矩形中心点的坐标,其他属性以此类推。
print(pic_rect.x,pic_rect.y)
# 背景的坐上角是原点的位置,x代表在水平方向上离原点的距离,y代表在垂直方向上离原点的距离。
通过修改Rect将实现对图像的移动。
# 如上图所示,下面代码将把矩形向上刚好移除屏幕
pic_rect.y = - pic_rect.height
# 我们还可以先定义一个移动速度,然后使用一个循环使Rect的x或y值按一定的速度移动
speed = 1
while True:
pic_rect.x += speed
设置游戏循环
while True:
fpsticks.tick(60) # 设置游戏刷新频率,每秒循环的次数
for event in pygame.event.get():
if pic_rect.topleft == (300, 200): # 判断小车是否进入目标区域
msg = font.render('Well done', True, (255, 255, 255))
else:
msg = font.render('Go to the target...', True, (255, 255, 255))
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed() # 返回一个布尔值序列代表键盘上每个键被按下状态
if keys[pygame.K_UP]: # 意思是判断键盘上的Up键是否被按下
pic_rect.y -= speed # 代表每按下一次,小车的y坐标减去速度,等同于小车按照speed向上移动一次
elif keys[pygame.K_DOWN]:
pic_rect.y += speed # 小车向下移动,小车的y坐标增大
elif keys[pygame.K_LEFT]:
pic_rect.x -= speed # 小车向左移动,小车的x坐标减小
elif keys[pygame.K_RIGHT]:
pic_rect.x += speed # 小车向右移动,小车的x坐标增大
screen.fill((0, 0, 0)) # 背景不断刷行,从而隐藏小车移动过程中留下的痕迹
screen.fill((255, 0, 0),(300, 200, 50, 50)) # 此处绘制的是目标位置,背景刷新的同时,刷新目标位置,如果不刷新,目标位置将被背景覆盖住
screen.blit(msg, msg_rect.topleft) # 刷新消息框信息
screen.blit(pic, pic_rect.topleft) # 刷新小车位置
pygame.display.update() # 重新显示屏幕内容
本篇到此结束,在下一篇中将对上述代码的结构和方法进行优化,随后以实例引入精灵的相关介绍。