Godot從0開(kāi)始的教程—4.計(jì)分板
記分板、幻燈片和對(duì)話系列簡(jiǎn)介
以下三個(gè)系列是同一項(xiàng)目的一部分。他們將幫助您建立必要的基礎(chǔ)來(lái)編寫(xiě)對(duì)話系統(tǒng)。
到最后,您將編寫(xiě)分支對(duì)話系統(tǒng)的基礎(chǔ)代碼,如視覺(jué)小說(shuō)和日本角色扮演游戲中所見(jiàn)。

在第一個(gè)項(xiàng)目中,您將創(chuàng)建一個(gè)記分牌,列出用戶的姓名和高分。

然后,您將編寫(xiě)一個(gè)“游戲介紹幻燈片”。這是一系列插圖,并附有玩家可以翻閱的文字。您將對(duì)線性對(duì)話系統(tǒng)使用相同的代碼。

最后,您將在分支對(duì)話系列的顯示中添加選擇和分支。
通過(guò)這三個(gè)項(xiàng)目,您將學(xué)習(xí)如何:
在 Godot 中創(chuàng)建用戶界面。
從播放器獲取文本或按鈕輸入。
使用 GDScript 代碼動(dòng)態(tài)創(chuàng)建節(jié)點(diǎn)。
使用代碼加載和實(shí)例化場(chǎng)景。
使用字典創(chuàng)建分支數(shù)據(jù)結(jié)構(gòu)。
和更多。您將開(kāi)始使用數(shù)組、字典、信號(hào)和?onready
變量。這將建立在您目前所學(xué)的基礎(chǔ)上。
我們選擇讓您為這個(gè)項(xiàng)目創(chuàng)建用戶界面,因?yàn)樗鼈兪俏覀儼l(fā)現(xiàn)的最容易教給您的方法。
記分板是幻燈片的墊腳石,幻燈片是分支對(duì)話系統(tǒng)的墊腳石。
練習(xí)將第一次偏離課程。您將重復(fù)使用在這里學(xué)到的內(nèi)容來(lái)創(chuàng)建待辦事項(xiàng)列表、黨員狀態(tài)顯示等。
有了這個(gè),讓我們開(kāi)始我們的記分牌。
找到課程文件
首先,在 Godot 中打開(kāi)項(xiàng)目“Learn to Code with Godot: Practices”,然后在FileSystem?dock 中展開(kāi)?Scoreboard
目錄。沒(méi)有場(chǎng)景可以開(kāi),我們一起來(lái)創(chuàng)造場(chǎng)景!教程見(jiàn)!
記分牌:介紹
在本系列的第一個(gè)項(xiàng)目中,您將創(chuàng)建一個(gè)記分牌。
https://www.bilibili.com/video/BV1ik4y1n79v?p=1

我們將項(xiàng)目分為三個(gè)階段,以使其更容易消化。
首先,您將創(chuàng)建一個(gè)使用函數(shù)調(diào)用列出名稱的面板。

然后,您將添加一個(gè)表單,允許玩家輸入他們的名字并在面板中列出。

最后,您將從字典中加載現(xiàn)有名稱和分?jǐn)?shù)。這是以后支持保存和加載樂(lè)譜所必需的。
我們不會(huì)考慮從硬盤(pán)驅(qū)動(dòng)器保存或加載數(shù)據(jù)。
這是您稍后將在課程中學(xué)習(xí)的內(nèi)容,但本系列將為您提供編寫(xiě)游戲保存代碼的必要基礎(chǔ)。
設(shè)計(jì)得分面板
https://www.bilibili.com/video/BV1ik4y1n79v?p=2
在第一個(gè)視頻中,我們一起設(shè)計(jì)了高分面板。
這涉及使用專用于用戶界面的Godot節(jié)點(diǎn)。
創(chuàng)建用戶界面很復(fù)雜,所以如果您沒(méi)有從一開(kāi)始就了解所有細(xì)節(jié),請(qǐng)不要擔(dān)心。您將在課程中再次使用這些節(jié)點(diǎn),并通過(guò)實(shí)踐更好地理解它們。
新概念
控制節(jié)點(diǎn)
Godot 帶有許多專用于用戶界面 (UI) 設(shè)計(jì)的節(jié)點(diǎn):
節(jié)點(diǎn)。它們?cè)?創(chuàng)建新節(jié)點(diǎn)窗口中都有一個(gè)綠色圖標(biāo)。
為了讓您了解
節(jié)點(diǎn)的強(qiáng)大程度,您在 Godot 編輯器中看到的所有內(nèi)容本身都使用了它們。
當(dāng)您設(shè)計(jì)用戶界面時(shí),您需要可以自由嵌套和組合的框和小部件。
不同的游戲和應(yīng)用程序需要不同的用戶界面,因此 UI 設(shè)計(jì)系統(tǒng)往往既靈活又復(fù)雜。
這就是為什么 Godot 的節(jié)點(diǎn)在Inspector
中帶有許多部分和屬性。
每個(gè)
節(jié)點(diǎn)都是一個(gè)可調(diào)整大小的框,它相對(duì)于父框進(jìn)行錨定和調(diào)整大小,最大的是游戲窗口。在視頻中,您可以看到當(dāng)我們選擇一個(gè)節(jié)點(diǎn)并使用?Layout -> Full Rect時(shí)。四個(gè)綠色別針代表記分牌的定位點(diǎn)。

節(jié)點(diǎn)框和這些引腳之間的距離定義了節(jié)點(diǎn)的邊距(下面的黃色箭頭)。

當(dāng)玩家調(diào)整游戲窗口大小時(shí),計(jì)分板也會(huì)調(diào)整大小但相對(duì)于游戲窗口的角保持固定邊距。

集裝箱
節(jié)點(diǎn)是節(jié)點(diǎn)的子類別 ,可以自動(dòng)重新定位和調(diào)整其 子節(jié)點(diǎn)的大?。?/p>
拉伸它的孩子以適應(yīng)面板。
對(duì)其子項(xiàng)強(qiáng)制執(zhí)行固定邊距。
將其子項(xiàng)排列在一列中。
Godot 帶有所有基本容器來(lái)顯示
行、列、網(wǎng)格等中的其他節(jié)點(diǎn)。使用 Label 節(jié)點(diǎn)顯示文本
該
節(jié)點(diǎn)允許您繪制未格式化的行或文本段落。它具有可用于大寫(xiě)、換行或重新對(duì)齊文本的設(shè)置。
這就是這部分的內(nèi)容。在下一課中,您將僅使用代碼在看板上顯示姓名列表。
使用主題設(shè)計(jì)記分牌
https://www.bilibili.com/video/BV1ik4y1n79v?p=3
在本視頻中,我們使用 Godot 的資源為我們的界面提供默認(rèn)字體和更好的面板樣式。
新概念
資源
在 Godot 中,資源通常是您插入節(jié)點(diǎn)的文件。紋理、聲音和字體都是資源的示例。
我們?cè)诒疽曨l中查看了其中的幾個(gè):資源、以及我們分配給記分牌面板的 。
更準(zhǔn)確地說(shuō),資源是 Godot 高效加載和重用的數(shù)據(jù)容器。
您游戲的大部分共享數(shù)據(jù)都將依賴于資源,例如您在整個(gè)用戶界面中重復(fù)使用的字體。
下面概述的每個(gè)塊對(duì)應(yīng)于一種不同類型的資源。

字體文件
您的計(jì)算機(jī)使用字體文件來(lái)繪制文本。

這些文件包含每個(gè)文本字符的繪圖,采用稱為矢量的特定圖像格式。它允許計(jì)算機(jī)繪制任何大小的文本,而不會(huì)使文本變得模糊或像素化。

常見(jiàn)的字體文件擴(kuò)展名是.ttf
(TrueType 字體:Apple 的專有格式)和.otf
(OpenType 字體:一種開(kāi)放格式)。
Godot中的動(dòng)態(tài)字體資源
要更改文本的字體和繪圖大小,Godot 需要您創(chuàng)建一個(gè)資源。該資源使用一個(gè)字體文件來(lái)繪制文本,并使用一些設(shè)置來(lái)更改文本大小、線條大小等。

在分?jǐn)?shù)面板中列出名稱
在本課中,我們將向記分板添加代碼以顯示姓名列表。

右鍵單擊Scoreboard節(jié)點(diǎn)并選擇Attach Script為其提供一個(gè)新腳本。

確保模板設(shè)置為Empty,然后單擊?Create。

我們想要在ScoresColumn節(jié)點(diǎn)中列出姓名和分?jǐn)?shù)。對(duì)于每個(gè)名稱,我們將使用一個(gè)?Label
節(jié)點(diǎn)。
由于我們需要各種名稱,因此我們不想手動(dòng)創(chuàng)建標(biāo)簽節(jié)點(diǎn)。
相反,我們將使用代碼動(dòng)態(tài)創(chuàng)建標(biāo)簽。
使用代碼創(chuàng)建節(jié)點(diǎn)
到目前為止,我們已經(jīng)使用“創(chuàng)建新節(jié)點(diǎn)”窗口在編輯器中創(chuàng)建了節(jié)點(diǎn)。

您還可以使用 GDScript 代碼創(chuàng)建節(jié)點(diǎn),如下所示:
您編寫(xiě)節(jié)點(diǎn)類型的名稱后跟?
.new()
。例如,Timer.new()
,或?Sprite.new()
。您可以使用節(jié)點(diǎn)的屬性(例如
Sprite.texture
.您可以使用成員函數(shù)將其添加為另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)?
add_child()
。
在您添加一個(gè)節(jié)點(diǎn)作為另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)之前,它只存在于計(jì)算機(jī)的內(nèi)存中,不會(huì)影響顯示。
下面是使用代碼創(chuàng)建節(jié)點(diǎn)的代碼示例?Label
。
另一個(gè)創(chuàng)建一個(gè)?Timer
.
使用代碼的好處是我們可以根據(jù)需要?jiǎng)?chuàng)建任意數(shù)量的節(jié)點(diǎn),而無(wú)需事先知道它們的數(shù)量。
創(chuàng)建標(biāo)簽的函數(shù)
讓我們編寫(xiě)一個(gè)函數(shù)來(lái)將名稱添加到記分板。我們將調(diào)用它,?add_line()
因?yàn)槲覀兩院髮⑹褂盟鼇?lái)注冊(cè)玩家的姓名和分?jǐn)?shù)。
我們首先創(chuàng)建一個(gè)?Label
節(jié)點(diǎn)并將對(duì)它的引用存儲(chǔ)在?line
變量中。text
?然后我們通過(guò)變量訪問(wèn)標(biāo)簽的成員變量line
。
設(shè)置節(jié)點(diǎn)不會(huì)使其出現(xiàn)在屏幕上。要顯示標(biāo)簽,我們必須將它添加到我們的節(jié)點(diǎn)樹(shù)中。
我們想添加標(biāo)簽作為ScoresColumn節(jié)點(diǎn)的子節(jié)點(diǎn),以便它們垂直排列。
所以我們首先獲取ScoresColumn節(jié)點(diǎn),并add_child()
函數(shù)將其添加為它的子節(jié)點(diǎn)。
注意:在 Godot 中, the$
是函數(shù)的別名get_node()
。
你給它一個(gè)節(jié)點(diǎn)的路徑,函數(shù)返回一個(gè)對(duì)該節(jié)點(diǎn)的引用。獲取節(jié)點(diǎn)允許您訪問(wèn)節(jié)點(diǎn)的函數(shù)和變量。
將分?jǐn)?shù)列存儲(chǔ)在變量中
您可以看到ScoresColumn的節(jié)點(diǎn)路徑很長(zhǎng)且難以閱讀。我們的代碼用一個(gè)變量來(lái)標(biāo)記它會(huì)更具可讀性。
GDScript 中的一個(gè)好習(xí)慣是為您在腳本頂部使用的節(jié)點(diǎn)創(chuàng)建成員變量。
它一目了然地向您顯示腳本工作所需的節(jié)點(diǎn)。
但是,我們不能只將節(jié)點(diǎn)存儲(chǔ)在成員變量中。在訪問(wèn)節(jié)點(diǎn)之前,我們需要等待節(jié)點(diǎn)處于就緒狀態(tài)。
等待節(jié)點(diǎn)準(zhǔn)備就緒
當(dāng)您運(yùn)行一個(gè)場(chǎng)景時(shí),Godot 會(huì)創(chuàng)建節(jié)點(diǎn)并將它們按順序添加到場(chǎng)景樹(shù)中。在此之前,您的代碼中無(wú)法訪問(wèn)子節(jié)點(diǎn):您無(wú)法使用符號(hào)$
來(lái)訪問(wèn)該節(jié)點(diǎn)。
我們說(shuō)節(jié)點(diǎn)還沒(méi)有準(zhǔn)備好。
Godot 提供了一個(gè)特殊的函數(shù),你可以編寫(xiě)它來(lái)在所有子節(jié)點(diǎn)就緒時(shí)運(yùn)行代碼:
您可以使用它來(lái)獲取子節(jié)點(diǎn)并將其存儲(chǔ)在腳本成員變量中。
然后,每次你想訪問(wèn)ScoresColumn節(jié)點(diǎn)時(shí),你可以寫(xiě)scores_column
.
onready快捷方式
由于分配對(duì)變量的引用非常普遍,GDScript 提供了一個(gè)關(guān)鍵字來(lái)在子項(xiàng)準(zhǔn)備好時(shí)設(shè)置變量:?onready
。
我們可以使用它將ScoresColumn存儲(chǔ)在變量中。您需要在add_line()
?函數(shù)上方添加以下行。
請(qǐng)注意,必須onready
位于?var
關(guān)鍵字之前。此外,它僅在定義成員變量時(shí)有效。
通過(guò)上面的行,您可以在函數(shù)中使用變量?add_line()
。您的代碼應(yīng)如下所示:
將名字添加到樂(lè)譜
要向記分牌添加一條線,您需要調(diào)用該?add_line()
函數(shù)。
我們必須在函數(shù)內(nèi)部執(zhí)行此_ready()
操作,因?yàn)樵?add_line()
函數(shù)需要ScoresColumn?節(jié)點(diǎn)。
您可以根據(jù)需要多次調(diào)用該函數(shù)。如果您運(yùn)行場(chǎng)景 (?F6),您應(yīng)該會(huì)看到一個(gè)名稱列表。

你的問(wèn)題
_ready() 是如何保證我能拿到節(jié)點(diǎn)的?
函數(shù)和函數(shù)_ready()
一樣_process()
?,是在Godot引擎中定義的。它存在于每個(gè)節(jié)點(diǎn)上。
當(dāng)您運(yùn)行一個(gè)場(chǎng)景時(shí),Godot 會(huì)讀取您的場(chǎng)景文件并準(zhǔn)備創(chuàng)建一個(gè)節(jié)點(diǎn)樹(shù)。
Godot 首先從上到下依次創(chuàng)建節(jié)點(diǎn)。
然后,Godot_ready()
按照兩個(gè)規(guī)則調(diào)用節(jié)點(diǎn)上的函數(shù):
引擎從上到下處理節(jié)點(diǎn)。
每當(dāng)節(jié)點(diǎn)有子節(jié)點(diǎn)時(shí),引擎都會(huì)
_ready()
?在父節(jié)點(diǎn)之前調(diào)用子節(jié)點(diǎn)。
在我們的記分板場(chǎng)景中,引擎將從上到下創(chuàng)建節(jié)點(diǎn),使它們可以使用,從 開(kāi)始
,然后是 ,然后是ScoresColumn,順序如下。
然后,它會(huì)讓父級(jí)?VBoxContainer
準(zhǔn)備就緒,然后是,最后是?記分牌。?MarginContainer
這種方法允許您讓子節(jié)點(diǎn)在將它們放入函數(shù)_ready()
或使用onready
關(guān)鍵字之前正確地初始化它們自己。
“虛”是什么意思?
and 函數(shù)定義void
后的關(guān)鍵字表示函數(shù)不返回值。add_line()
_ready()
如果您指定該函數(shù)是void
,如果您或隊(duì)友試圖從中返回一個(gè)值,Godot 會(huì)警告您。
代碼
這是第一課的完整代碼。
添加表單以輸入您的姓名
在本課中,您將添加一個(gè)字段,讓玩家將他們的名字添加到記分牌中。

我們將首先設(shè)計(jì)一個(gè)帶有確認(rèn)按鈕的名稱表單,讓玩家輸入他們的名字。
然后,我們將編寫(xiě)將字段中鍵入的名稱注冊(cè)到記分板的功能。
在下一課中,我們將添加一個(gè)按鈕來(lái)隱藏記分板并返回到窗體。

這將允許您在記分牌中輸入多個(gè)名稱。
創(chuàng)建 ScoreForm 場(chǎng)景
要添加表單并使其與記分板通信,我們需要一個(gè)包含表單和記分板實(shí)例的場(chǎng)景。
轉(zhuǎn)到Scene -> New Scene創(chuàng)建一個(gè)新的空?qǐng)鼍?,然后單擊Scene?dock中的User Interface按鈕。

一個(gè)

我們想要一行包含一個(gè)輸入字段和一個(gè)表單按鈕。
選擇ScoreForm后,創(chuàng)建一個(gè)新
節(jié)點(diǎn)。該 節(jié)點(diǎn)將其子節(jié)點(diǎn)排成一行。然后,創(chuàng)建一個(gè)
節(jié)點(diǎn)和一個(gè) 作為 .?將 重命名 為NameField并將 重命名 為OkButton。到目前為止,您的場(chǎng)景應(yīng)該如下所示。

使表格更寬
我們的表單很小,卡在視圖的左上角。
我們需要幾個(gè)步驟才能使其沿著ScoreForm節(jié)點(diǎn)邊界框的上邊緣延伸 :
首先,選擇
,然后在頂部的工具欄中單擊Layout -> Top Wide。

? 2.選擇后
,單擊并拖動(dòng)底部調(diào)整大小手柄以使容器更高。
? 3.選擇名稱字段。在Inspector中,打開(kāi)Size Flags -> Horizontal中的Expand復(fù)選框。

名稱字段現(xiàn)在應(yīng)該擠壓視圖右上角的按鈕。

將節(jié)點(diǎn)設(shè)置為在容器內(nèi)擴(kuò)展會(huì)使其增長(zhǎng)并將同級(jí)節(jié)點(diǎn)推至最小尺寸。
我們可以通過(guò)給它一些文本來(lái)增加按鈕的最小寬度。選擇OkButton并在Inspector中將其Text設(shè)置為“Ok”?。

當(dāng)我們這樣做的時(shí)候,讓我們選擇 NameField并給它一些占位符文本。在Inspector中,展開(kāi)其?Placeholder類別并將Text設(shè)置為類似“Enter your name”的內(nèi)容。

然后,您可以選擇ScoreForm,按Alt,然后單擊并拖動(dòng)其中一個(gè)角調(diào)整大小手柄以使其變小。

如您所見(jiàn),文本看起來(lái)與記分牌不同。要解決這個(gè)問(wèn)題,請(qǐng)選擇ScoreForm并在Inspector中展開(kāi)。右鍵單擊?[empty]插槽并選擇Quick Load。

加載scoreboard_theme.tres
我們之前保存的文件。
實(shí)例化記分牌場(chǎng)景
當(dāng)我們點(diǎn)擊OkButton時(shí),我們想要顯示?帶有輸入名稱的記分牌。為此,我們需要添加記分板的實(shí)例作為表單的子項(xiàng)。這將允許我們調(diào)用它的add_line()
函數(shù)。
選擇ScoreForm并單擊場(chǎng)景??繖陧敳康逆溄訄D標(biāo)以打開(kāi)實(shí)例子場(chǎng)景?窗口。

搜索Scoreboard.tscn
并按Enter添加節(jié)點(diǎn)。
我們想先看到表格,但Scoreboard將其隱藏。單擊場(chǎng)景??繖谥杏浄职迮赃叺难劬D標(biāo)?以默認(rèn)隱藏它。

你的場(chǎng)景應(yīng)該是這樣的。

請(qǐng)將場(chǎng)景保存在目錄Scoreboard.tscn
中的文件旁邊Scoreboard/
。
設(shè)計(jì)好表單后,我們就可以添加代碼并在記分板上顯示輸入的名稱。我們將在下一課中這樣做。
按確定按鈕時(shí)添加分?jǐn)?shù)
當(dāng)玩家點(diǎn)擊OkButton時(shí),我們想要注冊(cè)他們?cè)谟浄职迳陷斎氲拿帧?/p>
為此,我們需要:
將新腳本附加到ScoreForm。
將OkButton的
pressed
信號(hào)連接到?ScoreForm。獲取記分板節(jié)點(diǎn)并調(diào)用其?
add_line()
函數(shù)。
右鍵單擊ScoreForm節(jié)點(diǎn)并選擇附加腳本為其創(chuàng)建一個(gè)空腳本。我們需要腳本來(lái)連接按鈕的信號(hào)。

連接按鈕的按下信號(hào)
選擇OkButton節(jié)點(diǎn)。

在pressed
信號(hào)并將其連接到?ScoreForm。

這會(huì)將您帶到腳本編輯器并創(chuàng)建一個(gè)新?_on_OkButton_pressed()
函數(shù)。
按下按鈕時(shí)注冊(cè)名稱
我們需要訪問(wèn) Scoreboard和NameField?節(jié)點(diǎn)以使用玩家輸入的文本。
所以我們onready
在腳本的頂部定義了兩個(gè)變量。
然后,我們可以?在回調(diào)函數(shù)中調(diào)用Scoreboard的函數(shù)。add_line()
我們還調(diào)用它的show()
?函數(shù)使其可見(jiàn)并重置NameField以清空該字段?text
。
用按鈕隱藏記分牌
當(dāng)玩家輸入名字時(shí),他們會(huì)卡在記分牌上。

我們可以使用 a?Button
及其pressed
信號(hào)來(lái)隱藏面板。
在Scoreboard場(chǎng)景中,選擇?VBoxContainer
節(jié)點(diǎn)并添加一個(gè)新的?Button
名為HideButton的子節(jié)點(diǎn)。

在檢查器頂部?將按鈕的文本設(shè)置為“隱藏” 。

該按鈕水平拉伸以填充它可用的空間。我們想把它放在左下角。
為此,我們必須進(jìn)行兩項(xiàng)更改:
使ScoresColumn垂直展開(kāi)并按下按鈕。
將按鈕更改為不填充所有可用的水平空間。
選擇ScoresColumn并在Inspector中,向下轉(zhuǎn)到Size Flags類別。展開(kāi)它并選中?Vertical旁邊的Expand復(fù)選框。

Vertical標(biāo)志使容器內(nèi)的控制節(jié)點(diǎn)嘗試使自己盡可能高。
然后,選擇HideButton并在Size Flags?類別中,取消選中Horizontal旁邊的?Fill復(fù)選框。

Fill標(biāo)志進(jìn)行?Control
拉伸以占用所有水平或垂直軸空間。
連接按鈕的按下信號(hào)
選擇HideButton后,前往?Node
dock 將其信號(hào)連接pressed
到Scoreboard。

在 Godot 為我們創(chuàng)建的函數(shù)中,?_on_HideButton_pressed()
我們想調(diào)用?hide()
.?單擊按鈕后它將隱藏記分牌。
代碼
到目前為止,這是ScoreForm和?Scoreboard的完整代碼。
ScoreForm.gd
Scoreboard.gd
將分?jǐn)?shù)添加到記分板表單
在本課中,我們將在表單和記分牌中添加一個(gè)分?jǐn)?shù)字段。

我們將首先更新記分板以在每一行中接受一個(gè)名字和一個(gè)分?jǐn)?shù)。
我們將創(chuàng)建一個(gè)代表一條得分線的新場(chǎng)景來(lái)實(shí)現(xiàn)這一點(diǎn)。
然后我們將在表單中添加一個(gè)分?jǐn)?shù)字段,并在按下 OkButton 時(shí)將玩家姓名和分?jǐn)?shù)發(fā)送到記分?牌。
創(chuàng)建 ScoreLine 場(chǎng)景
我們將首先設(shè)計(jì)一個(gè)場(chǎng)景來(lái)表示一行。
它應(yīng)該是一排,其中一個(gè)
代表分?jǐn)?shù),另一個(gè)代表球員的名字。
創(chuàng)建一個(gè)新場(chǎng)景并單擊其他節(jié)點(diǎn)按鈕以創(chuàng)建一個(gè)
.
將節(jié)點(diǎn)重命名為ScoreLine并添加兩個(gè)
節(jié)點(diǎn)作為其子節(jié)點(diǎn)。將節(jié)點(diǎn)分別重命名
為PointsLabel和?NameLabel以區(qū)別它們。
我們可以將分?jǐn)?shù)染成黃色,以將其與球員姓名區(qū)分開(kāi)來(lái)。
首先,我們要為每個(gè)標(biāo)簽添加一些占位符文本。為此,選擇每個(gè)節(jié)點(diǎn)并在Inspector中,在其文本字段中寫(xiě)入一些內(nèi)容?。

然后,選擇PointsLabel。在Inspector中,向下滾動(dòng)到節(jié)點(diǎn)部分下方的Visibility
類別。展開(kāi)類別并將調(diào)制顏色更改為黃色。

將場(chǎng)景保存在目錄中,并通過(guò)右鍵單擊腳本并選擇附加腳本Scoreboard/
將腳本附加到ScoreLine節(jié)點(diǎn)。
我們定義了兩個(gè)函數(shù),我們將用作記分板的接口?來(lái)顯示分?jǐn)?shù)和名稱。
這兩個(gè)功能相似:它們更新標(biāo)簽的文本。
與直接訪問(wèn)節(jié)點(diǎn)(如points_label
.
它允許您稍后在函數(shù)內(nèi)添加指令,而不會(huì)導(dǎo)致游戲出錯(cuò)。
使用記分牌中的新 ScoreLine
打開(kāi)Scoreboard腳本并將?add_line()
函數(shù)替換為以下代碼。我們稍后會(huì)分解它。
在第一行,我們做了兩件事:
預(yù)加載ScoreLine場(chǎng)景。
創(chuàng)建一個(gè)新實(shí)例并將其存儲(chǔ)在
line
?變量中。
該preload()
函數(shù)允許您使用絕對(duì)或相對(duì)路徑加載資源文件,如場(chǎng)景。
這是一個(gè)特殊的函數(shù),它告訴 Godot 在啟動(dòng)游戲時(shí)加載一次場(chǎng)景,然后將其保存在內(nèi)存中。這樣,我們可以快速創(chuàng)建它的新實(shí)例。
像以前一樣,我們將行添加為ScoresColumn的子級(jí)。在這種情況下,場(chǎng)景實(shí)例有點(diǎn)像節(jié)點(diǎn):您可以將其添加為另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)。
最后兩行調(diào)用我們?cè)?ScoreLine場(chǎng)景中定義的兩個(gè)函數(shù),分別傳遞球員姓名和得分。
將分?jǐn)?shù)字段添加到 ScoreForm
現(xiàn)在,我們將向ScoreForm添加一個(gè) points 字段。
打開(kāi)ScoreForm場(chǎng)景并復(fù)制?NameField節(jié)點(diǎn)。將新節(jié)點(diǎn)重命名為?PointsField。

在Inspector中,我們可以刪除Placeholder -> Text。

在腳本中,我們需要在一個(gè)新?onready
變量中獲取我們的點(diǎn)字段。在頂部周圍,添加變量。
然后,我們需要更新我們的信號(hào)回調(diào)函數(shù)。
我們更新對(duì)Scoreboard.add_line()
函數(shù)的調(diào)用并將PointField的文本傳遞給它。
目前,即使字段為空,玩家也可以將新名稱和分?jǐn)?shù)添加到記分牌中。
我們可以在函數(shù)的開(kāi)頭使用條件來(lái)防止這種情況發(fā)生。
return
?請(qǐng)注意,在上面的代碼清單中,我們沒(méi)有在關(guān)鍵字后面寫(xiě)任何內(nèi)容。寫(xiě)入只是return
結(jié)束函數(shù)的執(zhí)行,并不返回任何值。
此代碼更改完成了本課程。您現(xiàn)在可以運(yùn)行場(chǎng)景,輸入名稱和分?jǐn)?shù),它應(yīng)該會(huì)出現(xiàn)在記分牌上。

我們代碼的限制
從技術(shù)上講,您可以在分?jǐn)?shù)字段中鍵入任何文本。
我們不會(huì)費(fèi)心確保您在此處輸入數(shù)字,因?yàn)樵谕暾挠螒蛑?,系統(tǒng)會(huì)為玩家計(jì)算分?jǐn)?shù)。
實(shí)踐:庫(kù)存網(wǎng)格
打開(kāi)實(shí)踐庫(kù)存網(wǎng)格。
完成練習(xí)后,跑步場(chǎng)景應(yīng)如下所示。

練習(xí):詩(shī)歌
打開(kāi)練習(xí)詩(shī)。
運(yùn)行場(chǎng)景應(yīng)該是這樣的。

挑戰(zhàn):待辦事項(xiàng)清單
打開(kāi)練習(xí)待辦事項(xiàng)列表。
最終結(jié)果應(yīng)該是這樣的。

代碼
這是到目前為止場(chǎng)景的完整代碼。
ScoreLine.gd
Scoreboard.gd
ScoreForm.gd
使用字典加載現(xiàn)有樂(lè)譜
在最后一部分中,我們從數(shù)組中“加載”現(xiàn)有分?jǐn)?shù)。

您將在此處看到的是保存和加載數(shù)據(jù)的基礎(chǔ),您將在本課程的后面學(xué)習(xí)實(shí)際操作。
我們將對(duì)分支對(duì)話系統(tǒng)使用相同的技術(shù)。
使用數(shù)據(jù)而不是函數(shù)調(diào)用
到目前為止,我們直接調(diào)用函數(shù)將分?jǐn)?shù)添加到記分板。
但是如果你退出游戲再回來(lái),每次的棋盤(pán)都是空的,因?yàn)槟愕墓?jié)點(diǎn)和變量只存在于計(jì)算機(jī)的臨時(shí)內(nèi)存中。
要保存樂(lè)譜,您需要將樂(lè)譜寫(xiě)入計(jì)算機(jī)硬盤(pán)上的文件中。
你是怎樣做的?您將分?jǐn)?shù)作為數(shù)據(jù)存儲(chǔ)在變量中。
與大多數(shù)語(yǔ)言一樣,Godot 具有內(nèi)置工具,可以從文件中編寫(xiě)和加載字典、數(shù)組、文本等。
在這種情況下,我們需要將玩家的名字映射到他們的分?jǐn)?shù),因此我們將使用字典。
將名稱和分?jǐn)?shù)表示為字典數(shù)組
打開(kāi)記分板腳本。如果手邊沒(méi)有它,可以按Ctrl+?Alt+O使用?“快速打開(kāi)腳本”窗口。

我們添加一個(gè)名為 : 的新成員變量player_scores
,將玩家的名字映射到他們的分?jǐn)?shù)。
每個(gè)鍵是一個(gè)玩家的名字,對(duì)應(yīng)的值是他們的整數(shù)分?jǐn)?shù)。
我會(huì)讓你像上面那樣寫(xiě)幾個(gè)名字和分?jǐn)?shù)對(duì)。
在計(jì)分板上顯示分?jǐn)?shù)
為了將分?jǐn)?shù)“加載”到記分板中,我們定義了函數(shù)?_ready()
并循環(huán)遍歷每個(gè)分?jǐn)?shù)。
player_scores
我們通過(guò)調(diào)用 函數(shù)在記分牌中為字典中的每個(gè)名字添加一行?add_line()
。
我們可以使用您在從零開(kāi)始學(xué)習(xí) GDScript 應(yīng)用程序中學(xué)習(xí)的字典訪問(wèn)符號(hào)來(lái)獲得每個(gè)名稱的分?jǐn)?shù):?player_scores[name]
。
更新玩家的分?jǐn)?shù)
除了在我們的字典中顯示分?jǐn)?shù)之外,我們還想讓它們保持最新。
如果玩家打破了他們之前的最佳成績(jī),或者如果新玩家完成了游戲,我們希望對(duì)其進(jìn)行跟蹤。
我們更新add_line()
函數(shù)以存儲(chǔ)新玩家得分。
如果您現(xiàn)在運(yùn)行ScoreForm場(chǎng)景,在輸入姓名和分?jǐn)?shù)后,您應(yīng)該會(huì)看到您的姓名已添加到列表底部。

稍后,您將學(xué)習(xí)如何從硬盤(pán)保存和加載數(shù)據(jù)以及如何正確構(gòu)建數(shù)據(jù)。
但我們必須一步一個(gè)腳印。
您在這個(gè)項(xiàng)目中學(xué)到了許多新技術(shù)。在接下來(lái)的兩個(gè)項(xiàng)目中,您將重用和構(gòu)建您在這里學(xué)到的知識(shí)。
代碼
這是該項(xiàng)目的完整代碼。
ScoreLine.gd
Scoreboard.gd
ScoreForm.gd
創(chuàng)建節(jié)點(diǎn)和場(chǎng)景實(shí)例
本指南回顧了如何創(chuàng)建節(jié)點(diǎn)和場(chǎng)景的實(shí)例。
我們將討論:
new()
調(diào)用和 函數(shù)的區(qū)別instance()
。如何使用
new()
.如何使用?
instance()
.如何將實(shí)例添加為其他節(jié)點(diǎn)的子節(jié)點(diǎn)?
add_child()
。何時(shí)應(yīng)使用代碼創(chuàng)建節(jié)點(diǎn)。
如何加載場(chǎng)景文件、腳本或資源。
load()
和 功能的區(qū)別preload()
。
如果我們將編程比作烹飪,將 Godot 引擎比作廚師:
腳本就是食譜。_?它描述了如何制作一道新菜。我們可以根據(jù)細(xì)節(jié)定制每道菜,例如添加更多或更少的鹽。這種定制將是您的變量。從?腳本中,我們可以創(chuàng)建新節(jié)點(diǎn)。
一個(gè)場(chǎng)景文件是一個(gè)完整的菜單。這是一堆帶有配料的食譜,因此 Godot 可以按照您最初設(shè)計(jì)的那樣精確地重新制作多道菜肴。我們從場(chǎng)景文件創(chuàng)建節(jié)點(diǎn)分支。
腳本和場(chǎng)景文件都是您制作復(fù)制品的模板。
和函數(shù)new()
_?instance()
有兩個(gè)函數(shù)分別創(chuàng)建一個(gè)節(jié)點(diǎn)和一個(gè)場(chǎng)景實(shí)例:new()
和instance()
。
new()
如果您想要一個(gè)?腳本實(shí)例,或者您想要一個(gè)場(chǎng)景instance()
實(shí)例,您可以使用。
注意:雖然instance()
僅用于場(chǎng)景,new()
但也用于比節(jié)點(diǎn)更多的類型。您將在課程的后面了解到這一點(diǎn)。
函數(shù).new()
_
創(chuàng)建特定節(jié)點(diǎn)類型時(shí),您使用?Object.new()
.?它是Godot中存在于腳本和內(nèi)置對(duì)象類型(節(jié)點(diǎn)是特定類型的對(duì)象)上的函數(shù)?。
下面,我們使用該new()
函數(shù)以編程方式創(chuàng)建三個(gè)按鈕。
當(dāng) Godot 讀到這一行時(shí)?var button := Button.new()
:
它使用配方。
它創(chuàng)建了
.
當(dāng)您使用場(chǎng)景??繖谥械奶砑庸?jié)點(diǎn)按鈕(或按?+ )在編輯器中添加節(jié)點(diǎn)時(shí),在幕后,Godot 會(huì)調(diào)用?.CtrlA.new()


函數(shù)instance()
_
創(chuàng)建場(chǎng)景實(shí)例時(shí),您使用?.instance()
.?例如:
當(dāng) Godot 讀到這一行時(shí)?var heart_pickup := pickup_heart_scene.instance()
:
它使用
pickup_heart_scene
?菜單。它再現(xiàn)了您在編輯器中設(shè)計(jì)的場(chǎng)景。
當(dāng)您在編輯器中打開(kāi)場(chǎng)景文件,或在場(chǎng)景eock 中使用添加場(chǎng)景實(shí)例按鈕添加場(chǎng)景?(或按?+?+?)時(shí),Godot 會(huì)?在幕后調(diào)用。CtrlShiftA.instance()


函數(shù)add_child()
?_
一旦你有了一個(gè)實(shí)例,無(wú)論你使用instance()
?還是new()
,你都會(huì)想要將它添加到場(chǎng)景樹(shù)中。不在場(chǎng)景樹(shù)中的節(jié)點(diǎn)不執(zhí)行任何操作。
你這樣做add_child()
:
上面的代碼可以生成如下所示的節(jié)點(diǎn)樹(shù):

什么時(shí)候應(yīng)該在代碼或編輯器中創(chuàng)建節(jié)點(diǎn)
一般來(lái)說(shuō),最好從編輯器中創(chuàng)建節(jié)點(diǎn)和場(chǎng)景。您可以獲得更好的視覺(jué)預(yù)覽,并且可以使用?Inspector調(diào)整屬性。
但請(qǐng)考慮以下情況:
您需要一個(gè)箱子來(lái)提供隨機(jī)物品。
您需要敵人數(shù)量不斷增加。
您需要列出玩家所有已占用的保存槽。
您有一個(gè)清單,其中可以包含玩家拾取的任何物品。
你有一個(gè)高分板,可以加載最好的球員并顯示他們。
在這些示例中使用編輯器創(chuàng)建節(jié)點(diǎn)很困難,因?yàn)槟€不知道需要什么。
那就是您會(huì)喜歡使用代碼創(chuàng)建節(jié)點(diǎn)的時(shí)候。
我們?nèi)绾渭虞d場(chǎng)景文件、腳本或資源?
Godot 讓我們通過(guò)將文件路徑作為參數(shù)傳遞給函數(shù)來(lái)加載文件preload()
。
運(yùn)行場(chǎng)景時(shí),此函數(shù)會(huì)在屏幕上顯示任何內(nèi)容之前加載文件。
您可以通過(guò)右鍵單擊文件并從上下文菜單中選擇復(fù)制路徑來(lái)從文件系統(tǒng)??繖趶?fù)制文件的絕對(duì)路徑。
您還可以使用快捷鍵?Ctrl+?Shift+C來(lái)更快地完成它。
例如:
使用相對(duì)文件路徑preload()
我們建議盡可能使用相對(duì)路徑,因?yàn)樗梢愿p松地在您的 Godot 項(xiàng)目中移動(dòng)文件。
例如,如果你要加載的場(chǎng)景與你正在使用的腳本在同一個(gè)目錄中,你可以這樣寫(xiě)路徑:
當(dāng)您在編輯器中打開(kāi)資源時(shí),Godot 會(huì)在后臺(tái)使用相同的機(jī)制加載它。
使用?load()
函數(shù)代替preload()
如果您事先不知道資源的路徑,則無(wú)法使用該preload()
功能。相反,您將使用該?load()
函數(shù)。
例如:
上面的代碼將加載一個(gè)名為 的圖像?res://common/arrows/arrow_west_red.png
,但我們可以動(dòng)態(tài)更改color
和direction
以加載不同的文件。
該load()
函數(shù)與 有重要區(qū)別?preload()
:
編輯器不檢查路徑。如果通過(guò)調(diào)用加載一個(gè)不存在的文件
load()
,編輯器無(wú)法提前知道。使用preload()
,如果你使用了錯(cuò)誤的路徑,編輯器會(huì)立即報(bào)錯(cuò)。路徑不能是相對(duì)的。該函數(shù)
load()
?只接受絕對(duì)路徑。
信號(hào):連接和良好實(shí)踐
本指南回顧了到目前為止我們所看到的有關(guān)信號(hào)的所有內(nèi)容:
如何使用代碼或編輯器連接信號(hào)。
何時(shí)使用任一連接方法。
回調(diào)函數(shù)是什么以及如何命名它們。
信號(hào)是節(jié)點(diǎn)在發(fā)生某些事情時(shí)發(fā)出的消息。例如,當(dāng)您單擊 a 時(shí)pressed
?信號(hào)。

通過(guò)將信號(hào)連接到節(jié)點(diǎn),您可以讓 Godot 在每次信號(hào)發(fā)出時(shí)調(diào)用該節(jié)點(diǎn)的函數(shù)。我們稱該函數(shù)為回調(diào),因?yàn)樗谛盘?hào)發(fā)出時(shí)被“回調(diào)”。
連接信號(hào)
連接信號(hào)有兩種方式:
在 Godot 編輯器中使用Node dock。
通過(guò)在代碼中調(diào)用
connect()
函數(shù)。
何時(shí)連接代碼或編輯器
在以下情況下使用編輯器連接信號(hào):
您不需要?jiǎng)討B(tài)創(chuàng)建節(jié)點(diǎn)。
您更喜歡在場(chǎng)景??繖诤湍_本編輯器中看到信號(hào)連接的視覺(jué)指示。
你想讓 Godot 為你創(chuàng)建回調(diào)函數(shù)。
在以下情況下使用代碼連接信號(hào):
您使用代碼動(dòng)態(tài)地實(shí)例化節(jié)點(diǎn)或場(chǎng)景。
您更喜歡將信號(hào)連接和回調(diào)函數(shù)放在同一個(gè)文件中。
讓我們看看如何使用這兩種方法連接按鈕的pressed
信號(hào)。我們將再次使用記分板場(chǎng)景的?HideButton節(jié)點(diǎn)作為示例。

如何使用編輯器連接
要使用編輯器連接信號(hào),請(qǐng)?jiān)趫?chǎng)景??繖谥羞x擇包含要連接的信號(hào)的節(jié)點(diǎn)。

在界面的右側(cè),前往Inspector旁邊的Node?dock 。??繖诹谐隽怂x節(jié)點(diǎn)的信號(hào)。

雙擊要連接的信號(hào)以打開(kāi)信號(hào)連接窗口。

您連接到的節(jié)點(diǎn)必須附加一個(gè)腳本,以便 Godot 創(chuàng)建它所謂的接收方方法(回調(diào)函數(shù))。

您可以連接的節(jié)點(diǎn)的名稱將顯示為白色,而其他節(jié)點(diǎn)則顯示為灰色。
雙擊節(jié)點(diǎn)或單擊“連接”以連接信號(hào)。
如果回調(diào)函數(shù)尚不存在,Godot 將自動(dòng)在腳本中創(chuàng)建回調(diào)函數(shù)。它還會(huì)將您帶到腳本編輯器并滾動(dòng)到連接的功能。

與編輯器連接時(shí),會(huì)出現(xiàn)兩個(gè)圖標(biāo)。
首先,在Scene?dock 中,發(fā)射圖標(biāo)位于發(fā)射節(jié)點(diǎn)旁邊。

單擊它會(huì)重新打開(kāi)Node?dock,其中會(huì)顯示已連接的信號(hào)。

然后,在腳本編輯器中,回調(diào)函數(shù)左側(cè)的空白處會(huì)出現(xiàn)一個(gè)圖標(biāo)。

單擊它可顯示有關(guān)哪個(gè)節(jié)點(diǎn)將哪個(gè)信號(hào)連接到此功能的信息。

當(dāng)您開(kāi)始將多個(gè)信號(hào)連接到同一個(gè)回調(diào)函數(shù)時(shí),它特別有用,因?yàn)樗鼈兌剂性谶@個(gè)彈出窗口中。
如何通過(guò)代碼連接
要通過(guò)代碼連接到信號(hào),請(qǐng)connect()
?在具有信號(hào)的節(jié)點(diǎn)上調(diào)用函數(shù)。
該connect()
函數(shù)具有三個(gè)必需的參數(shù):
信號(hào)的名稱作為
.對(duì)持有回調(diào)函數(shù)的節(jié)點(diǎn)的引用。用于?
self
連接到您附加腳本的節(jié)點(diǎn)。回調(diào)函數(shù)的名稱作為
.
該函數(shù)有更多可選參數(shù),我們將在本課程的后面探討。
要將按鈕的信號(hào)與代碼連接起來(lái),我們首先需要獲取按鈕節(jié)點(diǎn)。我們用一個(gè)onready
變量來(lái)做到這一點(diǎn),并在函數(shù)中連接信號(hào)_ready()
。
# We get a reference to the HideButton node.
對(duì)該connect()
函數(shù)的調(diào)用讀作“將?HideButton的pressed
信號(hào)連接到該節(jié)點(diǎn)的?_on_HideButton_pressed()
函數(shù)”。
剩下的就是編寫(xiě)_on_HideButton_pressed()
?函數(shù)并向其提供您在按下按鈕時(shí)需要運(yùn)行的指令。
回調(diào)函數(shù)
Godot 用戶遵循命名信號(hào)回調(diào)函數(shù)的約定:_on_NodeName_signal_name()
.
例如,如果您連接名為HideButtonpressed
的節(jié)點(diǎn)的信號(hào),您將調(diào)用函數(shù)?。_on_HideButton_pressed()
這只是一個(gè)指南。稍后,您會(huì)看到我們通常更喜歡將信號(hào)直接連接到現(xiàn)有函數(shù),而不是創(chuàng)建新的回調(diào)函數(shù)。
如果您使用編輯器連接節(jié)點(diǎn),Godot 將負(fù)責(zé)根據(jù)此約定命名節(jié)點(diǎn)。
這就是第一個(gè)信號(hào)回顧指南。展望未來(lái),您將學(xué)習(xí)如何創(chuàng)建新信號(hào)、從代碼中發(fā)出它們,以及管理多個(gè)信號(hào)連接的新技術(shù)。
備忘單:最有用的 UI 節(jié)點(diǎn)入門(mén)
Godot 有許多 UI 節(jié)點(diǎn),適用于任何用戶界面,從簡(jiǎn)單到復(fù)雜。
龐大的功能集一開(kāi)始很容易讓您不知所措。
這個(gè)簡(jiǎn)短的備忘單列出了開(kāi)始在 Godot 中創(chuàng)建用戶界面的最有用的節(jié)點(diǎn)。
您將使用最多的節(jié)點(diǎn)
我們建議您從六個(gè)非常有用的 UI 節(jié)點(diǎn)開(kāi)始。
, 顯示文本。

,玩家可以點(diǎn)擊它與用戶界面進(jìn)行交互。

,其中顯示了一張圖片。

,它為玩家提供了一個(gè)可編輯的文本字段。您可以將其用于登錄表單或供玩家在多人游戲中輸入昵稱。

,顯示帶有可選滾動(dòng)條的大文本框并支持文本格式(斜體、粗體等)。

, 繪制水平或垂直條。您可以將其用于健康欄或加載進(jìn)度顯示。

我們使用了記分板系列中的前三個(gè)節(jié)點(diǎn),我們將在接下來(lái)的兩個(gè)系列中使用
和。最有用的容器
還有一些
您會(huì)經(jīng)常使用的節(jié)點(diǎn):正如我們已經(jīng)看到的那樣,它在一列中對(duì)齊它的子項(xiàng)。

將
其子項(xiàng)排成一行。下面,您可以看到 一個(gè) .
對(duì)其子項(xiàng)應(yīng)用固定邊距。下面,邊距容器在面板邊緣和按鈕之間創(chuàng)建空間。

可以
在孩子身后畫(huà)一個(gè)面板,讓他們伸展以填充面板。我們經(jīng)常將它與 結(jié)合起來(lái),例如,圍繞人物肖像創(chuàng)建一個(gè)框架。
節(jié)點(diǎn)
會(huì)自動(dòng)放置和調(diào)整其子 節(jié)點(diǎn)(其他容器、按鈕、標(biāo)簽等)的大小。當(dāng) UI 節(jié)點(diǎn)是容器的直接子節(jié)點(diǎn)時(shí),您不能再手動(dòng)移動(dòng)子節(jié)點(diǎn)。有時(shí)您會(huì)需要其他節(jié)點(diǎn),但以上十個(gè)節(jié)點(diǎn)應(yīng)該可以滿足您的大部分需求。