Up to date

This page is up to date for Godot 4.3. If you still find outdated information, please open an issue.

遊戲資訊顯示

我們的遊戲最後還需要使用者介面(User Interface,UI),顯示分數、“遊戲結束”資訊、重啟按鈕。

Create a new scene, click the "Other Node" button 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 節點建立下列子節點:

  • Label ,命名為 ScoreLabel

  • Label ,命名為 Message

  • Button ,命名為 StartButton

  • Timer ,命名為 MessageTimer

點擊 ScoreLabel 並在屬性面板中的 Text 輸入一個數字。 Control 節點的預設字形很小,而且也縮放得不是很好。遊戲素材裡有包含了一個字形檔,檔名為「Xolonium-Regular.ttf」。依照下列步驟來使用這個字形:

在“Theme Overrides > Fonts”(主題覆蓋 > 字體)中選擇“載入”,然後選中“Xolonium-Regular.ttf”檔。

../../_images/custom_font_load_font.webp

字形尺寸仍然太小,請在“Theme Overrides > Font Sizes”(主題覆蓋 > 字形大小)下將其增加到 64 。當 ScoreLabel 完成此操作後,請重複對 MessageStartButton 節點做同樣的修改。

../../_images/custom_font_size.webp

備註

錨點與外邊距: Control 節點除了位置與大小之外,也可以設定錨點 (Anchor) 與外邊距 (Margin)。錨點定義原點(相對於節點邊緣的參考點)。外邊距則會在移動或縮放 Control 節點時自動更新。這兩個屬性的變化會反映出 Control 節點到錨點的距離。詳細說明請參考 doc_design_interfaces_with_the_control_nodes

請將節點如下圖排列。拖動節點可以手動放置,也可以使用"錨點預設(Anchor Preset)"進行更精確的定位。

../../_images/ui_anchor.webp

ScoreLabel

  1. 新增文字 0

  2. 將“Horizontal Alignment”和“Vertical Alignment”設定為 Center

  3. 為“Anchor Preset”選擇 Center Top

訊息

  1. 新增文本 : Dodge the Creeps!

  2. 將“Horizontal Alignment”和“Vertical Alignment”設定為 Center

  3. 將“Autowrap Mode”設定為 Word ,否則標籤只會有一行。

  4. 在“Control - Layout/Transform”中將“Size X”設定為 480 ,使用螢幕的完整寬度。

  5. 為“Anchor Preset”選擇 Center

StartButton

  1. TextStart

  2. 在“Control - Layout/Transform”中將“Size X”設定為 200、“Size Y”設定為 100,在邊框和文字之間新增間距。

  3. 為“Anchor Preset”選擇 Center Bottom

  4. 在“Control - Layout/Transform”中將“Position Y”設定為 580

MessageTimerWait Time 設為 2 ,將 One Shot 設為「開啟」。

現在將這個腳本新增至 HUD

extends CanvasLayer

# Notifies `Main` node that the button has been pressed
signal start_game

當我們想要暫時顯示訊息(如「Get Ready」)時可以呼叫這個函式。

func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()

當玩家輸了之後會呼叫這個函式。會在畫面上顯示 2 秒「Game Over」,然後回到標題畫面、暫停一下,最後顯示「Start」按鈕。

func show_game_over():
    show_message("Game Over")
    # Wait until the MessageTimer has counted down.
    await $MessageTimer.timeout

    $Message.text = "Dodge the Creeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    await get_tree().create_timer(1.0).timeout
    $StartButton.show()

當玩家輸了之後會呼叫這個函式。會在畫面上顯示 2 秒「Game Over」,然後回到標題畫面、暫停一下,最後顯示「Start」按鈕。

備註

需要暫停一下下的時候,除了使用 Timer 節點外也可以使用 SceneTree(場景樹)的 create_timer() 函式。當需要像上面的程式碼一樣新增一點延遲的時候很有用,上面的例子中我們用它來在顯示「Start」按鈕前增加一點點等待時間。

將以下更新分數程式碼新增到 HUD

func update_score(score):
    $ScoreLabel.text = str(score)

Connect the pressed() signal of StartButton and the timeout() signal of MessageTimer to the HUD node, and add the following code to the new functions:

func _on_start_button_pressed():
    $StartButton.hide()
    start_game.emit()

func _on_message_timer_timeout():
    $Message.hide()

將 HUD 場景連接至 Main 場景

我們現在做好 HUD 場景了。讓我們回到 Main。像剛才實體化 Player 場景一樣,在 Main 場景中實體化 HUD。場景樹會看起來像這樣,檢查一下有沒有漏了什麼:

../../_images/completed_main_scene.webp

我們現在需要把 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")

game_over() 中我們需要呼叫對應的 HUD 函式:

$HUD.show_game_over()

最後,將這段程式碼加到 _on_ScoreTimer_timeout() 來讓分數改變的時候能同步顯示:

$HUD.update_score(score)

警告

Remember to remove the call to new_game() from _ready() if you haven't already, otherwise your game will start automatically.

Now you're ready to play! Click the "Play the Project" button.

刪除舊的怪物

如果一直玩到「Game Over」並直接開始新遊戲的話,上一場遊戲的怪物可能還在畫面上。開始遊戲的時候如果能讓舊的怪物消失會更好。而我們只需要告訴 所有 怪物,刪除自己。我們可以在這裡使用「群組」功能。

In the Mob scene, select the root node and click the "Node" tab next to the Inspector (the same place where you find the node's signals). Next to "Signals", click "Groups" to open the group overview and the "+" button to open the "Create New Group" dialog.

../../_images/group_tab.webp

Name the group mobs and click "ok" to add a new scene group.

../../_images/add_group_dialog.webp

Now all mobs will be in the "mobs" group.

../../_images/scene_group_mobs.webp

We can then add the following line to the new_game() function in Main:

get_tree().call_group("mobs", "queue_free")

call_group() 函式會呼叫群組中所有節點的指定名稱的函式——在這裡我們用來讓所有怪物刪除自己。

遊戲在這一點上大部分已經完成。在下一部分和最後一部分中,我們將通過新增背景,迴圈音樂和一些鍵盤快捷鍵來對其進行一些潤色。