在遊戲開發中,尤其是對於移動端的遊戲開發來說,直接使用TTF來進行渲染是非常消耗資源的;而且一般的遊戲用到的字的個數都是有限的。針對以上幾個弊端,就有人按照着活字印刷術的原理來設計了一個在遊戲中常用的位圖導出工具,比如windows下的bmfont、java寫的hiero等等,用到文字比較多的一般是RPG遊戲,如下圖所示:
以下是BMFont官網的簡介:
此程序將允許您從TrueType字體生成位圖字體。應用程序生成圖像文件和字符描述,遊戲可以讀取這些文件和字符描述,以便輕鬆呈現字體。
位圖在遊戲引擎中一般都會有封裝好的,比如cocos2dx在2.x時代提供了LabelBMFont,在3,x後爲Label。
本節主要講解的就是如何通過python來實現根據用到的文字導出位圖文件。
1.安裝BMFont
首先需要安裝BMFont。BMFont的安裝很簡單,這個軟件同時提供了界面和命令行,不過美中不足的就是隻能在windows下使用。對於批量導出來說,命令行尤其重要。至於BMFont的簡單使用,可以參考下面這個帖子或者自行百度:
https://blog.csdn.net/u013654125/article/details/78672809
2.配置Path
由於批量導出使用的得是命令行,所以在python程序運行時,需要知道BMFont的安裝路徑。
假設此時的BMFont安裝在D盤的bmfont下,那麼在Path中則添加下面一條:
D:\BMFont
之後可以在dos中確定是否可以找得到這個軟件,鍵入bmfont,如果直接顯示的是bmfont的界面,則表示Path的路徑配置成功。
注:這一步是非必須的,如果不想配置的話,在python代碼中得需要明確bmfont的安裝路徑。
3.從配置|源文件文件中提取文本
一般情況下,像上圖這種對話的文本是寫在配置文件或者腳本文件中的,所以需要有一個規則來提取要顯示的文本。
以下面這個腳本爲例:
function Map01_01:firstIn()
-- 第一次運行,執行腳本
base.setGameState(GameState.Script);
--獲取主角名字
local playerName = party.getName(0);
--旁白
message.showText("***","一羣小鬼(初三的模樣)在網吧坐在一塊玩遊戲", TextPosition.Middle,true);
end
上面的示例是我寫的RPG遊戲的部分腳本代碼。可以看到,文本顯示主要是message.showText函數的前兩個參數。所以,我們需要提取的就是這兩個參數的文本。然後再把這個操作擴展到所有的腳本文件,挨個提取完之後導出爲一個文本,以供BMFont所使用。
import os
import re
def generate_text(path, filename):
"""
遍歷path路徑下的所有文件,並正則提取出所有文本,然後生成utf-8的txt文件
:param path: 要遍歷的路徑名
:param filename: 導出的文件名
:return:
"""
# 獲取路徑下的所有文件
paths = os.listdir(path)
# 正則匹配要顯示的文本
pattern = re.compile(r'showText\(\"(.*?)\"\s*,\s*\"(.*?)\"')
# 用得到數字
contents = ["1234567890"]
# 遍歷
for name in paths:
fp = open(os.path.join(path, name), "r", encoding="utf-8")
lines = fp.readlines()
text = "".join(lines)
results = re.findall(pattern, text)
if len(results) == 0:
continue
print(results)
for result in results:
contents.append(result[0])
contents.append(result[1])
# 寫入文件
with open(filename, "w", encoding="utf-8") as fp:
fp.writelines(contents)
print("寫入文件成功:%s" % filename)
以上代碼的流程圖大致如下:
值得一提的就是正則提取文本的規則,大家可以根據自己的需要來改變提取規則。如果提取規則過於麻煩,或者有多於一個的提取規則,則可以考慮封裝不同的函數來進行提取。
4.導出位圖
位圖的導出則相對來說比較簡單了。
def generate_fnt(bmfc, input, path, filename):
"""
根據配置文件和輸入的文本文件來導出對應的fnt文件和png文件
:param bmfc: BMFont的配置文件
:param input: 文本文件
:param path: 輸出路徑
:param filename: 輸出文件名稱
:return:
"""
# 判斷輸出文件夾是否存在
if not os.path.exists(path):
os.mkdir(path)
print("創建文件夾成功", path)
ret = os.system("bmfont -c %s -t %s -o %s" % (bmfc, input, os.path.join(path, filename)))
# 導出成功
if ret == 0:
print("fnt文件導出成功")
bmfont的命令行:
- -c 配置文件,擴展名爲*.bmfc
- - t 文本文件
- -o 導出文件
os.system()的返回值就是命令的返回值,一般情況下返回0則表示操作成功。
最後就是上面兩個函數的整合了。
if __name__ == '__main__':
# 主目錄
base_path = os.path.join(".", "RPGGame", "Resources")
# 先提取出要用到的文本,並生成文件
generate_text(os.path.join(base_path, "script"), "1.txt")
# 使用bmfont 命令行導出資源文件,並放到對應的文件夾中
generate_fnt("1.bmfc", "1.txt", os.path.join(base_path, "fonts"), "1.fnt")
由於不同操作系統的路徑分隔符是不同的,所以上面的代碼中用到了os.path.join()。