Heads up display¶
The final piece our game needs is a User Interface (UI) to display things like score, a "game over" message, and a restart button.
Create a new scene, and add a CanvasLayer node named
HUD
. "HUD" stands for "heads-up display", an informational display that
appears as an overlay on top of the game view.
使用 CanvasLayer 節點可以讓我們在遊戲上方的圖層上繪製 UI 元素,這樣上面顯示的資訊就不會被其他遊戲元素如玩家或怪物給蓋住。
HUD 需要顯示如下資訊:
分數,會通過
ScoreTimer
來更改。訊息,如「Gamer Over」或「請準備!」
用來開始遊戲的「Start」按鈕。
UI 元素所使用的基本節點是 Control 。我們需要使用兩種類型的 Control 節點來給這個遊戲建立 UI: Label (標籤)與 Button (按鈕)。
為 HUD
節點建立下列子節點:
點擊 ScoreLabel
並在屬性面板中的 Text
輸入一個數字。 Control
節點的預設字體很小,而且也縮放得不是很好。遊戲素材裡有包含了一個字體檔,檔名為「Xolonium-Regular.ttf」。依照下列步驟來使用這個字體:
Under Theme overrides > Fonts click on the empty box and select "New DynamicFont"

Click on the "DynamicFont" you added, and under Font > FontData, choose "Load" and select the "Xolonium-Regular.ttf" file.

Set the "Size" property under Settings
, 64
works well.

Once you've done this on the ScoreLabel
, you can click the down arrow next
to the Font property and choose "Copy", then "Paste" it in the same place
on the other two Control nodes.
備註
Anchors and Margins: Control
nodes have a position and size,
but they also have anchors and margins. Anchors define the origin -
the reference point for the edges of the node. Margins update
automatically when you move or resize a control node. They represent
the distance from the control node's edges to its anchor.
依照下圖排列節點。點擊「畫面配置」按鈕來設定 Control 節點的配置:

可以拖移節點來手動排列,或是使用下列設定來更精確地排放:
ScoreLabel¶
畫面配置 :「上延伸」
Text :
0
Align :「Center」
訊息¶
畫面配置 :「水平中央延長」
Text :
Dodge the Creeps!
Align :「Center」
Autostrap : 「開啟」
將 HUD 場景連接至 Main 場景¶
我們現在做好 HUD
場景了。讓我們回到 Main
。像剛才實體化 Player
場景一樣,在 Main
場景中實體化 HUD
。場景樹會看起來像這樣,檢查一下有沒有漏了什麼:

我們現在需要把 HUD
的功能連接到 Main
腳本。所以我們需要在 Main
場景內新增一點點東西:
在節點分頁中,設定 HUD 的 start_game
訊號的連接,在「連接訊號」視窗中將「Receiver 方法」設為「new_game」來將訊號連接到 Main 節點的 new_game()
函式。之後檢查看看腳本中的 ``func new_game()``旁邊有沒有出現綠色的連線圖示。
new_game()
中,需要更新分數並顯示「Get Ready」訊息:
$HUD.update_score(score)
$HUD.show_message("Get Ready")
var hud = GetNode<HUD>("HUD");
hud.UpdateScore(Score);
hud.ShowMessage("Get Ready!");
_hud->update_score(score);
_hud->show_get_ready();
game_over()
中我們需要呼叫對應的 HUD
函式:
$HUD.show_game_over()
GetNode<HUD>("HUD").ShowGameOver();
_hud->show_game_over();
最後,將這段程式碼加到 _on_ScoreTimer_timeout()
來讓分數改變的時候能同步顯示:
$HUD.update_score(score)
GetNode<HUD>("HUD").UpdateScore(Score);
_hud->update_score(score);
現在已經可以執行遊戲了!點擊「執行專案」按鈕。接著會被要求選擇一個主場景,這裡我們選 Main.tscn
。
刪除舊的怪物¶
如果一直玩到「Game Over」並直接開始新遊戲的話,上一場遊戲的怪物可能還在畫面上。開始遊戲的時候如果能讓舊的怪物消失會更好。而我們只需要告訴 所有 怪物,刪除自己。我們可以在這裡使用「群組」功能。
在 Mob
場景中,先選擇根節點,然後點擊屬性面板旁邊的「節點」分頁(跟設定節點訊號的地方相同)。點擊「訊號」旁邊的「群組」,接著編輯器會讓你設定新群組名稱,最後點擊「新增」。

Now all mobs will be in the "mobs" group. We can then add the following line to
the new_game()
function in Main
:
get_tree().call_group("mobs", "queue_free")
// Note that for calling Godot-provided methods with strings,
// we have to use the original Godot snake_case name.
GetTree().CallGroup("mobs", "queue_free");
get_tree()->call_group("mobs", "queue_free");
call_group()
函式會呼叫群組中所有節點的指定名稱的函式——在這裡我們用來讓所有怪物刪除自己。
The game's mostly done at this point. In the next and last part, we'll polish it a bit by adding a background, looping music, and some keyboard shortcuts.