Make a Common “Damage Number” Animation Using Godot, PaintNet and Bitmap Font Generator

這篇文章講的是如何做一個遊戲中常見的會跳動的傷害值動畫,長得像下面的圖示。

會用到的有

  1. Bitmap Font Generator
  2. PaintNet
  3. Godot

通通是免費 MIT License 軟體,非常感謝這麼多人的付出。m(_ _)m

會用到 Bitmap Font Generator 和 PaintNet 是因為 Godot 不支援文字的漸層色,如果不需要漸層效果就不需要這二樣。

首先我們先把數字零到數字九變成一些 PNG 檔,會用到的是 Bitmap Font Generator。他在將文字從字形的向量資料轉變成 PNG 的過程中,可以指定文字大小,留白大小,填滿文字中間是用黑色白色還是透明色,是否要外框與外框粗細等等簡單的設定。

因為我們只需要零到九,所以選擇這十個字就好,然後在 Font Setting 中我要求用 PNG 輸出,字體高度 240 pixel,邊框寬度 3。

Export Options 裏,我設定輸出的十個數字的圖片長 3000,因為我希望它們在同一行方便做漸層。文字留 padding 20px,輸出 PNG。

輸出結果有一個 PNG 和一個文字的 fnt 檔說明每個字元圖片的大小和 offset。

接下來我們用 PaintNet 加漸層,先讀取 PNG 檔。

  1. 加一個新的 Layer,要是勾選的狀態。
  2. 在原來的 Layer 用 Magic Wand 把十個數字的外框圈起來
  3. 在新 Layer 會出現這十個外框。
  4. Unselect old layer
  5. In new layer,click Gradient in tool panel,選擇起點顏色和終點顏色,然後在畫面上用 “畫一條直線” 的方法指定漸層的起點和終點。
  6. Select old layer 看效果,效果好就儲存。

再來是 Godot, 我們要客製化一個 BBcode 給 RichTextLabel 使用。先開一個新的 GDScript 檔案,用來定義新的 BBcode。

tool
extends RichTextEffect
class_name RichTextDamage

# Syntax: [damage height=100.0 length=0.5 xshift=-50 yshift=100 delay=0.05 loop=false anitimer=true anilength=1.0][/damage]

# Define the tag name.
var bbcode = "damage"

func _process_custom_fx(char_fx):
	# Get parameters, or use the provided default value if missing.	
	var length = char_fx.env.get("length", 0.5)
	var height = char_fx.env.get("height", 100.0)
	var xshift = char_fx.env.get("xshift", 50)
	var yshift = char_fx.env.get("yshift", 100 )
	var delay = char_fx.env.get("delay", 0.05)
	var loop = char_fx.env.get("loop", false)
	var anitimer = char_fx.env.get("anitimer", true)
	var anilength = char_fx.env.get("anilength", 1.0)

	if anitimer and char_fx.elapsed_time >= anilength:
		char_fx.visible = false

	var char_relative_elapsed = char_fx.elapsed_time - char_fx.absolute_index * delay
	var x_pos = char_fx.absolute_index * xshift
	
	if char_relative_elapsed < 0: 
		char_fx.offset = Vector2(x_pos, height + yshift) 
		return true 
	# done 
	if !loop and char_relative_elapsed >= length:
		char_fx.offset = Vector2(x_pos, height + yshift)
		return true
	
	var y_pos = height - abs(sin( PI * char_relative_elapsed / length)  * height)
	char_fx.offset = Vector2(x_pos, y_pos + yshift)
	
	return true

 

在右下的 File System -> res:// 加入 New Resource -> RichTextEffect,建立了 *.tres 後將剛剛的 GDScript 連結起來。

在 RichTextLabel 裏,要改的有二個地方,第一個是指定字型。Inspector->Custom Fonts->Normal Fonts,建立 Bitmap Font 字型,指定剛剛的 fnt 檔。再來是加入剛剛寫的 BBCode 定義,Custom Effect->加一個->讀取剛剛的 *.tres。然後在 BBcode 寫

[damage]1234[/damage]

完成!

用 Bitmap Font 的優點是可以隨意改圖片樣式,但有嚴重缺點

  1. 不能改字型大小,要改只能改 Control Scale,這點 Godot 4.x 聽說會改。
  2. 要動用繪圖軟體

用 Dynamic Font 雖然可以改字體大小,但

  1. 每次都要讀整個字型檔,可是我們只用的到十個數字很浪費資源。
  2. Godot 3.x 沒有支援漸層色特效,好像也沒有支援外框? 不過我可以同時寫重疊的二個字,類似的立體陰影效果。

補充一點,RichTextLabel 是從左上角開始畫字的,所以要再往上移動會超出外框無法看到,所以我的特效是先全部往下移再往上跳,參考上面的 GDScript。