当前位置:   article > 正文

Python pygame(GUI编程)模块最完整教程(5)_pygame gui

pygame gui

上一篇文章: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方法用于创建窗口。

  1. pg.display.set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface

size参数指定窗口的大小,一般是一个元组(宽, 高)。如果设为(0, 0),那么窗口将和电脑屏幕一样大。如果将宽度设为0或高度设为0,那么窗口的宽度或高度和电脑屏幕一样。

flags指定窗口的额外参数,参数之间用按位或运算符"|"组合。额外参数有:

参数

解释

FULLSCREEN

使窗口全屏显示

HWSURFACEFULLSCREEN模式下启动硬件加速

DOUBLEBUF

双缓冲模式,仅在OPENGL模式下生效,作用是缓冲绘制的内容,避免卡顿

OPENGL

创建一个OpenGL渲染显示(OpenGL是一个3D绘图引擎)

RESIZABLE

窗口允许用户改变大小

NOFRAME

隐藏窗口边框和标题栏

SCALED

使窗口大小适配分辨率高的显示器,在分辨率较高的显示器上不会显得特别小

SHOWN

窗口以显示模式打开(默认)

HIDDEN

窗口以隐藏模式打开

比如下面的代码就表示创建一个400x300的,全屏、默认为隐藏的pygame窗口。

  1. 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窗口。

  1. screen = pg.display.get_surface()

13.2 设置标题和图标

pg.display.set_caption方法用于设置窗口的标题,默认的标题是"pygame display window"

pg.display.set_icon方法设置窗口的图标,参数必须是一个Surface对象。

  1. pg.display.set_caption(title) -> None
  2. 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",分别对应三种不同的提示图标。

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方法可以预先设定所有的声音参数,达到控制声音播放效果的功能。

  1. 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秒内变得越来越弱最后消失。

示例如下:

  1. import pygame as pg
  2. pg.init()
  3. pg.mixer.pre_init()
  4. sound = pg.mixer.Sound("click.ogg") #音效文件
  5. sound.play() #播放音效
  6. while True: #play方法是非阻塞的,如果不放这个循环,程序会直接结束
  7. pass

14.3 播放背景音乐

pg.mixer还有一个子模块music,用于控制背景音乐。背景音乐和音效差不多,但是背景音乐只能同时播放一个。

播放背景音乐首先需要进行载入。pg.mixer.music.load方法通过一个文件路径载入声音,然后通过pg.mixer.music.play播放。

  1. import pygame as pg
  2. pg.init()
  3. pg.mixer.pre_init()
  4. pg.mixer.music.load("bgm.ogg")
  5. pg.mixer.music.play(-1) #循环播放背景音乐(-1即无限次)
  6. while True:
  7. 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

矩形对象是可以迭代的,如下:

  1. r = Rect(0, 1, 2, 3)
  2. 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坐标使当前位置不变。示例如下:

  1. >>> r = pg.Rect((150, 150, -100, -100))
  2. >>> print(r)
  3. <rect(150, 150, -100, -100)>
  4. >>> r.normalize()
  5. >>> print(r)
  6. <rect(50, 50, 100, 100)>
  7. >>>

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对象。此时将返回第一个找到的与当前矩形发生碰撞的其他对象。示例如下:

  1. >>> r = pg.Rect((0, 0, 100, 100))
  2. >>> class ObjectWithSomeRectAttr:
  3. def __init__(self, box):
  4. self.collision_box = pg.Rect(box)
  5. >>> objects = [
  6. ObjectWithSomeRectAttr((300, 400, 500, 500)), #No collide
  7. ObjectWithSomeRectAttr((200, 900, 100, 100)), #No collide
  8. ObjectWithSomeRectAttr((99, 99, 100, 100)), #Collide!
  9. ]
  10. >>> def key_func(obj):
  11. return obj.collision_box #返回将要与矩形进行碰撞检测的矩形
  12. >>> obj = r.collideobjects(objects, key=key_func)
  13. >>> print(obj.collision_box)
  14. <rect(99, 99, 100, 100)>
  15. >>>

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对象不可散列,所以不能作为字典的键。作为字典的键之前应转换为元组。如下所示:
  1. 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相同,但是可支持浮点数的运算,这在很多时候都是有用的。

  1. >>> r = pg.FRect(1.3, 1.5, 2, 5)
  2. >>> r
  3. FRect(1.300000, 1.500000, 2.000000, 5.000000)
  4. >>> r = pg.Rect(1.3, 1.5, 2, 5)
  5. >>> r
  6. Rect(1, 1, 2, 5)
  7. >>>

Surface.get_frect可以返回一个FRect对象,用法与get_rect类似。

15.4 向量

pygame中支持向量。向量指具有大小和方向的量,你可以把它理解为一个(x, y)形式的元组,但是被封装成一个类,具有一系列强大的功能。

pygame中支持的向量有二维和三维两种,分别作为两个类:Vector2和Vector3。它们被放在pygame的数学库(pg.math)中,由于比较常用,它们也被导入到了主模块中,所以只需pg.Vector2即可调用。

下面介绍二维向量,它由Vector2方法创建:

  1. pg.Vector2() -> Vector2(0, 0)
  2. pg.Vector2(int) -> Vector2
  3. pg.Vector2(float) -> Vector2
  4. pg.Vector2(Vector2) -> Vector2
  5. pg.Vector2(x, y) -> Vector2
  6. pg.Vector2((x, y)) -> Vector2

如果说Rect对象表示了一个面,那么向量对象表示的则是一个点或是一段距离。向量对象支持一系列数学运算,包括加减乘除和圆整(__round__,pygame-ce 2.1.4新增)。和Rect还有一个不同,向量对象支持小数,而Rect只支持整数(这是因为Rect对象表示的是一个完整的位置,像素只能为整数;而向量是为了精确的数学运算设计的)。

  1. >>> vec = pg.Vector2(10, 10)
  2. >>> vec2 = pg.Vector2(5, 5)
  3. >>> vec + vec2
  4. <Vector2(15, 15)>
  5. >>> vec - vec2
  6. <Vector2(5, 5)>
  7. >>> vec - 3 * vec2
  8. <Vector2(-5, -5)>
  9. >>> vec // 3
  10. <Vector2(3, 3)>
  11. >>> vec += pg.Vector2(3.14, 3.1415)
  12. >>> vec
  13. <Vector2(13.14, 13.1415)>
  14. >>> round(vec, 1)
  15. <Vector2(13.1, 13.1)>
  16. >>>

向量的引用和修改也很简单,只需要通过向量的x, y, z(仅Vector3支持z轴)属性或索引即可。

  1. >>> vec = pg.Vector2(1, 2)
  2. >>> vec.x = 4
  3. >>> vec
  4. <Vector2(4, 2)>
  5. >>> vec.y = 8
  6. >>> vec
  7. <Vector2(4, 8)>
  8. >>> vec.x, vec.y
  9. (4.0, 8.0)
  10. >>> vec[0], vec[1]
  11. (4.0, 8.0)
  12. >>>

向量对象还支持一种奇怪的属性引用方式,可以将x, y, z组合作为向量的属性。

  1. >>> vec = pg.Vector2(1, 2)
  2. >>> vec.xy
  3. <Vector2(1, 2)>
  4. >>> vec.yx
  5. <Vector2(2, 1)>
  6. >>> vec.xyx
  7. <Vector3(1, 2, 1)>
  8. >>> vec.xyxyxyxyxyxy
  9. (1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 2.0)
  10. >>> vec.yyyyy
  11. (2.0, 2.0, 2.0, 2.0, 2.0)
  12. >>> vec.xy = (2, 3)
  13. >>> vec.xyx = (2, 3, 2) #这样的赋值方式是不支持的
  14. Traceback (most recent call last):
  15. File "<pyshell#42>", line 1, in <module>
  16. vec.xyx = (2, 3, 2)
  17. AttributeError: Attribute assignment conflicts with swizzling.
  18. >>>

向量有一个特殊之处。渲染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()函数用于限制一个数值的范围。

  1. pg.math.clamp(value, min, max) -> float

min表示最小值,max表示最大值。如果value小于min,则返回min;如果value大于max,则返回max;否则返回value。例如:

  1. >>> pg.math.clamp(10, 100, 200) #把数值限制在100-200之间
  2. 100
  3. >>> pg.math.clamp(130, 100, 200)
  4. 130
  5. >>> pg.math.clamp(999, 100, 200)
  6. 200
  7. >>>

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之间。

线性插值公式为:result = a+(b-a)\times value

示例如下:

  1. >>> pg.math.lerp(10, 20, 0.2)
  2. 12.0
  3. >>> pg.math.lerp(0, 10, 0.8)
  4. 8.0

smoothstep用于平滑插值。平滑插值按照一条S形曲线,在value较小和较大的时候变化较小,value适中的时候变化较大。

此外,math模块中还包含上一章介绍过的Vector2和Vector3,这里不再赘述。

下一篇文章

Python pygame(GUI编程)模块最完整教程(6)_Python-ZZY的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/471979
推荐阅读
相关标签
  

闽ICP备14008679号