Pygame入门笔记
介绍
费曼学习法最重要的部分,即把知识教给一个完全不懂的孩子——或者小白。
为了更好的自我学习,也为了让第一次接触某个知识范畴的同学快速入门,我会把我的学习笔记整理成电子幽灵系列。
提示:文章的是以解释-代码块-解释的结构呈现的。当你看到代码块并准备复制复现的时候,最好先保证自己看过了代码块前后的解释。
Pygame笔记目录
Pygame介绍
Pygame是用来做页面游戏的一个开源Python库。通过Pygame可以很方便地制作出一个交互界面,进而创作页面游戏。
官方Github:https://github.com/pygame
官方文档:https://www.pygame.org/docs/
本文档内容总结自Pygame官方文档及其中译版本、BiliBili相关教程
下载
- 下载:python3 -m pip install -U pygame --user
最新版本:python -m pip install -U pygame==2.5.2 --user
常用模块
模块一览
模块名称 | 模块功能 |
---|---|
cdrom | 播放/回放 |
cursors | 加载光标图像,包括标准指针 |
Color | 填充颜色 |
display | 控制显示窗口或屏幕 |
draw | 在Surface对象上绘制简单的形状、线或点 |
event | 管理事件和事件队列 |
font | create和render TrueType字体 |
image | 保存和加载图像 |
joystick | 管理操纵杆设备 |
key | 管理键盘 |
mixer | 管理声音 |
mouse | 管理鼠标 |
movie | 播放视频 |
music | 播放音频 |
overlay | 访问高级视频叠加 |
rect | 管理矩形区域 |
scrap | 本地剪切板访问 |
sndarray | 用numpy操纵声音 |
sprite | 操纵移动图像sprite(精灵) |
surfarray | 用numpy操纵图像 |
surface | 管理图像和屏幕 |
time | 控制时间 |
transform | 缩放,旋转和翻转图像 |
#导入、初始化、退出
import pygame as pg
pg.init()#初始化pygame界面
pg.get_init()#如果已经初始化,返回True
pg.quit()#退出pygame界面
虽然我比较习惯于把pygame缩写成pg,但是并没有发现其他人有这个习惯…
'''以下是官网的例子'''
# Example file showing a basic pygame "game loop"
import pygame
# pygame setup
pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()
while 1:
# poll for events
# pygame.QUIT event means the user clicked X to close your window
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# fill the screen with a color to wipe away anything from last frame
screen.fill("purple")
# RENDER YOUR GAME HERE
# flip() the display to put your work on screen
pygame.display.flip()
clock.tick(60) # limits FPS to 60
某些需要注意的点
- blit(我也忘记我为什么要写这个?)
BLIT意味着把一个图像复制到另一个图像(相当于图层覆盖)
(更正式的定义是将 数据数组 复制到 位映射数组 (bitmapped array)的目的地)
具体细节就是为目标图像上的像素点重新赋值。 - 屏幕坐标
pygame的坐标轴是以左上角为原点的,以向右和向下为X、Y正方向。 - 特殊数据结构:Rect
在pygame中有一个特殊的容器,叫做Rect。它是一个包含四个数的元组,结构是(左、上、宽、高)。前两个数字确定Rectangle的左上角,后两个确定它的宽和高。
pygame中很多函数都需要且接受Rect参数,传入即可。比如blit函数就可以接受一个Rect参数,但是只使用前两个参数作为图像的左上角。因此可以只输入一个二元/三元组作为Rect容器的一部分。
常用模块&常用函数(本笔记后来要用到的部分)
display模块
'''display模块常用函数'''
from pygame import display
display.init()
display.get_init()
''''''
screen=display.set_mode((680,720))#输入一个二元组,初始化一个相应长宽的界面
#这个页面可以赋值给一个对象,使得我们能够在之后面向他编程
print(screen)
surface=display.get_surface()#获取当前surface对象
print(surface)
display.flip()#更新并在屏幕上显示当前的surface对象
#display.update(rectangle=None)#更新部分内容并在屏幕上显示。如果参数为空(rectangle=None),则与flip功能相同
'''update函数可以传递一个rectangle_list,可以同时传递多个rect参数,效率更高'''
display.quit()
输出:
<Surface(680x720x32 SW)>
<Surface(680x720x32 SW)>
draw 模块
'''draw模块常用函数'''
import pygame as pg
from pygame import draw
color=(255,255,255)
width=8#注意,如果这里width为0,绘制的图形就是实心的
'''画一条线,参数顺序为:哪个Surface对象、颜色、起始坐标、终点坐标、宽度(像素级)'''
draw.line(screen, color, (35, 35), (135, 135), width)
'''画一个圆,参数顺序为:哪个Surface对象、颜色、圆心坐标、半径、边缘宽度(像素级)'''
draw.circle(screen,color,(200,200),30,width)
'''画一个长方形,参数顺序为:哪个Surface对象、颜色、Rect容器、边缘宽度(像素级)'''
draw.rect(screen, color, (500, 100, 40, 80), width)
'''画一个椭圆,参数顺序为:哪个Surface对象、颜色、Rect容器、边缘宽度(像素级)'''
draw.ellipse(screen, color, (600,300,100,50),width)
key模块
'''key模块常用函数'''
import pygame
from pygame import key
'''返回一个按键布尔列表,哪个键被按下了,相应的按键就会变为True'''
pressed=key.get_pressed()
'''返回一个按键布尔字典,如果相应的键被按下,就会返回True'''
keys=key.get_key_pressed()
'''设置一个重复事件,参数顺序为:按键后多少ms后开始重复、每次重复间隔多少ms'''
key.set_repeat(1000,10)
key.set_repeat(None)#参数为None将禁用重复。
'''返回当前键盘重复事件的延迟时间和间隔时间,以毫秒为单位。'''
delay, interval = pygame.key.get_repeat()
print(delay, interval) # 输出当前的延迟时间和间隔时间
'''返回给定按键名称'''
key_name = key.name(pygame.K_LEFT)
print(key_name) # 输出:LEFT
'''返回给定修饰键的状态。
修饰键:Shift、Ctrl、Alt'''
mod=key.get_mods()
'''设置当前按下的修饰键的状态。
可以将修饰键的组合作为参数传递给该函数,以设置修饰键的状态。'''
key.set_mods(pygame.KMOD_SHIFT | pygame.KMOD_CTRL)#这里是同时按下Shift和Ctrl
上述模块和函数已经足以完成一些基础控制了。接下来,我们要用这些函数实现一些功能。
基础控制
接下来将用pygame中的各种库函数完成一系列基础控制。比如创建一个窗口、给这个窗口涂一些颜色,可以移动窗口中的某些图像等等。
创建窗口
'''ver0.1'''
import pygame as pg
pg.init()
pg.display.set_mode()
问题:
- 窗口最大化全屏,无法进行其他操作
- 窗口只会闪一下,之后无法再响应
'''ver0.2'''
import pygame as pg
pg.init()
size=wideth,length=(360,240)#size会自动转化为元组
pg.display.set_mode(size)
while 1:
continue
ver0.2解决了0.1的问题,
但是由于此处为死循环,没有退出条件,所以程序会一直进行下去,关闭窗口时,就会出现"无法响应"的类似报错的问题。
'''ver0.3'''
import pygame as pg
pg.init()
size=width,length=720,680
pg.display.set_mode(size)
while 1:
for event in pg.event.get():#遍历所有事件
if event.type==pg.QUIT:#如果点击了关闭窗口按钮
pg.quit()#执行退出操作
至此,解决了0.2的问题,构成了一个相对完整、健全的页面。
为窗口涂色
在这里,我们用上面“创建窗口”中已经有的基础,继续更高级的控制。
import pygame as pg
pg.init()
screen=pg.display.set_mode((1280,720))
print(screen)
'''pygame.display.set_mode会产生一个图像表面(surface)对象screen,构成screen页面上的每一个像素都有自己的颜色。
每一个像素的颜色color是一个三元整数组,范围是0~255。
用fill函数可以让整个页面现实一种颜色(由参数决定)'''
color=(123,0,0)
screen.fill(color)
pg.display.flip()
running = True
while 1:
for event in pg.event.get():#遍历所有事件
if event.type==pg.QUIT:#如果点击了关闭窗口按钮
running = False#执行退出操作
print(screen)
pg.quit()
输出:
< Surface(1280x720x32 SW) >
代表screen是一个图像表面对象(surface),分辨率为1280x720个像素,用32位存储每个像素的颜色,SW代表用软件渲染。(相对的,HW代表硬件渲染)
pygame中也可以自己直接创建一个Surface对象而不直接显示到窗口中,就是pg.surface()。
现在我们要改变窗口中一个像素点的颜色。
- set_at()方法
Surface对象的set_at方法可以将某个像素点变为我们想要的颜色。
用法:set_at(坐标位置,颜色)
坐标位置是一个二元组(Rect前两位),颜色可以是三元组(R,G,B),也可以是四元组(R,G,B,A)。
import pygame as pg
pg.init()
screen=pg.display.set_mode((1280,720))
color=(123,0,0)
screen.fill(color)
screen.set_at((640,360),(255,255,255))#把某个像素变为某个颜色
pg.display.flip()
running=True
while running:
for event in pg.event.get():#遍历所有事件
if event.type==pg.QUIT:#如果点击了关闭窗口按钮
running=False#执行退出操作
pg.quit()
移动简单图像
移动一个已经被加载进来的图片显然简单很多,但是移动画出的图形可以和上面的操作连接起来。
- 注:在操作的时候如果打开输入法,会在输入字母的时候隐藏地唤起输入法,输入法会阻碍界面捕捉按键状态。如果打开输入法后敲击字母按键后无法移动,按下Enter即可脱离卡死。
接下来,画一个实心圆,并且用方向键使它移动。
'''version 1.0'''
import pygame as pg
pg.init()
color = (255,255,255)
size = wideth,length = (1280,640)
circle = {
'center' : (640,320),
'radius' : 50,
'color' : color
}
screen = pg.display.set_mode(size)
running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
keys = pg.key.get_pressed()
if keys[pg.K_LEFT] :
circle['center'] = (circle['center'][0] - 1, circle['center'][1])
elif keys[pg.K_RIGHT] :
circle['center'] = (circle['center'][0] + 1, circle['center'][1])
elif keys[pg.K_UP] :
circle['center'] = (circle['center'][0], circle['center'][1] - 1)
elif keys[pg.K_DOWN] :
circle['center'] = (circle['center'][0], circle['center'][1] + 1)
screen.fill('black')
pg.draw.circle(screen,circle['color'],circle['center'],circle['radius'],width = 0)
pg.display.flip()
pg.quit()
ver1.0中,利用pygame.key模块,可以通过操控上下左右键控制圆的移动。
但是,圆会超出边框,所以接下来给圆加上边框,让它不会超出边框。
'''version 2.0'''
import pygame as pg
pg.init()
color = (255,255,255)
size = wideth,length = (1280,640)
circle = {
'center' : (640,320),
'radius' : 50,
'color' : color
}
#clock = pg.time.Clock()
screen = pg.display.set_mode(size)
running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
keys = pg.key.get_pressed()
if keys[pg.K_LEFT] & (circle['center'][0] - circle['radius'] > 0) :
circle['center'] = (circle['center'][0] - 1, circle['center'][1])
elif keys[pg.K_RIGHT] & (circle['center'][0] + circle['radius'] < wideth) :
circle['center'] = (circle['center'][0] + 1, circle['center'][1])
elif keys[pg.K_UP] & (circle['center'][1] - circle['radius'] > 0) :
circle['center'] = (circle['center'][0], circle['center'][1] - 1)
elif keys[pg.K_DOWN] & (circle['center'][1] + circle['radius'] < length) :
circle['center'] = (circle['center'][0], circle['center'][1] + 1)
screen.fill('black')
pg.draw.circle(screen,circle['color'],circle['center'],circle['radius'],width = 0)
pg.display.flip()
#clock.tick(60)
pg.quit()
ver2.0中,圆不会再超出边框了。至此,我们完成了一个相对结构化的小程序;尽管他只是让我们可以移动一个圆,但也是好的开始。
日志
- 动笔:2024/5/1
- 第一稿结束:2024/5/8
- 第二稿更改:2024/5/9