【心得】【1.16+】在地圖中使用名條顯示動畫的方式與教學(附超簡單使用的工具、數據報)

先上效果圖

大家好,我是貓狗喵

1.16 出了一個方便的東西叫做自訂字體檔,不過目前好像沒看到它被拿來做什麼有趣的應用。那剛好最近趁八月去當兵前幫 Terry 做還原楓谷的系統,其中很多特效就使用名條動畫來呈現,所以今天就來分享如何靠自訂字體檔做到名條動畫的效果吧!
對了如果有人有興趣這個在 minecraft 還原楓谷的計劃,近期應該會以製作日誌的形式發文,其中也會包含一些應用技術分析,有興趣的可以追蹤一下
喔還有,根據過往經驗,每次我發技術文大多都是大家看看覺得有趣,然後還是沒看到有人拿來應用,所以這次我打算更改一下我的文章內容安排。這次開頭就上如何快速把這個功能套用在你地圖裡的方法,後面才講解原理,想了解運作原理的記得看到後面嘿

一步步教你在地圖中套用名條動畫

1. 首先下載 Font Animation Creator 這個程序

度的我寫的,這兩天才趕工把他改寫成圖形介面的程序所以寫得很醜

原碼都附在裡面了,想改寫請註明原作,然後如果有 BUG 可以跟我說但我不見得會修

2. 解壓縮到文件夾後會看到下面四個文件,運行 Font Animation Creator.exe 就對了

3. 點開後等他一段時間會出現下面這個畫面

功能解釋:

  • A:動畫要導入哪一個資源包文件夾內,右邊的按鈕可以選擇文件夾
  • B:添加一張圖片列表 E 時,該畫格預設的停留時間
  • C列表 E 中目前選擇的畫格停留的時間
  • D:選擇一個 GIF 檔導入列表 E
  • E:動畫畫格列表,順序由上到下,可以用拖曳的方式調整畫格順序
  • F:添加一張圖片到列表 E,要注意所有圖片都會置中對齊
  • G:移除列表 E 選擇中的畫格
  • H:清空列表 E 的內容
  • I:預覽動畫效果,在遊戲中會顯示原本的大小,但解析度最高就是如預覽的這樣
  • J:當你在遊戲里繞著圖片跑的時候,他會以哪邊為旋轉軸面向你
  • K:如何把當前動畫間隔轉換成 minecraft 中的動畫間隔,不懂就用默認值就好
  • L:把列表 E 的內容轉換成 minecraft 的名條動畫,並在目標資源包內保存相關素材

4. 全部設置好後按「創建」按鈕,他會叫你幫動畫文件取一個名字,高興取什麼都行

5. 創建完成後會跳出字體檔存放的文件夾,裡面有一個 mcfunction 文件,就是用來生成名條動畫的

6. 下載倒退字元資源包,把它的內容全部丟進你自己的資源包裡面

要注意使用這個資源包是需要原作表示的,不過內容的修改等等就完全沒有限制

7. 在這裡下載 Font Animation datapack 這個數據報,或是在 Font Animation Creator 的文件夾裡面也有。把它丟到你地圖的 datapacks 文件夾裡面

8. 上一步的數據報有安裝成功的話,進去遊戲應該會看到安裝成功的消息。

這時候就可以把上面的 summon.mcfunction 丟到自己的數據報裡面,並且運行來看看效果了!

如何?是不是真的超簡單?這次大家總該把這技術拿來用了吧?

如果大家有使用這套工具的話希望可以在地圖中註明一下,不過真的沒標註我也不會咬你就是了

如果你想知道其中的一些選項實際有什麼功能,可以跳到最後選項效果解說的部分來看


動畫名條的原理教學

終於來到眾所期待的教學環節了(還是說其實沒人想知道,大家只想要工具而已?)
這次的教學我也會改變一下內容呈現的方式,不同於以往直接把一卡車的內容倒下去,這次我會試著把我一些思路歷程跟主要的技術點列出來,有興趣的不妨跟著思考看看粗體字的問題要怎麼解決,想好了或是想不出來再往下看我的解法

==============   正文開始   ===============

  • 如何讓文本圖片照順序更替?
(如果你在這邊想到用 list 的作法的人不要急,這作法我後面再講)
在過去版本中最直覺的想法應該是:透過分數窮舉對應的文本圖片。不過窮舉這種東西就是浪費性能,又沒有泛用性,每次做新的動畫就要再窮舉一次、多做一套連閃偵測
不過到了 1.16 出了自訂字體檔後就不一樣了,在遊戲中我們可以不用窮舉自動依串列出文本的方式就是數字顯示,不管是記分板還是 nbt 數值,我們可以輕易的運算然後用 json 格式顯示出來。如果還不清楚如何把分數寫進 json 字元串可以看這篇,我過去都是用 loot table 法不過聽說告示牌法比較省,所以現在也換成告示牌法了。有了依串列出文本的方式後,我們只要把

圖片對應的數字文本寫進自訂字體檔,然後在我們的 json 字元串聲明使用的字體就可以了。

那這邊又會遇到兩個問題:

1. 要怎麼聲明我們 json 字元串要用哪個字體?

聲明字體好像很單純,只要把 font 寫進 json 裡面就好了,然而問題在於怎麼知道要寫什麼 font 進去。如果每個動畫個別使用不同的 json 聲明,那還是沒有解決窮舉法一個動畫需要一套連閃的問題

這時候就要用一點小技巧了,那就是利用 json 解析的特性

常用 json 生成器的人應該會發現,生成器產生的中括弧 […] 的內容,開頭第一個對象基本上都是空字元串,以前我也一直覺得意義不明,後來才知道它的功能是什麼。在 WIKI 頁面中也有提到格式的繼承關係。如果你用 data get 把中括弧解析後的新字元串抓出來看會發現,中括弧其實就是被解析成第一個對象 extra 其它對象的格式

利用這個特性,我們只要把字元串以中括弧或 extra 形式寫好,第一個對象填入我們要的字體格式的空字元串,第二個對象填入我們要顯示的數字就完成了。不過這裡又會遇到一個小問題

怎麼針對每個不同的動畫填入不同字體的空字元串?


我的作法是事先寫好,以字元串形式存在顯示名條的實體身上,例如 ‘{“text”:””,”font”:”test:main”}’。然後當要解析 json 的時候,只要用 json  當中的 nbt 搭配 interpret 的效果就可以還原出那個有字體的空字元串了。

2. 數字只有 10 個,動畫畫格數超過 10 個怎麼辦?

要想打破數字的數量限制,勢必得使用更多的字體檔。在上一個問題我們已經知道要把有字體的空字元串存在名條實體身上,那接下來的問題就是

要怎麼存更多的字體,並且依序替換?

我的作法很簡單,就是使用 list 來保存那些字元串,解析 json 時固定填入 list 的第一項,然後每顯示完 10 個一組的數字就把 list 第一個對象移除掉。

聽到這裡,一開始就想到 list 法的人應該已經按耐不住了 我這不是來了嗎.jpg

我也是在打這篇文章的時候才想到,其實還有一套不需要數字,也不需要多個字體檔的作法。那就是事先把每個畫格的圖片存成自訂字體檔中的各個文本,然後把那些文本全部依序存在 list 裡面,這樣我們只要每個畫格顯示 list 的第一個字,然後移除第一個 list 的對象就搞定了

說到這裡,感覺好像製作名條動畫的工具都已經俱備了,但其實還有一個小問題還沒解決

每個畫格的停留時間該怎麼設置?

我們剛剛說的「每次」更換一個顯示的文本,原則上就是每 tick 運行一次。但是 1 tick 就是 50 毫秒,先不考慮實際動畫中每個畫格的停留時間常常不是 50 毫秒的整數倍的問題,假設現在同一個動畫中有的畫格停留 100 毫秒,有的停留 200 毫秒,我們要怎麼處理呢?

或許你會想到另外再開一個 list 保存每個畫格的停留 tick 數量,不過這個方法有點複雜,也需要比較多的運算。這裡我採用的方法是:一個畫格不夠,那不會再一個嗎?

以我的顯示數字的作法來說,假設第一個畫格會停留 200 毫秒,那我就把 0123 四個數字全部都設置成同樣的圖片不就搞定了嗎(茶

那如果你用 list 法原理也是一樣,同樣的一個字塞四次就解決了

到這裡一套優雅的,免窮舉的名條動畫顯示系統就完成了。只需要一套連閃,召喚的時候填入不同的字元串就會自動顯示不同的動畫。下一步要提到的則是進一步優化相關的技巧,如果對系統性能不在意的可以跳到下個分隔線後,關於 Font Animation Creator 部分選項效果解說的部分

  • 如何透過 藥水雲(area_effect_cloud) 來當顯示名條的實體?
或許有些人還不清楚,不過藥水雲在性能上比起盔甲架或掉落物等實體節省了 10 倍左右,因此非必要的情況下使用藥水雲作為實體可以大幅節省資源
於是我就在想這個功能是不是可以只用藥水雲來達成,顯示名條的部分只要是實體就能做到,用藥水雲絕對沒問題。問題出在字體的 list 該存在哪裡
盔甲架或掉落物可以透過道具欄位的虛擬 nbt 輕鬆創建一個字元串的 list 來訪問字體 (還不知道虛擬 nbt 是什麼的自己回去看這篇),但是藥水雲可就沒有那種方便的東西了。翻遍藥水雲的 nbt 數據不要說是字元串 list 了,就連字元串都找不到幾個。撇除 CustomName 是我們要用的,剩下的字元串數據就只有 Particle 而已,設成原版沒有的 particle 還會被強制改回去。就在打算放棄的時候突然想到還有一個東西可以用,那就是所有實體都可以有的 Tags
不過如果你直接開開心心的把那些字體的 json 字元串丟進 Tags 你會發現,那個順序是在哈啰?
如果他是單純的單個數字的字元串,看起來好像又會照順序,但只要加上其他字以後整個順序就找不出規律了。這時候有點程序 sense 的人應該就會猜到,結合這個摸不著頭緒的順序,以及內容不能重複的特性,答案就是……
沒錯 Tags 是用 HashSet 去存的,沒學過程序的只要知道他會經過一串數學公式去得出他所屬的位置就好了
那因為 Java Edition 的 Minecraft 是用 Java 寫的(廢話),可是我又查不到 Java 的 Hash 公式是什麼,為了驗證我把人生第一次寫 Java 的經驗就用在這上面了。(後來聽強者我同學說 Java String 的 Hash 公式是把第一個字元乘以 31 再加下一個字元,重複以上動作到最後一個字。不過不知道溢出的話怎麼處理,我也懶得驗證所以就算了)
而 Font Animation Creator 當中我給 Tags 排序的方法就是先丟進 Java 程序存到 HashSet 再吐回來給我,想要的可以直接運行 PrintSet.exe 那個文件,輸入幾個字元串然後用空格隔開,他就會回傳 Hash 後的順序了,或是你直接開 Minecraft 把 Tags 寫進去再抓結果也可以知道順序。
那知道 Tags 的順序之後我們就可以像一般字元串 list 那樣使用 Tags 來訪問數據了,要注意的只有不能給它亂加其他的 tag 進去,要不然你不知道他被排到哪,哪天他就被拿來當成字體格式字元串你都不知道
另外前面提到的完全用 list 來保存每個畫格要顯示內容的方法,在這邊也需要一些調整。前面提到如果一個畫格要顯示 4 tick 那你就要把同樣的圖片文本塞 4 個進去,但是 Tags 是不可重複的,也就是說你沒辦法塞 4 個相同的字進去 Tags 裡面,這時候你就必須同一張圖片用 4 個不同的字來顯示,而且這 4 個字的順序要排在一起,在計算順序的時候相對來說麻煩了一點

做到這邊,數據報的部分就可以划下完美的句點了,至少我也沒想到什麼更好的做法了,可喜可賀
接下來就是 Font Animation Creator 中一些選項與效果的解說

Font Animation Creator 部分選項效果解說

終於來到最後的部分了,這篇文章打到現在已經花了一天多了,幸好巴哈現在有備份功能,要不然想隔一段時間再編輯還要先複製原碼真夠麻煩的
  • 圖片解析度與大小關係
在自訂字體檔中有一個限制,那就是字體讀取的圖片長寬都不能超過 256 像素,超過就會死圖
不過在遊戲裡面顯示的大小就沒有限制了(至少一般大小不可能超過),因此只要在解析度最高 256 * 256 的限制下,還是可以在遊戲里顯示原始圖片的大小比例
而 Font Animation Creator 中間預覽的區塊的大小就是 256 * 256,也就是說成品的解析度最多就是像預覽畫面中的那樣。為了保持各個圖片大小比例的關係,如果有圖片長或寬超過 256 的話,所有圖片都會縮小「讓圖片列表中最大的圖片壓縮回 256 * 256 內的壓縮比例」
另外在遊戲中沒有標準的圖片大小的概念,所以我預設在遊戲中顯示的圖片長度數值是原圖片的一半,這是我認為看起來最貼近圖片在 Minecraft 中應該顯示的大小比例。然後我懶得再把這個比例的控制寫進程式了(排版好麻煩R),所以想要改的自己研究原碼來改或是放大縮小原始圖片的大小吧
  • 圖片錨點功能解說
在 Minecraft 中名條的顯示是會以中心點為球心旋轉面向玩家的,球心就如下圖紅點所示,位於背景海苔條的中心
圖片會自動置中,所以左右的旋轉是固定的,但是上下的旋轉就得看圖片相對球心的高度了,這東西是由字體檔控制的,看你需要以圖片的哪個點為旋轉中心就調到那個點吧
下面三張圖由左至右分別是錨點為 0.0 / 0.5 / 1.0 時的圖片與旋轉軸相對位置
  • 幀分割公式解說
這應該是大家最看不懂的東西了,不用 Google 了,這兩個選項的名詞都是我取的
這部分主要就是要解決前面說的,每個畫格停留時間不會剛好是 50 毫秒的倍數的問題
這裡就拿下面這張圖來解釋一下 (沒錯這是魔力爪的畫格停留時間圖)
橫軸是時間線,藍線代表實際畫格切換的時間,紅色代表每個 tick 的時間,綠色待會再說
  • 時間門檻法
這個演算法的邏輯非常直覺,就是我每個 50 毫秒(紅線位置)都個別判斷現在處於哪個原始畫格的範圍內(包含開頭,不含結束),以上圖來說,紅色的 0, 50, 100 都屬於第一個畫格,150, 200 屬於第二個畫格,以此類推直到 600 毫秒的瞬間就消失了,也不用再切換畫格了
一般情況下都建議使用這個演算法,雖然偶爾會有畫格延遲的感覺出現,但是 50 毫秒的間距並不會讓這個感覺太明顯。使用這個演算法的優點是可以較還原原始動畫的速度,並且在很多畫格的停留時間小於 50 毫秒的時候,可以節省一些未使用到的畫格圖片的文件
時間門檻法還原楓谷天怒特效(每個畫格固定 120 毫秒),偶爾有卡頓的感覺但不明顯
  • 最小間距差法
這個演算法其實也很直覺,只是有些特殊狀況需要處理。這個演算法的結果就如上圖綠線所示
最小間距差,顧名思義就是最小化「顯示的畫格停留時間」,與「實際畫格停留時間」的差距
以上圖來說,各個畫格停留的時間依序為 120, 90, 120, 90, 150 毫秒
在以 50 毫秒為最小單位的情況下,最接近的停留時間依序為 100, 100, 100, 100, 150 毫秒,也就是上圖中綠線的分布情形
這個演算法的優點是,當原始動畫的各個畫格停留時間很穩定,但並不是 50 毫秒的整數倍時,它可以有效的保持原始動畫的流暢度,而不會有畫格延遲的感覺出現
然而相對來說它就會導致動畫的播放有變速的感覺,假設原始畫格停留時間固定是 60 毫秒,用這個演算法跑出來的動畫就會有快進 1.2 倍的效果(顯示的畫格停留時間都是 50 毫秒)
而所謂的的特殊狀況就是,當原始畫格停留時間小於 25 毫秒時,這個畫格最接近的停留時間就會變成「0」,沒錯毫無懸念直接死去。這就代表假如你把 40 FPS 以上的動畫丟進這個演算法裡面,你會發現就跟把錢丟進楓谷的金蘋果一樣,噗通一聲就不見了
為了避免這樣的狀況,所以我的程序在運行這個演算法的時候,有限制每個畫格最小的停留時間就是 50 毫秒,雖然這樣就不會丟東西進去然後什麼都沒跑出來,不過你會體會到什麼叫做「世界越快,心則慢」的超級慢動作特效
最小間距差法還原楓谷天怒特效(每個畫格固定 120 毫秒),有了快進 1.2 倍的效果

好啦這次的教學就到這邊結束了,真有夠長的
這種可以自由顯示圖片的字體檔其實從 1.13 版本就有了,我在浮光戰記地圖跟 DIO 數據報都有應用到,只是以前只能改原版的文本,所以不能亂改數字之類的,現在 1.16 有自訂字體後終於更加活用了
關於字體檔的格式說明大家可以看這篇,雖然是英文就是了
如果看不懂的話在下面留言敲碗,有人敲我再考慮寫一篇相關的教學 (゚∀゚)
本文來自網路,不代表3樓貓立場,轉載請註明出處:https://www.3loumao.org/3421.html?variant=zh-tw
返回頂部