如何尋找和載入遊戲字型?以及取得和設定字型樣式等問題
訂閱 375
雖然本節的範例中包含繪製文字的程式碼,但本節不會講解與文字繪製相關的問題,要了解文字繪製,請檢視在表面中繪製影像和文字(字型)一段。
Pygame 字型載入與樣式控製,font 模組簡介影片示範 YouTube
Pygame 中的 font 模組
Pygame 套件的font
模組,包含了與字型相關的功能,主要涉及字型的載入(取得),以及字型的繪製(本節內容不涉及此部分),當你匯入pygame
模組時,font
模組會被pygame
模組匯入。
初始化 font 模組
與pygame
模組一樣,font
模組擁有用於初始化的函式init
,該函式會在pygame
模組的init
函式中被呼叫,這意味著一旦使用pygame
模組進行初始化,呼叫font
模組的init
函式將是沒有必要的。
init()
可以重複呼叫 init 函式
你可以反覆呼叫init
函式,這沒有任何問題,即便在呼叫quit
函式之後。
# 匯入模組 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
模組。
# …
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
會嘗試去除他們。
# …
# 取得所有可用字型的名稱
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
函式還是會傳回其名稱。
# …
# 取得預設字型的檔案名稱
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
。
# …
# 取得字型檔案的路徑
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
物件,以將對應的字型載入到遊戲中。
# 匯入並初始化 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_bold
和set_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
變數,遊戲中的文字將以粗體樣式繪製。
# 匯入並初始化 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_italic
和set_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
方法為字型取消斜體樣式,但這不會產生任何效果。
# 匯入並初始化 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_underline
和set_underline
方法,以及underline
變數,可用於取得和設定遊戲字型是否擁有底線樣式。
get_underline()
- 傳回值
如果
get_underline
傳回True
,則表示以底線樣式繪製文字。
set_underline(value)
- value 參數
value
參數是一個布林值,如果為True
,則表示以底線樣式繪製文字。
font.underline
font.underline = underline
- underline 值
underline
是一個布林值,如果為True
,則表示以底線樣式繪製文字。
# 匯入並初始化 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_strikethrough
和set_strikethrough
方法,以及strikethrough
變數,可用於取得和設定遊戲字型是否擁有刪除線樣式。
get_strikethrough()
- 傳回值
如果
get_strikethrough
傳回True
,則表示以刪除線樣式繪製文字。
set_strikethrough(value)
- value 參數
value
參數是一個布林值,如果為True
,則表示以刪除線樣式繪製文字。
font.strikethrough
font.strikethrough = strikethrough
- strikethrough 值
strikethrough
是一個布林值,如果為True
,則表示以刪除線樣式繪製文字。
# 匯入並初始化 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
方法所傳回的空間大小可能和你預期的不一樣。
在下面的範例中,繪製換行字元和定位字元僅需要很少的空間。
# 匯入並初始化 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
,大部分字型會對組合中的字母之間的距離進行微調(字距微調),以改善文字的可讀性,因此,一次性繪製所有文字所需要的空間寬度,可能與單獨繪製文字中的每個字元所需的空間寬度不同。
# …
# 載入字型 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
方法的傳回值是表示字型行高的整數。
# 匯入並初始化 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
方法的傳回值是表示字型高度的整數。
# …
# 取得字型高度
print(f'字型高度:{f.get_height()}')
字型高度:82
取得字型的上移量和下移量
Font
物件的get_ascent
和get_descent
方法,可用於取得字型的上移量和下移量,上移量(正整數)表示字型基線與字型頂端之間的距離,下移量(負整數)表示字型基線與字型底端之間的距離,字型上移量和下移量的絕對值之和等於字型的高度(而非行高)。
get_ascent()
- 傳回值
get_ascent
方法的傳回值是表示字型上移量的正整數。
get_descent()
- 傳回值
get_descent
方法的傳回值是表示字型下移量的負整數。
在下面的範例中,字型的上移量為66
,字型的下移量為-16
,兩者的絕對值之和為82
,等於字型的高度。
# 匯入並初始化 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
表示字元的前進位移值。
在下面的範例中,我們取得了字元A
,e
,p
的量值。
# 匯入並初始化 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 作為文字整形的引擎。
# 匯入並初始化 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
表示修補號碼。
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)