• Python最经典的2D游戏开发第三方库,也支持3D游戏开发
• Pygame适合用于游戏逻辑验证、游戏入门及系统演示验证
• Pygame是一种游戏开发引擎,基本逻辑具有参考价值
• Pygame有些"过时",但永远"不过时"
• 使用Pygame可以开发出优秀的游戏!
• sys是Python的标准库
• sys提供Python运行时环境变量的操控
• sys.exit()用于退出结束游戏并退出
对Pygame内部各功能模块进行初始化创建及
变量设置,默认调用
初始化显示窗口,第一个参数size是一个二
值元组,分别表示窗口的宽度和高度
无限循环,直到Python运行时退出结束
从Pygame的事件队列中取出事件,并从队列
中删除该事件,例如:键盘按下是一个事件。
获得事件类型,并逐类响应;pygame.QUIT
是Pygame中定义的退出事件常量
对显示窗口进行更新,默认窗口全部重绘
moveBall1.py(壁球小游戏)
import pygame,sys
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
pygame.display.set_caption("小球碰撞")
color=60,63,65
screen.fill(color)
ball=pygame.image.load("pic/ball.png")
ball_rect=ball.get_rect()
speed=[1,1]
while True:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
ball_rect=ball_rect.move(speed[0],speed[1])
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.update()
控制帧速度,即窗口刷新速度,例如:
clock.tick(100)表示每秒钟100次帧刷新
视频中每次展示的静态图像称为帧
moveBall2.py
import pygame,sys
pygame.init()
size = width, height = 600, 400
speed = [1,1]
BLACK = 0, 0, 0
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pygame壁球")
ball = pygame.image.load("PYG02‐ball.gif")
ballrect = ball.get_rect()
fps = 300
fclock = pygame.time.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]))
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)
pygame.display.update()
fclock.tick(fps)
事件处理需求
• 响应用户键盘、鼠标等外设操作
• 响应屏幕尺寸和模式变化
• 响应游戏情节的特定触发条件
• 产生一些触发条件
Pygame事件队列
Pygame事件
pygame.event.EventType
• 事件本质上是一种封装后的数据类型(对象)
• EventType是Pygame的一个类,表示事件类型
• 事件类型只有属性,没有方法
• 用户可自定义新的事件类型
Pygame事件处理函数
键盘事件及类型的使用
鼠标事件及类型的使用
壁球小游戏(鼠标型)
事件类型及属性
事件处理的重要函数
键盘事件及属性
按键的常量名称
event.key
按键的修饰符
鼠标事件及属性
e.event.MOUSEMOTION 鼠标移动事件
• event.pos 鼠标当前坐标值(x,y),相对于窗口左上角
• event.rel 鼠标相对运动距离(X,Y),相对于上次事件
• event.buttons 鼠标按钮状态(a,b,c),对应于鼠标的三个键
pygame.event.MOUSEBUTTONUP 鼠标键释放事件
• event.pos 鼠标当前坐标值(x,y),相对于窗口左上角
• event.button 鼠标按下键编号n 取值 0/1/2,分别对应三个键
pygame.event.MOUSEBUTTONDOWN 鼠标键按下事件
• event.pos 鼠标当前坐标值(x,y),相对于窗口左上角
• event.button 鼠标按下键编号n 取值为整数,左键为1,右键为3,设备相关
import pygame,sys
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
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("[MOUSEMOTTON]",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()
对小球弹跳进行优化
import pygame, sys
pygame.init()
vInfo = pygame.display.Info()
# 设置屏幕显示为全屏
# size=width,height=vInfo.current_w,vInfo.current_h
# screen=pygame.display.set_mode(size,pygame.FULLSCREEN)
size = width, height = 600, 400
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
# 设置屏幕可改变
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)
ball = pygame.image.load("pic/ball.png")
ball_rect = ball.get_rect();
icon = pygame.image.load("pic/dragon.png")
pygame.display.set_icon(icon)
speed = [1, 1]
fps = 300
fClock = pygame.time.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(abs(speed[1]) / 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:
ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0] == 1:
ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
if pygame.display.get_active() and not still: # 当屏幕活跃时(未缩小为最小化)
ball_rect = ball_rect.move(speed[0], speed[1])
if (ball_rect.left < 0 or ball_rect.right > width):
speed[0] = -speed[0]
if ball_rect.right > width and ball_rect.right + speed[0] > ball_rect.right:
speed[0] = -speed[0]
if (ball_rect.top < 0 or ball_rect.bottom >height):
speed[1] = -speed[1]
if ball_rect.bottom > height and ball_rect.bottom + speed[1] >ball_rect.bottom:
speed[1] = -speed[1]
if ball_rect.top<0 and ball_rect.top+speed[1]<ball_rect.top:
speed[1] = -speed[1]
screen.fill(color)
screen.blit(ball, ball_rect)
pygame.display.update()
fClock.tick(fps)
事件处理的重要函数
pygame.event.get()
pygame.event.poll()
pygame.event.clear()
Pygame事件队列
pygame.event.set_blocked(type or typelist)
•控制哪些类型事件不允许被保存到事件队列中
pygame.event.set_allowed(type or typelist)
•控制哪些类型事件允许被保存到事件队列中
pygame.event.get_blocked(type)
•测试某个事件类型是否被事件队列所禁止
•如果事件类型被禁止,则返回True,否则返回False
pygame.event.post(Event)
•产生一个事件,并将其放入事件队列
•一般用于放置用户自定义事件(pygame.USEREVENT)
•也可以用于放置系统定义事件(如鼠标或键盘等),给定参数
pygame.event.Event(type, dict)
•创建一个给定类型的事件
•其中,事件的属性和值采用字典类型复制,属性名采用字符串形式
•如果创建已有事件,属性需要一致
import pygame, sys
pygame.init()
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("pygame事件处理")
fps = 12
fclok = pygame.time.Clock()
num = 10
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("[KEYDOW{}]".format(num), event.unicode, event.key, event.mod)
pygame.display.update()
fclok.tick(fps)
Color类用于表达色彩,使用RGB或RGBA色彩模式,A可选
Color类可以用色彩名字、RGBA值、HTML色彩格式等方式定义
pygame.Color
Color(name) 例如:Color(“grey”)
Color(r,g,b,a) 例如:Color(190, 190, 190, 255)
Color(rgbvalue) 例如:Color("#BEBEBEFF")
• RGB色彩模式之外增加了第四维度:alpha通道
• alpha通道表示不透明度,取值0-255,默认255
• alpha通道值越大,不透明度越高,255表示不透明
pygame.Color.r 获得Color类的红色值r
pygame.Color.g 获得Color类的绿色值g
pygame.Color.b 获得Color类的蓝色值b
pygame.Color.a 获得Color类的不透明度值a
pygame.Color.normalize 将RGBA各通道值归一到0-1之间
壁球小游戏(色彩型)
import pygame, sys
def RGBChanel(a):
return (0 if a<0 else (255 if a>255 else int(a)))
pygame.init()
vInfo = pygame.display.Info()
# 设置屏幕显示为全屏
# size=width,height=vInfo.current_w,vInfo.current_h
# screen=pygame.display.set_mode(size,pygame.FULLSCREEN)
size = width, height = 600, 400
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
# 设置屏幕可改变
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)
ball = pygame.image.load("pic/ball.png")
ball_rect = ball.get_rect();
icon = pygame.image.load("pic/dragon.png")
pygame.display.set_icon(icon)
speed = [1, 1]
fps = 300
fClock = pygame.time.Clock()
still = False
bgcolor=pygame.Color("black")
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(abs(speed[1]) / 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:
ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0] == 1:
ball_rect = ball_rect.move(event.pos[0] - ball_rect.left, event.pos[1] - ball_rect.top)
if pygame.display.get_active() and not still: # 当屏幕活跃时(未缩小为最小化)
ball_rect = ball_rect.move(speed[0], speed[1])
if (ball_rect.left < 0 or ball_rect.right > width):
speed[0] = -speed[0]
if ball_rect.right > width and ball_rect.right + speed[0] > ball_rect.right:
speed[0] = -speed[0]
if (ball_rect.top < 0 or ball_rect.bottom >height):
speed[1] = -speed[1]
if ball_rect.bottom > height and ball_rect.bottom + speed[1] > ball_rect.bottom:
speed[1] = -speed[1]
bgcolor.r=RGBChanel(ball_rect.left*255/width)
bgcolor.g=RGBChanel(ball_rect.top*255/width)
bgcolor.b=RGBChanel(min(speed[0],speed[1])*255/max(speed[0],speed[1],1))
screen.fill(bgcolor)
screen.blit(ball, ball_rect)
pygame.display.update()
fClock.tick(fps)
向屏幕上绘制一些简单的图形,如直线、圆形、椭圆等。任何一个图形绘制后,会返回一个矩形Rect类表示该形状
表达一个矩形区域的类,用于存储坐标和长度信息。Pygame利用Rect类来操作图形/图像等元素
Rect类提供了如下属性,返回一个数值或一个代表坐标的元组
Rect类提供了如下方法,用来操作Rect类
import pygame,sys
from math import pi
pygame.init()
size=width,height=600,400
screen=pygame.display.set_mode(size)
pygame.display.set_caption("pygame图形绘制")
WHITE=pygame.Color('white')
GREEN=pygame.Color('green')
GOLD=(255,251,0)
RED=pygame.Color('red')
elrect=pygame.draw.ellipse(screen,GREEN,(50,50,500,300),3)
c1rect=pygame.draw.circle(screen,GOLD,(200,180),30,5)
c2rect=pygame.draw.circle(screen,GOLD,(400,180),30)
r1rect = pygame.draw.rect(screen, RED, (170,130, 60, 10), 3)
r2rect = pygame.draw.rect(screen, RED, (370,130, 60, 10))
plist = [(295,170), (285,250), (260,280), (340,280), (315,250), (305,170)]
#l1rect = pygame.draw.lines(screen, GOLD, True, plist, 2)
al1rect = pygame.draw.aalines(screen, GOLD, True, plist, 2)
a1rect = pygame.draw.arc(screen, RED, (200,220,200,100), 1.4*pi, 1.9*pi, 3)
while True:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
pygame.display.update()
pygame.freetype
向屏幕上绘制特定字体的文字。文字不能直接print() ,而是用像素根据字体点阵图绘制
pygame.freetype是绘制文字的增强方法,建议使用必须额外增加import引用,如下:
系统中的字体
import pygame, sys
import pygame.freetype
import pygame, sys
pygame.init() # 对Pygame内部各功能模块进行初始化创建及变量设置,默认调用
screen = pygame.display.set_mode((600, 400)) # 初始化显示窗口,第一个参数size是一个二值元组,分别表示窗口的宽度和高度
pygame.display.set_caption("Pygame游戏绘制") # 设置显示窗口标题设置显示窗口的标题内容,参数title是一个字符串类型
GOLD = (255, 251, 0)
f1=pygame.freetype.Font("c://Windows//Fonts//msyh.ttc",36) # 微软雅黑
# f1rect=f1.render_to(screen,(200,160),"知行合一",fgcolor=GOLD,size=50)
f1 = pygame.freetype.Font('C://Windows//Fonts//msyh.ttc', 50) # 微软雅黑
f1surf, f1rect = f1.render("世界和平", fgcolor=GOLD, size=30)
f1rect.left=200
f1rect.top=160
while True: # 无限循环,直到Python运行时退出结束 # 微软雅黑
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit() # 用于退出结束游戏并退出
screen.blit(f1surf, f1rect)
pygame.display.update() # 刷新窗体
import pygame, sys
import pygame.freetype
pygame.init()
size = width, height = 600, 400
screen = pygame.display.set_mode(size)
pygame.display.set_caption("小球碰撞")
color = 60, 63, 65
screen.fill(color)
speed = [1, 1]
GOLD = (255, 251, 0)
RED = pygame.Color('red')
pos = [230, 100]
text = "世界和平"
f1 = pygame.freetype.Font("C://Windows//Fonts//msyh.ttc", 36)
# f1rect=f1.render_to(screen,pos,text,fgcolor=GOLD,size=60)
f1surf, f1rect = f1.render("世界和平", fgcolor=GOLD, size=50)
fps = 300
fclock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.VIDEORESIZE:
width = event.size[0]
height = event.size[1]
size = width, height
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
if pos[0] <= 0 or pos[0] + f1rect.width >= width:
speed[0] = -speed[0]
if pos[1] <= 0 or pos[1] + f1rect.height >= height:
speed[1] = -speed[1]
pos[0] = pos[0] + speed[0]
pos[1] = pos[1] + speed[1]
screen.fill(color)
# f1rect=f1.render_to(screen,pos,text,fgcolor=GOLD,size=50)
f1surf, f1rect = f1.render(text, fgcolor=GOLD, size=50)
screen.blit(f1surf, (pos[0], pos[1]))
pygame.display.update()
fclock.tick(fps)