URLhttps://learnscript.net/zh/pygame/font/
    复制链接转到说明  示例

    如何查找和加载游戏字体?以及获取和设置字体样式等问题

    我被代码海扁署名-非商业-禁演绎
    阅读 24:12·字数 7264·更新 

    虽然本节的示例中包含绘制文本的代码,但本节不会讲解与文本绘制相关的问题,要了解文本绘制,请查看在表面中绘制图像和文本(字体)一段。

    Pygame 中的 font 模块

    Pygame 包的font模块,包含了与字体相关的功能,主要涉及字体的加载(获取),以及字体的绘制(本节内容不涉及此部分),当你导入pygame模块时,font模块会被pygame模块导入。

    初始化 font 模块

    pygame模块一样,font模块拥有用于初始化的函数init,该函数会在pygame模块的init函数中被调用,这意味着一旦使用pygame模块进行初始化,调用font模块的init函数将是没有必要的。

    init()

    可以重复调用 init 函数

    你可以反复调用init函数,这没有任何问题,即便在调用quit函数之后。

    font.py
    # 导入模块 font
    from pygame import font
    
    # 初始化 font.init()

    判断 font 模块是否已经初始化

    pygame模块一样,font模块拥有判断font模块是否已经初始化的函数get_init

    get_init()

    返回值

    如果get_init函数返回True,那么表示font模块已经进行了初始化。

    在调用 quit 函数之后,get_init 函数将返回 False

    在调用quit函数之后,get_init函数将返回False,这表示再次调用init函数将产生实际效果,他会重新初始化font模块。

    font.py
    # …
    print(f'font 已经初始化?{font.get_init()}')
    font 已经初始化?True

    取消初始化 font 模块

    pygame模块一样,font模块拥有用于取消初始化的函数quit,该函数会在pygame模块的quit函数中被调用,这意味着一旦使用pygame模块取消了初始化,调用font模块的quit函数将是没有必要的。

    quit()

    可以重复调用 quit 函数

    init函数一样,你可以反复调用quit函数,这没有任何的问题。

    获取所有可用字体的名称

    font模块的get_fonts函数,可用于获取所有可用的字体的名称。

    get_fonts()

    返回值

    get_fonts函数的返回值是一个 Python 字符串列表,每一个字符串对应一个字体名称。

    在 Pygame 2.1.3 以及之后的版本中,除了系统字体,函数get_fonts还会检索用户字体,对于 Windows 操作系统而言。

    get_fonts 函数会简化字体名称

    get_fonts函数会将字体名称改为小写,同时,对于字体名称中包含的空格或标点,get_fonts会尝试去除他们。

    font.py
    # …
    # 获取所有可用字体的名称
    print(font.get_fonts())
    ['arial', 'arialblack', 'bahnschrift', ]

    获取默认字体的文件名

    font模块的get_default_font函数,可用于获取 Pygame 默认字体的文件名称。

    get_default_font()

    返回值

    get_default_font函数的返回值是一个 Python 字符串,表示默认字体的文件名称(不是文件路径)。

    Pygame 包所使用的默认字体

    Pygame 包所使用的默认字体并非操作系统的默认字体,一般情况下,Pygame 的默认字体文件(freesansbold.ttf)所在的目录与pygame模块所在的目录相同,但默认字体文件也可能被捆绑在其他文件中。

    这里需要指出,即便 Pygame 包所使用的默认字体文件不存在,font模块的get_default_font函数还是会返回其名称。

    font.py
    # …
    # 获取默认字体的文件名称
    print(font.get_default_font())
    freesansbold.ttf

    获取指定字体的文件路径

    font模块的match_font函数,可用于获取最符合给出条件的字体的文件路径,当然,该函数所找到的字体可能并不完全符合你的要求。

    就像 CSS 的font-family一样,你可以为font模块的match_font函数指定多个字体名称,match_font将依次检索这些字体名称以及其他条件(粗体,斜体),当某个字体可用时,将返回该字体的文件路径。

    match_font(name, bold=False, italic=False)

    name 参数

    name参数可以是一个字符串,表示需要获取文件路径的字体的名称,多个字体名称使用,进行分隔。name参数也可以是包含多个字体名称的迭代器对象,比如包含多个字体名称的 Python 元组。

    如果你不知道应该如何书写字体名称,那么可以使用get_fonts函数来查看可用的字体名称有哪些,详情请参考获取所有可用字体的名称一段。

    bold 参数

    bold参数是一个布尔值,如果设置为True,那么将尝试获取粗体字体的文件路径。

    italic 参数

    italic参数是一个布尔值,如果设置为True,那么将尝试获取斜体字体的文件路径。

    返回值

    match_font函数将返回包含字体文件路径的字符串,如果未找到字体,则返回空值None

    在 Pygame 2.1.3 以及之后的版本中,除了系统字体,函数match_font还会检索用户字体,对于 Windows 操作系统而言。

    match_font 函数会简化字体名称

    match_font函数会将字体名称改为小写,如果name参数所表示的字体名称包含空格或标点符号(不包括英文,),那么match_font将尝试去除空格和标点符号。

    在下面的示例中,我们给出了两个字体名称,由于第一个字体tahoma有效,虽然只找到了粗体样式(没有找到粗斜体样式),因此,第二个字体不会被检测,第二个字体名称Sitka Text等同于sitkatext

    font.py
    # …
    # 获取字体文件的路径
    print(font.match_font('tahoma,Sitka Text', True, True))
    # Windows 中的输出结果
    C:\WINDOWS\Fonts\tahomabd.ttf

    为游戏加载字体

    font模块的Font类,可将指定的字体文件加载到游戏中,只需要在创建其实例时,指定字体文件的路径以及字体的大小。

    Font(name, size)

    name 参数

    name参数是表示字体文件路径的字符串,或包含字体文件路径的类路径(path-like)对象,或包含字体数据的IO对象。

    如果未设置参数name或该参数为空值None,那么 Pygame 将使用默认字体。如果字体文件不存在,那么将导致异常FileNotFoundError

    size 参数

    size参数是一个表示字体大小的 Python 整数,默认大小为12

    无法通过 Font 对象修改字体大小

    需要说明的是,一旦创建了Font类的实例,你将无法通过该实例修改字体的大小。

    在下面的示例中,我们首先使用match_font函数获取了字体Microsoft JhengHei的文件路径,然后根据该路径创建了一个Font对象,以将对应的字体载入到游戏中。

    load.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 获取字体文件的路径,并创建一个字体对象 path = font.match_font('Microsoft JhengHei') # 字体将采用默认大小 12 f = font.Font(path)
    # 创建游戏窗口,并使用字体对象 f 绘制文字 from pygame import display w = display.set_mode((800, 600))
    # 在游戏窗口中绘制文字 ts = f.render('你好!', False, [255, 255, 255]) w.blit(ts, [200, 200]) display.flip()
    # 等待 3 秒 import time time.sleep(3)

    获取和设置字体是否拥有粗体样式

    Font对象的get_boldset_bold方法,以及bold变量,可用于获取和设置游戏字体是否拥有粗体样式。

    如果 Pygame 所加载的字体文件本身为粗体样式,那么使用Font对象的set_bold方法或修改其bold变量,将不会产生任何效果,即你不能以非粗体样式来绘制粗体文本。如果 Pygame 所加载的字体文件本身为非粗体样式,那么也应尽量避免使用Font对象的set_bold方法或修改其bold变量,以粗体样式来绘制非粗体文本(因为这需要计算),实现粗体效果应首先考虑加载对应的粗体字体文件。

    get_bold()

    返回值

    如果get_bold返回True,则表示以粗体样式绘制文本。

    set_bold(value)

    value 参数

    value参数是一个布尔值,如果为True,则表示以粗体样式绘制文本。

    font.bold
    font.bold = bold

    bold 值

    bold是一个布尔值,如果为True,则表示以粗体样式绘制文本。

    在下面的示例中,我们加载了一个非粗体字体文件,通过修改bold变量,游戏中的文本将以粗体样式绘制。

    bold.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载一个非粗体字体文件,字体大小 24 f = font.Font(font.match_font('Microsoft JhengHei'), 24)
    # 修改为粗体样式 f.bold = True print(f'粗体?{f.get_bold()}')
    # 创建游戏窗口,并使用字体对象 f 绘制文字 from pygame import display w = display.set_mode((800, 600))
    # 在游戏窗口中绘制文字 ts = f.render('以粗体样式绘制', False, [255, 0, 0]) w.blit(ts, [50, 50]) display.flip()
    # 等待 3 秒 import time time.sleep(3)
    粗体?True

    获取和设置字体是否拥有斜体样式

    Font对象的get_italicset_italic方法,以及italic变量,可用于获取和设置游戏字体是否拥有斜体样式。

    如果 Pygame 所加载的字体文件本身为斜体样式,那么使用Font对象的set_italic方法或修改其italic变量,将不会产生任何效果,即你不能以非斜体样式来绘制斜体文本。如果 Pygame 所加载的字体文件本身为非斜体样式,那么也应尽量避免使用Font对象的set_italic方法或修改其italic变量,以斜体样式来绘制非斜体文本(因为这需要计算),实现斜体效果应首先考虑加载对应的斜体字体文件。

    get_italic()

    返回值

    如果get_italic返回True,则表示以斜体样式绘制文本。

    set_italic(value)

    value 参数

    value参数是一个布尔值,如果为True,则表示以斜体样式绘制文本。

    font.italic
    font.italic = italic

    italic 值

    italic是一个布尔值,如果为True,则表示以斜体样式绘制文本。

    在下面的示例中,我们加载了一个斜体字体文件,虽然尝试通过set_italic方法为字体取消斜体样式,但这不会产生任何效果。

    italic.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载一个斜体字体文件 f = font.Font(font.match_font('Arial', italic=True), 30)
    # 无法将斜体修改为非斜体 f.set_italic(False) print(f'斜体?{f.get_italic()}')
    # 创建游戏窗口,并使用字体对象 f 绘制文字 from pygame import display w = display.set_mode([800, 600])
    # 在游戏窗口中绘制文字 ts = f.render('Draw in italic style', True, (0, 255, 0)) w.blit(ts, (200, 200)) display.flip()
    # 等待 3 秒 import time time.sleep(3)
    斜体?True

    获取和设置字体是否拥有下划线样式

    Font对象的get_underlineset_underline方法,以及underline变量,可用于获取和设置游戏字体是否拥有下划线样式。

    get_underline()

    返回值

    如果get_underline返回True,则表示以下划线样式绘制文本。

    set_underline(value)

    value 参数

    value参数是一个布尔值,如果为True,则表示以下划线样式绘制文本。

    font.underline
    font.underline = underline

    underline 值

    underline是一个布尔值,如果为True,则表示以下划线样式绘制文本。

    underline.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载 Pygame 默认字体,字体大小 30 f = font.Font(size=30) # 修改为下划线样式 f.set_underline(True)
    # 创建游戏窗口,并使用字体对象 f 绘制文字 from pygame import display w = display.set_mode((800, 600))
    # 在游戏窗口中绘制文字 w.blit(f.render('Underline', False, [255, 0, 255]), [200, 200]) display.flip()
    # 等待 3 秒 import time time.sleep(3)

    获取和设置字体是否拥有删除线样式

    Font对象的get_strikethroughset_strikethrough方法,以及strikethrough变量,可用于获取和设置游戏字体是否拥有删除线样式。

    get_strikethrough()

    返回值

    如果get_strikethrough返回True,则表示以删除线样式绘制文本。

    set_strikethrough(value)

    value 参数

    value参数是一个布尔值,如果为True,则表示以删除线样式绘制文本。

    font.strikethrough
    font.strikethrough = strikethrough

    strikethrough 值

    strikethrough是一个布尔值,如果为True,则表示以删除线样式绘制文本。

    strikethrough.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载第一个可用的字体 fontname = font.get_fonts()[0] f = font.Font(font.match_font(fontname)) # 修改为删除线样式 f.strikethrough = True
    # 创建游戏窗口,并使用字体对象 f 绘制文字 from pygame import display w = display.set_mode((800, 600))
    # 在游戏窗口中绘制文字 w.blit(f.render('Strikethrough', False, [255, 255, 255]), [300, 300]) display.flip()
    # 等待 3 秒 import time time.sleep(3)

    获取绘制文本所需的空间大小

    Font对象的size方法,可用于计算绘制指定文本所需的空间大小,该方法通常用于布局操作,比如,你可以在获取绘制所需的空间大小之后,判断文本是否能够完全显示在按钮之内。

    size(text)

    text 参数

    text参数是一个字符串,size方法将计算绘制该字符串所需的空间大小。

    返回值

    size方法返回一个形式类似于(width,height)的 Python 元组,其中width表示绘制文本所需空间的宽度,其中height表示绘制文本所需空间的高度。

    Font 对象的 size 方法不会处理字符串中的转义序列

    Font对象的size方法不会处理字符串中的转义序列,比如,换行符\n和制表符\t,这些转义序列可能会被表示为一个或数个空心方块,因此,size方法所返回的空间大小可能和你预期的不一样。

    在下面的示例中,绘制换行符和制表符仅需要很少的空间。

    size.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载默认字体,字体大小 24 f = font.Font(size=24) print(f'绘制 A 所需的空间大小:{f.size('A')}') # 绘制空间不会增加一个行的高度 print(f'绘制 A\\n 所需的空间大小:{f.size('A\n')}') # 绘制空间不会增加一个制表宽度 print(f'绘制 A\\t\\n 所需的空间大小:{f.size('A\t\n')}')
    绘制 A 所需的空间大小:(12, 16)
    绘制 A\n 所需的空间大小:(19, 16)
    绘制 A\t\n 所需的空间大小:(26, 16)

    大部分字体会对特定的字母组合进行字符间距微调

    对于一些字母的组合,比如ae,大部分字体会对组合中的字母之间的距离进行微调(字偶距微调),以改善文本的可读性,因此,一次性绘制所有文本所需要的空间宽度,可能与单独绘制文本中的每个字符所需的空间宽度不同。

    size.py
    # …
    # 加载字体 tahoma
    f = font.Font(font.match_font('tahoma'))
    # 计算一次性绘制所需的空间宽度
    print(f'一次性绘制 Appearance 所需的空间宽度:{f.size("Appearance")[0]}')
    
    # 计算单独绘制每个字符所需的空间宽度 width = 0 for i in 'Appearance': width += f.size(i)[0]
    print(f'单独绘制 Appearance 中的每个字符所需的空间宽度:{width}')
    一次性绘制 Appearance 所需的空间宽度:62
    单独绘制 Appearance 中的每个字符所需的空间宽度:65

    获取字体的行高

    Font对象的get_linesize方法,可以获取字体的行高,该方法通常用于在绘制多行文本时计算下一行文本的位置。

    Font 对象的 get_linesize 与 get_height 方法的返回值可能不同

    需要注意,Font对象的get_linesize方法的返回值与get_height方法的返回值可能不相等,如果不相等,那么字体行高一般大于字体高度。

    get_linesize()

    返回值

    get_linesize方法的返回值是表示字体行高的整数。

    height.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载默认字体,字体大小 120 f = font.Font(size=120) # 获取字体行高 print(f'字体行高:{f.get_linesize()}')
    字体行高:90

    获取字体的高度

    Font对象的get_height方法,可用于获取字体的高度,该高度为字体中所有字形的平均高度。

    get_height()

    返回值

    get_height方法的返回值是表示字体高度的整数。

    height.py
    # …
    # 获取字体高度
    print(f'字体高度:{f.get_height()}')
    字体高度:82

    获取字体的上移量和下移量

    Font对象的get_ascentget_descent方法,可用于获取字体的上移量和下移量,上移量(正整数)表示字体基线与字体顶部之间的距离,下移量(负整数)表示字体基线与字体底部之间的距离,字体上移量和下移量的绝对值之和等于字体的高度(而非行高)。

    get_ascent()

    返回值

    get_ascent方法的返回值是表示字体上移量的正整数。

    get_descent()

    返回值

    get_descent方法的返回值是表示字体下移量的负整数。

    在下面的示例中,字体的上移量为66,字体的下移量为-16,两者的绝对值之和为82,等于字体的高度。

    ascent_descent.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载默认字体,字体大小 120 f = font.Font(size=120) print(f'字体上移量:{f.get_ascent()},字体下移量:{f.get_descent()}') print(f'字体高度:{f.get_height()}')
    字体上移量:66,字体下移量:-16
    字体高度:82

    获取字体的度量值

    Font对象的metrics方法,可用于获取字体中某些字符的度量值。

    metrics(text)

    text 参数

    text参数是一个字符串,metrics方法将计算字符串中的每个字符的度量值。

    返回值

    metrics方法的返回值是一个包含元组的 Python 列表,每一个元组的形式均类似于(minx,maxx,miny,maxy,advance),其中minx表示字符在 X 轴上的最小偏移值,maxx表示字符在 X 轴上的最大偏移值,miny表示字符在 Y 轴上的最小偏移值,maxy表示字符在 Y 轴上的最大偏移值,advance表示字符的前进偏移值。

    在下面的示例中,我们获取了字符Aep的度量值。

    metrics.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 加载默认字体,字体大小 120 f = font.Font(size=120) # 获取每个字符的度量值 print(f'{f.metrics('Aep')}')
    [(2, 58, 0, 60, 59), (1, 44, -2, 44, 46), (4, 48, -18, 44, 50)]

    为文字整形设置文字编码

    Font对象的set_script方法,可用于为文字整形设置文字编码。

    set_script(script_code)

    script_code 参数

    script_code参数是一个表示文字编码(符合 ISO 15924 标准,由四个字符组成)的字符串。

    Font 对象的 set_script 方法需要 SDL_ttf 2.20.0 或更高版本

    要正常使用Font对象的set_script方法,需要 SDL_ttf 的版本为 2.20.0 或更高,否则会导致异常。

    什么是文字整形?

    文字整形用于对显示的文字进行调整,以达到一种最佳的视觉效果,Pygame 使用 HarfBuzz 作为文字整形的引擎。

    set_script.py
    # 导入并初始化 font 模块
    from pygame import font
    font.init()
    
    # 将文字整形设置为阿拉伯文 f = font.Font() f.set_script('Arab')

    获取 SDL_ttf 的版本信息

    font模块构建在 SDL_ttf 之上,该模块的get_sdl_ttf_version函数,其返回值是一个元组,元组包含了 SDL_ttf 的版本信息。

    get_sdl_ttf_version(linked=True)

    linked 参数

    如果linked参数为True,则函数get_sdl_ttf_version返回当前所使用的 SDL_ttf 的版本信息,否则返回 Pygame 包在编译时所针对的 SDL_ttf 版本。

    返回值

    get_sdl_ttf_version函数的返回值是一个形式类似于(major,minor,patch)的 Python 元组,其中major表示主要版本号,minor表示次要版本号,patch表示补丁号。

    version.py
    from pygame import font
    
    # 获取 SDL_ttf 版本 print(f'当前使用的 SDL_ttf 版本:{font.get_sdl_ttf_version()}') print(f'编译时针对的 SDL_ttf 版本:{font.get_sdl_ttf_version(False)}')
    当前使用的 SDL_ttf 版本:(2, 20, 1)
    编译时针对的 SDL_ttf 版本:(2, 20, 1)

    源码

    src/zh/font·codebeatme/pygame·GitHub

    讲解视频

    如何在 Pygame 中加载字体,以及获取和设置样式·YouTube如何在 Pygame 中加载字体,以及获取和设置样式·Bilibili