如何尋找和載入遊戲字型?以及取得和設定字型樣式等問題
訂閱 480
雖然本節的範例中包含繪製文字的程式碼,但本節不會講解與文字繪製相關的問題,要了解文字繪製,請檢視在表面中繪製影像和文字(字型)一段。
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)