上一篇文章:Python pygame(GUI编程)模块最完整教程(4)_pygame绘制圆角矩形_Python-ZZY的博客-CSDN博客
总目录:
README.md · Python-ZZY/Python-Pygame最完整教程 - Gitee.com
13 显示
参考资料:pygame.display — pygame-ce v2.3.1 documentation
13.1 创建窗口
pg.display.set_mode方法用于创建窗口。
pg.display.set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface
size参数指定窗口的大小,一般是一个元组(宽, 高)。如果设为(0, 0),那么窗口将和电脑屏幕一样大。如果将宽度设为0或高度设为0,那么窗口的宽度或高度和电脑屏幕一样。
flags指定窗口的额外参数,参数之间用按位或运算符"|"组合。额外参数有:
参数 | 解释 |
FULLSCREEN | 使窗口全屏显示 |
HWSURFACE | FULLSCREEN模式下启动硬件加速 |
DOUBLEBUF | 双缓冲模式,仅在OPENGL模式下生效,作用是缓冲绘制的内容,避免卡顿 |
OPENGL | 创建一个OpenGL渲染显示(OpenGL是一个3D绘图引擎) |
RESIZABLE | 窗口允许用户改变大小 |
NOFRAME | 隐藏窗口边框和标题栏 |
SCALED | 使窗口大小适配分辨率高的显示器,在分辨率较高的显示器上不会显得特别小 |
SHOWN | 窗口以显示模式打开(默认) |
HIDDEN | 窗口以隐藏模式打开 |
比如下面的代码就表示创建一个400x300的,全屏、默认为隐藏的pygame窗口。
pg.display.set_mode((400, 300), pg.FULLSCREEN | pg.HIDDEN)
pg.SCALED标志很有用。当你希望用户能够自由调节窗口的大小,并且窗口中的内容随着该大小进行变化,可以同时传递pg.SCALED|pg.RESIZABLE。
接下来的几个参数并不常用,新手无需了解它们。
depth指定颜色的深度。
vsync设置为True可以使画面垂直同步。当绘制的内容比较多时,可能会出现屏幕撕裂的现象,此时可以设置vsync=True来避免这一点(会影响帧速率)。
display指定默认的显示索引。
创建窗口后,如果不想在代码中一直引用窗口变量,可以使用pg.display.get_surface方法。这个方法返回当前建立的pygame窗口。
screen = pg.display.get_surface()
13.2 设置标题和图标
pg.display.set_caption方法用于设置窗口的标题,默认的标题是"pygame display window"
pg.display.set_icon方法设置窗口的图标,参数必须是一个Surface对象。
pg.display.set_caption(title) -> None
pg.display.set_icon(Surface) -> None
13.3 display模块索引-显示窗口
set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface
创建窗口
get_surface() -> Surface
获取窗口表面
flip() -> None
刷新窗口表面
update(rectangle=None) -> None
update(rectangle_list) -> None
刷新窗口表面(是flip的优化版本,但是速度可能较慢)
get_desktop_sizes() -> list
返回一个形如[(width, height), ...]的列表,每个元组表示电脑显示器的尺寸。
get_window_size() -> tuple
返回通过set_mode设置的窗口尺寸
gl_get_attribute(flag) -> value
获取OpenGL模式中的属性。
gl_set_attribute(flag, value) -> None
设置OpenGL模式中的属性,后文详解
get_active() -> bool
返回一个布尔值表示窗口是否处于激活
iconify() -> bool
最小化窗口
set_icon(Surface) -> None
设置窗口图标
set_caption(title, icontitle=None) -> None
设置窗口标题(icontitle参数在pygame2中无效)
get_caption() -> (title, icontitle)
返回窗口标题
set_allow_screensaver(bool=True) -> None
设置游戏运行时是否支持显示屏幕保护系统,调用时默认为支持。不进行设置时,默认不支持在游戏时显示屏保。
get_allow_screensaver() -> bool
返回一个布尔值,表示是否在游戏时显示屏保。
message_box(title, message=None, message_type='info', parent_window=None, buttons=('OK',), return_button=0, escape_button=None) -> int
创建一个消息框(pygame-ce 2.4.0新增)。
title表示消息框标题字符串,message表示消息框的提示内容字符串。
message_type是消息框的类型,可以是"info","warn","error",分别对应三种不同的提示图标。
buttons参数表示消息框下方一系列按钮名称的列表。
这个函数会阻塞当前的pygame窗口,直到用户点击消息框下方按钮后退出消息框。这个函数返回一个整数,表示用户选择按钮的索引,如上方消息框选择"I agree."将会返回0,"I don't agree"将会返回1。
此外还有两个参数,return_button和escape_button。
return_button是一个默认为0的整数值,表示默认选中的按钮索引。默认选中的按钮在消息框打开时会被激活,如果此时用户直接按下Enter键,就会选中那个激活的按钮选项。
escape_button默认为None。如果将它设置为一个按钮索引的整数值,则在消息框窗口右上方会添加一个"X"关闭按钮,点击这个关闭按钮或者按下ESC键会退出这个消息框,同时返回escape_button指定的按钮索引值。
14 声音
参考资料:pygame.mixer — pygame-ce v2.3.1 documentation
14.1 设定混音器
pg.mixer模块可以用于播放声音。pg.mixer.pre_init方法可以预先设定所有的声音参数,达到控制声音播放效果的功能。
pg.mixer.pre_init(frequency=44100, size=-16, channels=2, buffer=512, devicename=None, allowedchanges=pg.AUDIO_ALLOW_FREQUENCY_CHANGE | pg.AUDIO_ALLOW_CHANNELS_CHANGE) -> None
一般在初始化pygame模块后直接调用pre_init()。调用这个方法后,声音效果会好一些,比如音量过大的声音会被减小音量。
14.2 播放音效
pg.mixer中有一个Sound对象,可以用于播放音效。播放音效首先需要创建一个Sound对象。Sound支持的参数类型很多,可以是某个声音文件路径,也可以是声音的样本数据等等。
mixer支持的声音文件类型有:
-
MP3
-
OGG
-
WAV
在创建了一个声音对象后,可以Sound.play方法播放声音。play方法的第一个参数loops指定第一次播放后再次重复播放的次数,-1则为无限次播放,默认为0。
停止播放音效可使用Sound.stop方法。此外还有一个fadeout方法,可以淡出音频,支持一个参数表示淡出时间(ms);如果Sound.fadeout(2000),那么声音将在2秒内变得越来越弱最后消失。
示例如下:
import pygame as pg
pg.init()
pg.mixer.pre_init()
sound = pg.mixer.Sound("click.ogg") #音效文件
sound.play() #播放音效
while True: #play方法是非阻塞的,如果不放这个循环,程序会直接结束
pass
14.3 播放背景音乐
pg.mixer还有一个子模块music,用于控制背景音乐。背景音乐和音效差不多,但是背景音乐只能同时播放一个。
播放背景音乐首先需要进行载入。pg.mixer.music.load方法通过一个文件路径载入声音,然后通过pg.mixer.music.play播放。
import pygame as pg
pg.init()
pg.mixer.pre_init()
pg.mixer.music.load("bgm.ogg")
pg.mixer.music.play(-1) #循环播放背景音乐(-1即无限次)
while True:
pass
如果想要更换音乐,只需要重新载入新的背景音乐,然后调用play进行播放即可。
14.4 mixer模块索引-混音器
混音器(mixer)是一个管理声音的模块。每段声音将会被分配到各个声道(channel),混音器对各个声道进行混合形成最终播放的声音。声道的默认数量是8,这意味着默认情况下只能同时混合8个声音。多余的声音将被丢弃。
pre_init(frequency=44100, size=-16, channels=2, buffer=512, devicename=None, allowedchanges=AUDIO_ALLOW_FREQUENCY_CHANGE | AUDIO_ALLOW_CHANNELS_CHANGE) -> None
预先设置混音器。buffer参数控制混音器的采样数量,这意味着如果buffer比较高,那么声音丢失可能性就偏低,但速度可能稍慢。
stop() -> None, pause() -> None, unpause() -> None, fadeout(time) -> None
这几个函数和Channel对象的几个方法作用类似,但是可以作用于所有声道(Channel对象),关于Channel详见下文。
set_num_channels(count) -> None
设置声道数量,默认声道数量为8。
get_num_channels() -> count
返回声道数量。
set_reserved(count) -> count
设置预留声道,count表示需要预留的声道数量。一般播放声音(调用play())时会自动选择一个可用的声道,如果设置了预留则无法被play()选中。这样可以给一些重要的声音预留一些通道,保证不被占用。
返回实际的预留声道数量。如果之前的声道已经被占用了一部分,而剩余的可用声道数量小于给定参数count,那么则无法按照参数预留声道,只会预留剩余的可用声道。比如:一共8个声道,5个已经被占用,而希望预留4个声道,那么实际只会预留剩余的3个声道。
get_busy() -> bool
如果混音器处于忙碌(正在播放音效),返回True。
set_soundfont(path) -> None
这将设置用于播放midi音乐的soundfont文件。soundfont只影响MID、MIDI和KAR文件格式的播放。可选的path参数,一个字符串(或由分号分隔的多个字符串),必须指向要搜索的soundfont文件(如果缺少某些文件,则按给定的顺序)。如果path是空字符串或默认值(None),则将从混音器中清除任何指定的soundfont路径。
注意在Windows上,混音器总是使用内置的声音字体而不是指定的。
pygame 2.3.1新增。
get_soundfont() -> paths
这将获得soundfont文件路径作为字符串(每个路径由分号分隔),以便在播放MID、MIDI和KAR音乐文件格式时使用。如果未指定soundfont,则返回类型为None。
Sound(filename) -> Sound
Sound(file=filename) -> Sound
Sound(file=pathlib_path) -> Sound
Sound(buffer) -> Sound
Sound(buffer=buffer) -> Sound
Sound(object) -> Sound
Sound(file=object) -> Sound
Sound(array=object) -> Sound
创建音效对象。
Sound.play(loops=0, maxtime=0, fade_ms=0) -> Channel
播放音效,返回该音效播放的声道。loops表示第一次播放后,重复播放的次数;设为5则一共播放6次;无限次播放可设为-1。maxtime指定音效播放的最大时间,经过给定毫秒后停止播放声音。fade_ms表示淡入声音的时间,淡入表示开始播放时声音由最小逐渐变大。
Sound.stop() -> None
暂停音效的播放。
Sound.fadeout(time) -> None
暂停音效的播放(淡出)。淡出时声音逐渐变弱最后消失,淡出时间为给定参数time。
Sound.set_volume(value) -> None
设置音量,value范围是0-1之间的浮点数。
Sound.get_volume() -> value
返回当前音量
Sound.get_num_channels() -> count
返回一个整数表示这个音效在多少个声道被播放。
Sound.get_length() -> seconds
返回声音的长度(秒)。
Sound.get_raw() -> bytes
返回声音的原始字节码
Channel(id) -> Channel
创建一个声道对象,id是声道的标识符。
Channel.id -> int
返回声道的标识符(2.4.0新增)
Channel.play(Sound, loops=0, maxtime=0, fade_ms=0) -> None
在当前声道播放音效
Channel.stop() -> None
停止播放音效
Channel.pause() -> None
暂停播放音效
Channel.unpause() -> None
取消暂停播放音效
Channel.fadeout(time) -> None
停止播放音效(淡出)
Channel.set_volume(value) -> None
Channel.set_volume(left, right) -> None
设置音量。如果传递两个参数,则表示混音器立体声模式,左边的扬声器音量为left,右边的为right。
Channel.get_volume() -> value
返回音量
Channel.get_busy() -> bool
返回声道是否在混音中
Channel.get_sound() -> Sound
返回当前声道的音效对象
Channel.queue(Sound) -> None
排队某个音效。排队的音效将在当前音效播放完后直接开始播放。排队的音效只能有一个。
Channel.set_endevent() -> None
Channel.set_endevent(type) -> None
当声音全部播放结束后将type事件类型发送。
Channel.get_endevent() -> type
获取声音播放完成后发送的事件类型
14.4 mixer.music模块索引-背景音乐
music模块单独管理一个声道,只允许播放一个声音。
load(filename) -> None
load(fileobj, namehint="") -> None
载入声音文件。
unload() -> None
卸载声音文件
play(loops=0, start=0.0, fade_ms=0) -> None
播放声音。start表示开始播放声音的位置,取决于声音文件的类型;MP3和OGG文件中start单位为秒(MP3声音位置控制可能不精准),MOD文件中start表示整数模式数,其他格式文件不支持控制声音播放的位置。
rewind() -> None
将播放音乐位置重置为0。如果先前暂停了音乐,此时仍然处于暂停状态。
stop() -> None
停止播放音乐
pause() -> None
暂停播放音乐
unpause() -> None
取消暂停播放音乐
fadeout(time) -> None
停止播放音乐(淡出)。
set_volume(volume) -> None
设置音量
get_volume() -> value
获取音量
get_busy() -> bool
返回是否在播放背景音乐
set_pos(pos) -> None
设置音乐的播放位置
get_pos() -> time
获取音乐的播放位置
queue(filename) -> None
queue(fileobj, namehint="", loops=0) -> None
排队下一个音乐
set_endevent() -> None
set_endevent(type) -> None
播放结束时发送类型为type的事件
get_endevent() -> type
获取播放结束时发送的事件类型。
15 坐标处理
参考资料:
pygame.Rect — pygame-ce v2.3.1 documentation
pygame.math — pygame-ce v2.3.1 documentation
pygame.math — pygame-ce v2.3.1 documentation
15.1 矩形
pg.Rect创建一个矩形对象,用于操作矩形区域。前文已经介绍过矩形对象,它具有以下虚拟属性:
x,y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h
矩形对象是可以迭代的,如下:
r = Rect(0, 1, 2, 3)
x, y, w, h = r #位置和尺寸
Surface.get_rect方法返回表面的矩形对象。这个矩形对象中x=y=0,且w, h=表面的宽,表面的高。
15.2 Rect对象方法索引
copy() -> Rect
复制矩形
update(left, top, width, height) -> None
update((left, top), (width, height)) -> None
update(object) -> None
更改矩形信息
move(x, y) -> Rect, move_ip(x, y) -> None
move方法用于移动矩形(x, y坐标分别增加x, y个像素),返回新的矩形对象。move_ip方法中的ip表示in-place,表示原地修改矩形(在调用该方法的矩形对象上修改),而不是复制一个矩形对象,修改后返回。以下很多方法都支持_ip,不再赘述。
inflate(x, y) -> Rect, inflate_ip(x, y) -> None
将矩形对象的宽、高分别增加x, y个像素,并使更改后的矩形对象中心位置移动到原来矩形对象的中心位置。
粉色为原本的矩形,绿色是调用rect.inflate(50, 50)后的结果。
clamp(Rect) -> Rect, clamp_ip(Rect) -> None
将当前矩形的中心设为指定参数中Rect对象的中心。
上图中粉色为调用方法的矩形,红色为参数中的矩形,绿色为调用后的结果。
union(Rect) -> Rect, union_ip(Rect) -> None
获取两个矩形包围部分。矩形的包围部分覆盖了所有矩形的面积(可能有原始矩形中未覆盖的区域)
如图,绿色矩形为粉色和红色矩形的包围区域。
unionall(Rect_sequence) -> Rect, unionall_ip(Rect_sequence) -> None
获取多个矩形的包围区域。Rect_sequence是一个矩形序列,包含一系列矩形对象。
scale_by(scale_by) -> Rect, scale_by_ip(scale_by) -> None
scale_by(x, y) -> Rect, scale_by_ip(x, y) -> None
按比例缩放矩形,缩放后矩形仍然位于原先矩形的中心。如果只提供一个参数,则缩放整个矩形,如果提供两个参数,表示分别对宽和高进行不同的缩放。
pygame-ce 2.3.1新增
clip(Rect) -> Rect
返回两个矩形的重叠部分的矩形对象。
上图中绿色的矩形表示粉色矩形、红色矩形的重叠部分。
clipline(x1, y1, x2, y2) -> ((cx1, cy1), (cx2, cy2)) or ()
clipline((x1, y1), (x2, y2)) -> ((cx1, cy1), (cx2, cy2)) or ()
clipline((x1, y1, x2, y2)) -> ((cx1, cy1), (cx2, cy2)) or ()
clipline(((x1, y1), (x2, y2))) -> ((cx1, cy1), (cx2, cy2)) or ()
矩形和线段的碰撞检测。(x1, y1), (x2, y2)表示线段的两个端点,如果发生碰撞,则返回线段在矩形中的部分的两个端点。
如图,红色部分为原来的线段,绿色部分为该线段与粉色矩形发生碰撞的部分。(为了方便观察,红色线段边框绘制较粗)。
fit(Rect) -> Rect
移动并调整矩形的大小,使其适应给定矩形的范围,并返回调整后的结果(一个矩形对象)。调整后的矩形宽高之比不变,但是它被尽可能地放大,使其完全容纳于给定矩形的范围中(如果给定参数的矩形要比当前矩形小,那么矩形将会被缩小,使得大小刚好容纳在给定矩形之中)。调整后的矩形中心被移动到给定矩形的中心。
粉色是调用该方法的矩形,红色是给定矩形,绿色是调用fit后的结果。
normalize() -> None
如果当前矩形中宽或高为负数,则修改为正数,并移动x, y坐标使当前位置不变。示例如下:
>>> r = pg.Rect((150, 150, -100, -100))
>>> print(r)
<rect(150, 150, -100, -100)>
>>> r.normalize()
>>> print(r)
<rect(50, 50, 100, 100)>
>>>
contains(Rect) -> bool
如果给定矩形的范围完全在当前矩形的范围之内,则返回True。
collidepoint(x, y) -> bool
collidepoint((x,y)) -> bool
如果位于(x, y)的点在矩形范围之内,则返回True
colliderect(Rect) -> bool
如果两个矩形有重合的部分,则返回True
collidelist(list) -> index
测试矩形是否与一系列矩形碰撞。返回第一个找到的碰撞的索引。如果没有,则返回索引-1。
collidelistall(list) -> indices
返回一个包含与矩形碰撞的矩形的所有索引的列表。如果没有找到碰撞的矩形,则返回一个空列表。
list中可以包含Rect对象、可传递给Rect对象的参数(如(0, 0, 100, 100));也可以包含一个其他对象,但其中必须有一个名为rect的属性。
注意:collidelistall看似要比collidelist好用,其实二者各有优势。collidelistall返回碰撞的所有对象,这必然会大大降低代码的运行速度。如果只是要检测是否碰撞,而不在乎碰撞的数量,使用collidelist要更好。
collideobjects(rect_list) -> object
collideobjects(obj_list, key=func) -> object
可以传递一个矩形列表,它将返回第一个找到的与当前矩形发生碰撞的矩形对象。
也可以传递一系列其他对象的列表;此时需要指定key(一个函数),它包含一个参数表示即将进行检测的列表中的对象,必须返回一个Rect对象。此时将返回第一个找到的与当前矩形发生碰撞的其他对象。示例如下:
>>> r = pg.Rect((0, 0, 100, 100))
>>> class ObjectWithSomeRectAttr:
def __init__(self, box):
self.collision_box = pg.Rect(box)
>>> objects = [
ObjectWithSomeRectAttr((300, 400, 500, 500)), #No collide
ObjectWithSomeRectAttr((200, 900, 100, 100)), #No collide
ObjectWithSomeRectAttr((99, 99, 100, 100)), #Collide!
]
>>> def key_func(obj):
return obj.collision_box #返回将要与矩形进行碰撞检测的矩形
>>> obj = r.collideobjects(objects, key=key_func)
>>> print(obj.collision_box)
<rect(99, 99, 100, 100)>
>>>
collideobjectsall(rect_list) -> objects
collideobjectsall(obj_list, key=func) -> objects
与collideobjects类似,但是返回的不是第一个找到的对象而是所有发生碰撞的对象。
collidedict(dict) -> (key, value) or None
collidedict(dict, use_values=0) -> (key, value) or None
接受一个字典进行碰撞检测,并返回第一个找到的发生碰撞的键值对。如果use_values=0(默认),则使用字典的键与当前矩形进行碰撞检测,设为1则使用字典的值与当前矩形进行碰撞检测。
注意:pg.Rect对象不可散列,所以不能作为字典的键。作为字典的键之前应转换为元组。如下所示:
rect.collidedictall({tuple(key_rect) : value})
collidedictall(dict) -> [(key, value), ...]
collidedictall(dict, use_values=0) -> [(key, value), ...]
与collidedict类似,但是返回的不是第一个找到的对象而是所有发生碰撞的对象。
15.3 FRect - 支持浮点运算的矩形
版本为2.2.1的pygame-ce中新增了FRect类,其用法与Rect相同,但是可支持浮点数的运算,这在很多时候都是有用的。
>>> r = pg.FRect(1.3, 1.5, 2, 5)
>>> r
FRect(1.300000, 1.500000, 2.000000, 5.000000)
>>> r = pg.Rect(1.3, 1.5, 2, 5)
>>> r
Rect(1, 1, 2, 5)
>>>
Surface.get_frect可以返回一个FRect对象,用法与get_rect类似。
15.4 向量
pygame中支持向量。向量指具有大小和方向的量,你可以把它理解为一个(x, y)形式的元组,但是被封装成一个类,具有一系列强大的功能。
pygame中支持的向量有二维和三维两种,分别作为两个类:Vector2和Vector3。它们被放在pygame的数学库(pg.math)中,由于比较常用,它们也被导入到了主模块中,所以只需pg.Vector2即可调用。
下面介绍二维向量,它由Vector2方法创建:
pg.Vector2() -> Vector2(0, 0)
pg.Vector2(int) -> Vector2
pg.Vector2(float) -> Vector2
pg.Vector2(Vector2) -> Vector2
pg.Vector2(x, y) -> Vector2
pg.Vector2((x, y)) -> Vector2
如果说Rect对象表示了一个面,那么向量对象表示的则是一个点或是一段距离。向量对象支持一系列数学运算,包括加减乘除和圆整(__round__,pygame-ce 2.1.4新增)。和Rect还有一个不同,向量对象支持小数,而Rect只支持整数(这是因为Rect对象表示的是一个完整的位置,像素只能为整数;而向量是为了精确的数学运算设计的)。
>>> vec = pg.Vector2(10, 10)
>>> vec2 = pg.Vector2(5, 5)
>>> vec + vec2
<Vector2(15, 15)>
>>> vec - vec2
<Vector2(5, 5)>
>>> vec - 3 * vec2
<Vector2(-5, -5)>
>>> vec // 3
<Vector2(3, 3)>
>>> vec += pg.Vector2(3.14, 3.1415)
>>> vec
<Vector2(13.14, 13.1415)>
>>> round(vec, 1)
<Vector2(13.1, 13.1)>
>>>
向量的引用和修改也很简单,只需要通过向量的x, y, z(仅Vector3支持z轴)属性或索引即可。
>>> vec = pg.Vector2(1, 2)
>>> vec.x = 4
>>> vec
<Vector2(4, 2)>
>>> vec.y = 8
>>> vec
<Vector2(4, 8)>
>>> vec.x, vec.y
(4.0, 8.0)
>>> vec[0], vec[1]
(4.0, 8.0)
>>>
向量对象还支持一种奇怪的属性引用方式,可以将x, y, z组合作为向量的属性。
>>> vec = pg.Vector2(1, 2)
>>> vec.xy
<Vector2(1, 2)>
>>> vec.yx
<Vector2(2, 1)>
>>> vec.xyx
<Vector3(1, 2, 1)>
>>> vec.xyxyxyxyxyxy
(1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0)
>>> vec.yyyyy
(2.0, 2.0, 2.0, 2.0, 2.0)
>>> vec.xy = (2, 3)
>>> vec.xyx = (2, 3, 2) #这样的赋值方式是不支持的
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
vec.xyx = (2, 3, 2)
AttributeError: Attribute assignment conflicts with swizzling.
>>>
向量有一个特殊之处。渲染pygame时y坐标轴是向下的,但是向量计算中一般y坐标轴向上
15.5 Vector2对象方法索引-2D向量
copy() -> Vector2
复制向量对象。
update() -> None
update(int) -> None
update(float) -> None
update(Vector2) -> None
update(x, y) -> None
update((x, y)) -> None
更新向量对象的值。
dot(Vector2) -> float
返回两个向量的点乘结果。
公式:
cross(Vector2) -> float
返回两个向量的叉乘结果
公式:
length() -> float
返回向量距离原点(0, 0)的长度。
length_squared() -> float
返回向量距离原点的长度的平方(速度比length稍快,因为最后一步不需要开方)
normalize() -> Vector2, normalize_ip() -> None
修改向量使方向不变,长度为1。normalize_ip表示原地修改,而不是返回一个新向量。
is_normalized() -> Bool
判断向量的长度是否为1
scale_to_length(float) -> None
缩放向量,使其长度为float。
reflect(Vector2) -> Vector2, reflect_ip(Vector2) -> None
通过给定的向量作为法线,计算反射后向量的值。反射后向量长度不变。reflect_ip表示原地修改,而不是返回一个新向量。
distance_to(Vector2) -> float
返回两个向量之间的距离
distance_squared_to(Vector2) -> float
返回两个向量之间的距离的平方
move_towards(Vector2, float) -> Vector2, move_towards_ip(Vector2, float) -> None
使当前向量朝着指定向量Vector2的位置移动float的长度,移动的距离不超过当前向量和指定向量的距离。如果float为负数,则朝着指定向量Vector2的方向远离。
lerp(Vector2, float) -> Vector2
返回两个向量的线性插值,float范围是0-1。如float为0时,返回原本的向量;1时返回指定向量;0.5返回两个向量的角平分线;0.33或0.66返回的向量夹角三分线,分别靠近原本向量和指定向量。
slerp(Vector2, float) -> Vector2
返回两个向量的球面插值。
rotate(angle) -> Vector2, rotate_ip(angle) -> None
按角度逆时针旋转向量(由于pygame的坐标系的y轴向下,所以显示时为顺时针旋转)
rotate_rad(angle) -> Vector2, rotate_rad_ip(angle) -> None
按弧度逆时针旋转向量(由于pygame的坐标系的y轴向下,所以显示时为顺时针旋转)
angle_to(Vector2) -> float
返回当前向量旋转到指定向量的方向的角度。该计算的旋转不会越过负x轴。
as_polar() -> (r, phi)
返回一个元组,包含向量的长度和方位角(由x轴正方向顺时针旋转至当前向量的角度)
from_polar((r, phi)) -> None
设置向量的长度和方位角。
project(Vector2) -> Vector2
将当前向量投射到指定向量。
如图是向量a投射到向量CD的结果(向量b)。这对于在特定方向(例如墙的方向)找到某个部分的碰撞检测是很有用的。
epsilon -> 1e-6
向量比较或计算的容差。由于浮点数计算中可能会有误差,所以可以通过设置epsilon属性来指定一个偏差的值,在一定误差内比较向量的大小或进行一些计算。值不要设置过大,比如设置为0.5就是一个过大的值,会影响计算。
15.6 Vector3对象方法索引-3D向量
Vector3是三维向量,可以处理三维图形的坐标。它的大部分方法与Vector2一致,只是所需Vector2作为参数改成了Vector3,此处不再赘述,此外它还包括一些别的方法:
rotate_x(angle) -> Vector3, rotate_x_ip(angle) -> None
围绕x轴按角度逆时针旋转向量(由于pygame的坐标系的y轴向下,所以显示时为顺时针旋转)
rotate_x_rad(angle) -> Vector3, rotate_x_rad_ip(angle) -> None
围绕x轴按弧度逆时针旋转向量(由于pygame的坐标系的y轴向下,所以显示时为顺时针旋转)
此外还有rotate_y, rotate_z等一系列方法,此处不再赘述。
as_spherical() -> (r, theta, phi)
from_spherical((r, theta, phi)) -> None
这两个方法相当于Vector2.as_polar和from_polar,但是这两个方法作用于三维,其中r是径向距离,theta是倾角,phi是方位角。
15.7 其他几何图形对象
pygame-ce 2.4.0新增了geometry模块,这是一个实验性模块,尚未完工。其中包含Circle, Line, Polygon几个对象,和Rect对象某些用法有些类似,不过作用于不同的几何图形。
16 数学库
参考资料:pygame.math — pygame-ce v2.3.1 documentation
16.1 限制数值范围
pg.math库包含了一些数学操作。math库中的clamp()函数用于限制一个数值的范围。
pg.math.clamp(value, min, max) -> float
min表示最小值,max表示最大值。如果value小于min,则返回min;如果value大于max,则返回max;否则返回value。例如:
>>> pg.math.clamp(10, 100, 200) #把数值限制在100-200之间
100
>>> pg.math.clamp(130, 100, 200)
130
>>> pg.math.clamp(999, 100, 200)
200
>>>
16.2 插值
pygame-ce 2.4.0在math库中新增了两个插值方法,包括线性插值和平滑插值。
pg.math.lerp用于线性插值。
pg.math.lerp(a, b, value, do_clamp=True, /) -> float
这个函数将根据value返回a和b之间的线性插值。如果do_clamp设为True,则value的数值会被限定在0-1之间。
线性插值公式为:
示例如下:
>>> pg.math.lerp(10, 20, 0.2)
12.0
>>> pg.math.lerp(0, 10, 0.8)
8.0
smoothstep用于平滑插值。平滑插值按照一条S形曲线,在value较小和较大的时候变化较小,value适中的时候变化较大。
pygame 2.5.0中新增了pg.math.invlerp方法,这个方法和lerp方法作用相反。lerp函数返回一个插值后的结果,invlerp方法根据一个值返回插值位置的浮点值。
>>> pg.math.invlerp(10, 20, 12)
0.2
>>> pg.math.invlerp(0, 10, 8)
0.8
pygame 2.5.0还新增了pg.math.remap方法,用于将给定的一个数值从一个范围中映射到另一个范围。
pg.math.remap(i_min, i_max, o_min, o_max, value, /) -> float
相当于:
def remap(i_min, i_max, o_min, o_max, value):
pos = pg.math.invlerp(i_min, i_max, value)
return pg.math.lerp(o_min, o_max, pos)
例如:
>>> pg.math.remap(0, 10, 0, 100, 2)
20.0
>>> pg.math.remap(0, 10, 0, 1000, 2)
200.0