Pygame Pygame是个游戏开发的敲门砖,大家可以按照自己的喜好选择是否学习Pygame。喜欢游戏的同学可以学习Pygame,制作一个自己喜欢的小游戏。因为是游戏,我特意将背景设为了天空,希望大家在学习游戏开发时遨游梦想天空,体会游戏快乐!
一、Pygame的屏幕绘制机制
再上一个例子中我们已经用到了Pygame的屏幕窗体绘制,在这一节我们将继续深入的讲解pygame的屏幕绘制机制。包括屏幕的分辨率,尺寸,有无边框等等。
先介绍一些函数
pygame.display.set_mod(r=(0,0), flags=0)
r是游戏屏幕的分辨率,采用(width,height)方式输入,flags用来控制显示类型,可用**|**组合使用,常用显示标签如下:
pygeme.RESIZABLE窗口大小可调
pygame.NOFRAME窗口没有边界显示
pygame.FULLSCREEN窗口全屏显示
注意:屏幕改变相关游戏逻辑要做出相应的改变
pygame.disply.Info()
产生一个显示信息对象VideoInfo,表达当前屏幕的参数信息。在.set_mode()之前调用,则显示当前系统显示参数信息。其中有两个重要参数如下:
current_w 当前显示模式窗口的像素宽度
current_h 当前显示模式窗口的像素高度
pygame.VIDEORESIZE
这是一种窗口大小更改的事件,事件发生后,返回event.size元组,包含新窗口的宽度和高度。其中两个参数如下:
.size[0]宽度,也可以用event.w
.size[1]高度,也可以用event.h
返回参数仅在事件发生时有效
pygame.display.set_caption(title, icontitle)
title设置窗口的标题内容
icontitle设置图标化后的小标题小标题可选择是否设置,部分操作系统没有提供
pygame.display.get_caption()
返回当前设置窗口的标题及小标题内容,返回结构为**(title,icontitle)**,该函数与游戏交互逻辑相配合,可以根据游戏情节修改标题内容。
pygame.display.set_icon(surface)
设置窗口的图标效果,图标是一个surface对象
pygame.display.set_icon(surface)
设置窗口的图标效果,图标是一个surface对象
pygame.display.flip()
重新绘制屏幕中整个窗口
pygame.display.upddate()
仅绘制屏幕中有变化的部分,速度比pygame.display.flip()快
import pygame,sys
pygame.init() #初始化参数
size = width, height = 600,400 #设置窗体大小参数
speed = [1,1] #设置移动速度参数
BLACK = 0, 0, 0 #设置背景颜色参数RGB
screen = pygame.display.set_mode(size, pygame.RESIZABLE) #窗口大小可调
icon = pygame.image.load("code.jpg") #导入图标文件
pygame.display.set_icon(icon) #设置图标文件
pygame.display.set_caption("跟着夜寒学Python") #设置标题栏
ball = pygame.image.load("test.png") #导入图片,注意图片为自己下载的,在自己机子上运行时注意更改
ballrect = ball.get_rect() #设置图片surface参数
fps = 300 #设置刷新帧率参数
fclock = pygame.time.Clock() #创建clock.用于后续操作刷新时间
while True:
for event in pygame.event.get(): #获取事件
if event.type == pygame.QUIT: #点击右上角叉退出
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed[0] = speed[0] if speed[0] ==0 else (abs(speed[0]) -1 )* int(speed[0]/abs(speed[0]))
elif event.key == pygame.K_RIGHT:
speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
elif event.key == pygame.K_UP:
speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
elif event.key == pygame.K_DOWN:
speed[1] = speed[1] if speed[1] ==0 else (abs(speed[1]) -1 )* int(speed[1]/abs(speed[1]))
elif event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == pygame.VIDEORESIZE:
size = width, height = event.size[0], event.size[1]
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
if pygame.display.get_active(): #是否最小化界面
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = - speed[1]
screen.fill(BLACK) #设置轨迹填充
screen.blit(ball, ballrect) #将图片放在rect切线矩形上
pygame.display.update() #刷新
fclock.tick(fps) #刷新帧率
二、Pygame事件类型处理
上一部分我们详细讲解了pygame的屏幕绘制体系,当我们掌握了屏幕绘制体系之后我们便可以进一步学习事件处理机制,包括鼠标和按键的相关操作。这样我们才能做出更具有互动性的游戏。
先介绍一些函数
pygame.event.EventType
pygame的事件本质上是一种封装后的数据类型(对象),是Pygame的一个类,表示事件类型。事件类型只有属性,没有方法。(属性是类的静态参数,方法是类的可操作内容,不懂的可以去看这篇文章Python进阶学习之——类和对象)当事件发生后我们可以通过这个类获取事件还原参数,同时用户可以编写程序,自定义一些新的事件类型。
下面介绍一些pygame提供的一些事件类型:
QUIT
退出系统
ACTIVE
是否最小化界面
KEYDOWN 键盘的按下
KEYUP 键盘的释放
其中KEYDOWN 和KEYUP包含以下三个属性event.unicode、event,key、event.mod分别指键盘的unicode编码,按键名称,和键盘按下时的修饰符。部分电脑不支持返回unicode所以不建议使用,修饰符适用于组合,可产生整整想要表达的目的,下面介绍一些修饰符:
下面我们来举个例子让大家直观的看到变化:
import pygame,sys #引入
pygame.init() #初始化
screen = pygame.display.set_mode((600, 400)) #设置窗体大小
pygame.display.set_caption("跟着夜寒学Python") #设置标题栏
while True: #无限循环
for event in pygame.event.get():
if event.type == pygame.QUIT: #设置推出响应
sys.exit() #退出程序
elif event.type == pygame.KEYDOWN:
if event.unicode == "": #判断unicode编码是否为空
print("[KEYDOWN]:","#", event.key, event.mod) #空则输出#字符
else:
print("[KEYDOWN]:", event.unicode, event.key, event.mod) #不空输出unicode编码
pygame.display.update()
MOUSEMOTION 鼠标的移动
MOUSEBOTTONUP 鼠标按键的按下
MOUSEBOTTONDOWN 鼠标按键的释放
其中MOUSEMOTION包含三个属性event.pos:鼠标当前坐标值(x,y),相对于窗口左上角;event.rel:鼠标相对运动距离(x,y),相对于上次事件;event.bottons:鼠标按钮状态(a,b,c),对应于鼠标的三个键(左、中、右)。鼠标移动时,这三个键处于按下状态,对应的值为1,反之则为0。
其中MOUSEBOTTONUP和MOUSEBOTTONDOWN包含两个属性event.pos:鼠标当前坐标值(x,y),相对于窗口左上角;event.botton:鼠标按下(释放)键编号n,取值1/2/3,分别对应三个键编号不固定,与设备有关
下面我们来举个例子让大家直观的看到变化:
import pygame,sys
pygame.init()
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Pygame事件处理")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.unicode == "":
print("[KEYDOWN]:", "#", event.key, event.mod)
else:
print("[KEYDOWN]:", event.unicode, event.key, event.mod)
elif event.type == pygame.MOUSEMOTION: #监控鼠标指针位置
print("[MOUSEMOTION]:", event.pos, event.rel, event.buttons) #输出当前位置及按键情况
elif event.type == pygame.MOUSEBUTTONUP: · #监控鼠标按键是否释放
print("[MOUSEBUTTONUP]:", event.pos, event.button) #输出按下按键位置及编号
elif event.type == pygame.MOUSEBUTTONDOWN: #监控鼠标按键是否按下
print("[MOUSEBUTTONDOWN]:", event.pos, event.button) #输出按下按键位置及编号
pygame.display.update()
JOYAXISMOTION 游戏杆
JOYBALLMOTION 游戏杆
JOYHATMOTION 游戏杆
JOYBUTTONUP 游戏杆
JOYBUTTONDOWN 游戏杆
VIDEORESIZE 窗口
VIDEOEXPOSE 窗口
USEREVENT 用户自定义事件
pygame.event.get()
从事件队列中获得事件列表,即获得所有被队列的事件。同时它可以增加参数,获得某些或某类事件:
pygame.event.get(type)
pygame.event.get(typelist)
pygame.event.poll()
从事件队列中获得某一个事件,事件获取将从事件队列删除,如果事件队列为空,则返回event.NOEVENT
pygame.event.clear()
从事件队列中删除事件,默认删除所有事件,该函数与**pygame.event.get()**类似,区别仅是不对事件进行处理,只删除。同时可以增加参数,删除某类或某些类事件:
pygame.event.clear(type)
pygame.event.clear(typelist)
pygame.event.set_blocked(type or typelist)
控制哪些类型的事件不允许被保存到事件队列中
pygame.event.get_blocked(type or typelist)
控制哪些类型事件允许被保存到事件队列中
pygame.event.set_aiiowed(type)
测试某个事件类型是否被事件队列所禁止,如果事件类型被禁止,则返回True,否则返回False。
以上三个函数用来操作事件队列,事件队列仅能存储128个事件,满后新来的事件将被丢弃,所以需要规范处理。
pygame.event.post(Event)
产生一个时间,并将其放到事件队列,一般用于放置用户自定义事件(pygame.USERNAME),也可以用于放置系统定义事件,给定参数。
pygame.event.Event(type,dict)
创建一个给定类型的事件。其中,时间的属性和值采用字典类型复制,属性名采用字符串形式,如果创建已有事件,属性需要一致。
以上两个函数用来生成事件,下面我们来举个例子让大家直观的看到变化:
import pygame,sys
pygame.init()
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Pygame事件处理")
fps = 1 #每秒一帧
fclock = pygame.time.Clock()
num = 1
while True:
uevent = pygame.event.Event(pygame.KEYDOWN, {"unicode": 123, "key":pygame.K_SPACE, "mod":pygame.KMOD_ALT}) #生成事件的字典
pygame.event.post(uevent) #生成一个事件
num = num + 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.unicode == "":
print("[KEYDOWN {}]:".format(num), "#", event.key, event.mod)
else:
print("[KEYDOWN {}]:".format(num), event.unicode, event.key, event.mod)
pygame.display.update()
fclock.tick(fps)
这是一些按键常量名称:
最后我们再来改造一下游戏,使他可以根据我们鼠标的拖拽放置碰撞图片位置。
import pygame,sys
pygame.init() #初始化参数
size = width, height = 600,400 #设置窗体大小参数
speed = [1,1] #设置移动速度参数
BLACK = 0, 0, 0 #设置背景颜色参数RGB
screen = pygame.display.set_mode(size, pygame.RESIZABLE) #窗口大小可调
icon = pygame.image.load("code.jpg") #导入图标文件
pygame.display.set_icon(icon) #设置图标文件
pygame.display.set_caption("跟着夜寒学Python") #设置标题栏
ball = pygame.image.load("test.png") #导入图片,注意图片为自己下载的,在自己机子上运行时注意更改
ballrect = ball.get_rect() #设置图片surface参数
fps = 300 #设置刷新帧率参数
fclock = pygame.time.Clock() #创建clock.用于后续操作刷新时间
still = False
while True:
for event in pygame.event.get(): #获取事件
if event.type == pygame.QUIT: #点击右上角叉退出
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
speed[0] = speed[0] if speed[0] ==0 else (abs(speed[0]) -1 )* int(speed[0]/abs(speed[0]))
elif event.key == pygame.K_RIGHT:
speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
elif event.key == pygame.K_UP:
speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
elif event.key == pygame.K_DOWN:
speed[1] = speed[1] if speed[1] ==0 else (abs(speed[1]) -1 )* int(speed[1]/abs(speed[1]))
elif event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == pygame.VIDEORESIZE: #界面可调
size = width, height = event.size[0], event.size[1]
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
elif event.type == pygame.MOUSEBUTTONDOWN: #鼠标按下
if event.button == 1:
still = True
elif event.type == pygame.MOUSEBUTTONUP: #鼠标抬起
still = False
if event.button == 1:
ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0] == 1:
ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
if pygame.display.get_active() and not still: #是否最小化界面
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.right > width and ballrect.right + speed[0] > ballrect.right:
speed[0] = - speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = - speed[1]
if ballrect.bottom > height and ballrect.bottom + speed[1] > ballrect.bottom:
speed[1] = - speed[1]
screen.fill(BLACK) #设置轨迹填充
screen.blit(ball, ballrect) #将图片放在rect切线矩形上
pygame.display.update() #刷新
fclock.tick(fps) #刷新帧率
扫 码 关 注