歡迎參與討論,轉載請註明出處。
本文轉載自:https://musoucrow.github.io/2018/06/23/dfq_sheet/
前言
在遊戲開發的領域裏,圖集(SpriteSheet)是一個很重要的概念,其好處在鏈接處也已言明。但若是引擎沒提供相關的支持,那麼便需要自己搞個解決方案了。而LÖVE也恰好是沒有提供相關支持的,那麼只好自己動手豐衣足食了,本文便記錄其中心得。
裝箱問題
要實現圖集的核心便是對圖片進行拼合打包,其實類似的工具市面上亦有存在(如TexturePacker)。從功能上而論,TexturePacker完全可以滿足需求(有提供命令行模式,可實現自動化)。可惜TexturePacker的免費版根本不堪使用,而破解也相繼失敗。而其他類似的工具要麼無法滿足需求,要麼不支持macOS。只好自己手寫一套了。
實現的圖集的難點無非在於拼合時圖片排列的算法,由Claris告知得這種屬於裝箱問題,目前並無最優解。由裝箱問題爲關鍵字進行展開搜索,發現一種名爲MaxRectsBinPack的算法可解決問題,我將之翻譯成了Python版。如此裝箱問題便解決了。
拼合問題
接下來的問題便是“誰和誰拼合成一張圖”了,我對此立下三個原則:
- 關聯性不高者不拼(拼成大圖的代價便是成爲資源共同體,如果關聯性不高的拼合一塊則會造成極大的內存浪費)
- 黑底與透明者不拼(黑底圖拼成大圖必須得保證全圖無透明點,否則遊戲裏會出現奇怪的線條)
拼合後過大者不拼(需保證圖片大小在4096*4096及以下,否則恐怕出現上限問題)
以這三原則來看,是無法做到以文件夾爲單位進行粗暴的拼合了。所以採用了編寫配置的方式進行。
"effect": {
"map": {
"lorien": [
"lorien",
"/actor/article/lorien/pathgate",
"/actor/article/lorien/largegrass"
]
},
"death": [
"death",
"dieFlash"
],
"buff": {
"freeze": "freeze"
}
}
配置以JSON形式存儲,配置中的key代表着合圖文件夾的層級,value則爲欲拼合的圖片文件夾,若無/
開頭則代表以當前文件夾層級爲路徑,反之則爲全路徑。以這套方案便可很自由地選擇拼合的方案了。
配置問題
圖片的拼合問題解決後,便是遊戲要如何以最低的代價去兼容新的圖片形式了。解決方案自然是爲原圖片生成路徑一致的配置文件,遊戲通過讀取配置文件以無縫對接新的圖片形式。配置文件格式如下:
return {
image = "ui",
x = 0,
y = 151,
w = 45,
h = 41
}
配置文件記錄了所屬合圖的路徑以及在合圖中的座標寬高,如此便可清晰無比地取得了。由於Python的lupa模塊裝不上,爲此還專門寫了個Lua與JSON的轉換器。
大小問題
一般而言,因爲光柵化需要對紋理採樣進行快速取值,圖片大小需要遵循2的N次冪(256、512、1024…)。這種符合的圖片被稱爲POT(Power-Of-Two),同理不滿足的稱爲NPOT(Non-Power-Of-Two)。在早期POT紋理可以說是必須的,而今在OpenGL ES2.0後支持了NPOT。但爲了能滿足ETC壓縮以及兼容性,個人推薦還是對合圖進行POT化。
後記
其實從這個問題來看,選擇流行的大引擎的確會更爲方便。在Unity裏可以由後臺自動完成的事情現在卻要一篇文章來總結,不過賊船已經上了,就只能走到黑了。