關于無需程式設計即可建立視訊遊戲的那些工具的談論有很多。不用學習程式設計知識對很多獨立開發者來說就是一個夢想。這種需求 - 遊戲開發者、甚至在很多公司内部,希望對遊戲流程擁有更多控制權,已經有很長一段時間了。
很多引擎産品号稱是無需程式設計的環境,但相對于傳統的編碼開發流程,這些産品的最終使用結果,經常是做不出完整的作品、或者是能做出也太複雜或太低效。整個過程在這種環節反而耗費太多時間。實際上,遊戲引擎的通常趨勢是:在這種為了實作特定任務而必須要編碼的地方,添加一些工具來盡量減少編碼量、提升開發速度。
基于這種了解,Godot針對這個目标采用了一些有效的設計決策。第一點也是最重要的一點就是場景體系。起初它的目标并不明顯,但之後很好的發揮了作用:減輕了程式員為實作架構而需要額外編碼的工作。
在使用場景體系設計遊戲時,整個項目被劃分成互補的場景 - 不是獨立的。場景之間互補,而不是互相獨立。後續會有大量示例,但請先記住這點。
對于已有了專業程式設計知識的人來說,這是一種與MVC不同的設計模式。Godot承諾:你丢棄MVC程式設計習慣并換用"場景即complement"模式後,還能擁有高效。
Godot也使用 <code>繼承 <http://c2.com/cgi/wiki?EmbedVsExtend></code>__ 模式進行腳本程式設計,意味着腳本可以繼承所有可用的引擎類。
:ref:<code>doc_gdscript</code> 是Godot環境内運作的一種動态類型腳本語言。它的設計目标為:
簡單、熟悉、盡可能易于學習
代碼可讀性高、錯誤安全處理;語言多數借鑒自Python
開發者通常隻需花幾天學習它,兩周内就能完全适應。
和大多數動态類型語言一樣,更高的生産效率 - 易于學習、編碼很快、無需編譯等,意味着對應的是性能的降低,但引擎的大多數關鍵代碼是由C++編寫(矢量運算、實體學、數學、索引等),這使得遊戲最後的性能比多數類型的遊戲要好。
而且如果真有更高的性能要求,關鍵部分的代碼可以用C++重寫并暴露給腳本調用。這時,你隻需要将GDScript類替換成C++類即可,不需要修改遊戲其它地方。
在此之前,請確定你已經讀過 :ref:<code>doc_gdscript</code> 參考文檔了。它是一種簡單的語言,并且參考文檔也很短,大緻過一遍應該花不了幾分鐘。
本文将開始編寫一個簡單的GUI場景。用“addnode”對話框建立下述的節點和層級:
Panel
Label
Button
在場景樹面闆,看起來效果是這樣:
在2D編輯器面闆中要像這樣:
最後儲存場景,取名"sayhello.scn"
.. _doc_scripting-adding_a_script:
右鍵點選Panel節點,然後在右鍵菜單中選擇"Add Script":
彈出“script creation”對話框。對話框中可以選擇語言、類名等。腳本檔案中,GDScript是不用類名的,是以這個字段是不可編輯的。這個腳本相應的繼承自“Panel”,即繼承該Panel類型的節點(代碼其實會自動填充的)。
填寫腳本的路徑名然後選擇“Create”:
完成操作後,腳本被建立并添加到該節點下。在該節點下可以看到一個額外的圖示及“script”屬性:
打開腳本編輯器後,你就會發現已經自動填充了一段前面所述的模闆代碼:
當該節點(包括它所有的子節點)進入目前活躍狀态的場景時,"_ready()"函數會被執行。記住哦:這個不是構造函數,構造函數是“_init()”。
腳本給節點添加了行為,它用于控制該節點以及其它節點(子節點、父節點、同一級的兄弟節點等)的功能。腳本的局部作用域僅是該節點;該節點的那些虛拟函數被該腳本捕捉。
在大多數GUI節點中都用到了信号(Signal),其實其它節點也有。當一些特定類型的動作發生時,信号就會被“發射”出來,可以連接配接到任意腳本執行個體的任意函數。這一步中,按鈕的"pressed"信号會被連接配接到一個自定義函數。
編輯器中有連接配接信号到腳本的界面:選中場景樹中的節點,然後選擇“節點”頁籤,再選中其中的"Signals"頁籤。
此時我們主要對"pressed"信号感興趣。除了可用可視化界面來完成信号連接配接操作,也可以通過腳本代碼來進行。
針對這種情況,Godot的程式員可能用得最多的一個函數:
:ref:<code>Node.get_node() <class_Node_get_node></code>.
該函數使用路徑來擷取該場景中目前樹狀結構或任意地方的節點。
要擷取到該按鈕,需要用下述寫法:
下一步,當按鈕被按下時,會添加一個回調 - 改變标簽的文本内容:
最後,該按鈕的"pressed"信号需要在_ready()函數中進行連接配接, :ref:<code>Object.connect() <class_Object_connect></code>.
腳本的最終内容大緻如下:
運作場景,按下按鈕後應該就能得到預期的結果:
注意: get_node(path)僅會在節點的最直接的下一節範圍内查找,即Button必須是Panel子一級節點,否則是通路不到的。假如Button是Label的子一級節點,代碼就需要修改了:
而且要記住,這裡引用的是節點的名稱而不是節點的類型名。