在我們詳細介紹Ren’Py的程式語言之前,我們必須首先介紹一下Ren’Py腳本的結構。這包括:腳本文件如何分割為語句塊(block),而語句塊(block)是由多行腳本構成;各行腳本如何分割為基本元素(element),並構成語句(statement)。
Ren’Py遊戲腳本由game目錄下眾多副檔名為 .rpy 的文件組成。Ren’Py會依次檢查每一個文件(按照拉丁字母順序),並把文件內容用作腳本。
總之,把一份腳本打散成多個文件,與一份腳本保存在一個大文件中,兩種方法是等效的。主控流程可以在文件之間透過調用腳本標籤(label)跳轉。把一份腳本切分為多個文件跟創作者個人風格有關——有些遊戲製作者喜歡使用小文件(像一個事件一個文件,或者每一天一個文件),而其他製作者傾向於使用一個完整的大腳本文件。
為了提高載入速度,Ren’Py啟動時會把 .rpy 文件編譯為 .rpyc 文件。當一個 .rpy 文件發生變更時, .rpyc 只有重啟Ren’Py進程才會更新。另外,如果一個 .rpyc 文件並沒有對應的 .rpy 源文件,這個 .rpyc 文件依然會被使用。當 .rpy 文件已經刪除而 .rpyc 文件沒有刪除的情況下,可能會導致運行時出現問題。
檔案名必須以字母或者數字開頭,並且開頭不能用“00”,因為“00”開頭的文件是Ren’Py內部使用的。
基礎目錄是包含構建該遊戲所有文件的目錄。(這可能也包含一些跟遊戲無關的文件。)像README(須知)類文件應該放在基礎目錄中。
基礎目錄會被創建在Ren’Py目錄下,以創作者遊戲的名稱命名。例如,如果創作者的Ren’Py目錄名為renpy-6.11.2,遊戲名為“HelloWorld”,創作者的基礎目錄就是renpy-6.11.2/HelloWorld。
遊戲目錄很可能是在基礎目錄下一個名為“game”的目錄。例如,如果創作者的基礎目錄是renpy-6.11.2/HelloWorld,創作者的遊戲目錄就會是renpy-6.11.2/HelloWorld/game。
Ren’Py會按以下順序依次搜索所有目錄:
啟動器(launcher)只會識別“game”和“data”目錄。
遊戲目錄包含了遊戲內使用的所有文件。其自身及其所有子目錄下,會被掃描出所有 .rpy 和 .rpyc 文件,並拼裝組合成整個遊戲的腳本。 .rpa 文件也會被掃描到,這些文件會被遊戲自動使用。當遊戲指定某個需要載入的文件路徑時,文件路徑會與遊戲目錄關聯。(注意config.searchpath可以控制並修改這一點。)
Ren’Py腳本文件可能會包含一些注釋(comment)。每條注釋都以記號(‘#’)開頭,直到該行文本結束。不過有一種情況例外,注釋(comment)不能用在某個字串的一部分。
# 這是一條注釋。
show black # 這也是一條注釋。
"# 這不是一條注釋因為它是一個字串的一部分。"
Ren’Py忽略注釋, 所以腳本處理過程中那段注釋如同不存在。
一個腳本文件可以被切割為一些邏輯行(logical line)。一條logical line(邏輯行)往往在文件中頂格起始,換行結束,有一些例外:
一個邏輯行結束後,下一行就是另一個邏輯行的開始。
Ren’Py程式語言中大多數語句都只由一個邏輯行,有一些語句則包含多行。
"這是一條邏輯行"
"因為這條邏輯行包含一個字串,
所以換行也依然是同一條邏輯行。"
$ a = [ "由於括號的存在,這也是一條",
"可以突破換行的邏輯行。" ]
空的邏輯行會被忽略。
縮進 是我們指代Ren’Py語句每個邏輯行開頭的空間。在Ren’Py中,縮進必須使用空格。
縮進被用來將一些語句分組形成語句塊(block)。一個語句塊是一組邏輯行,通常也是一組語句。將一個文件分割為語句塊的原則是:
對Ren’Py來說,縮進非常重要,甚至縮進量能引起語法或者邏輯錯誤。同時,縮進的使用表明了塊結構,使我們不需要瀏覽整個腳本文件就能識別出塊結構。
"這是一個語句,後面跟著的是if語句,那是一個語句塊的一部分。"
if True:
"這個語句是新語句塊的一部分。"
"這個語句也是新語句塊的一部分。"
"這個語句又是第一個語句塊的一部分了。"
Ren’Py語句由一些基本部分組成。
關鍵字是一個英文單詞,必須在遊戲腳本中合法出現。關鍵字通常用於出現在語句和屬性中。
名字以一個下劃線(_)開頭的關鍵字僅限Ren’Py內部使用,除非文件另有說明。當一個關鍵字名字開頭是兩條下劃線__但結尾沒有兩條下劃線__,在使用時它會改變為特定文件版本號。
圖像名(image name) 由一個或多個部分構成,以空格分隔。 圖像名的第一部分稱作 圖像標籤(image tag) 。圖像名後面的部分都是 圖像屬性(image attributes) 。圖像的各部分都是由字元、數字和下劃線組成的字串。
例如,一個圖像名為 mary beach night happy 。圖像標籤(tag)就是 mary ,而圖像屬性(attribute)就是 beach 、 night 和 happy 。
字串以一個引用字元(“、’或者`)開頭,包含幾串文字,並以同樣的引用字元結尾。
反斜槓(\)用於字元轉義,一些特殊字元,比如%(需要寫作\%)、[(需要寫作\[)、{(需要寫作\{)。它還用於包含下一行,此時使用\n串。
在Ren’Py字串中,連續多個空格會被壓縮為一個空格字元,除非某個空格前面有一個反斜行。
'Strings can\'t contain their delimiter, unless you escape it.'
簡單表達式就是一個Python表達式,用於在Ren’Py腳本中運行Python。一個簡單表達式使用以下類型作開頭:
其後可以接續任意數量的:
舉例,3 、(3 + 4) 、 foo.bar 和 foo(42) 都是簡單表達式。但 3 + 4 則不是“簡單”表達式,因為該表達式是一個算式字串且沒有使用圓括號。
大多數Ren’Py語句使用通用的語法。而say語句是個例外,其使用開頭的某個關鍵字標識say語句。如果語句中包含變數的話,會跟在該關鍵字後面。
變數後面會跟著一個或多個特性(property)。特性(property)可以使用任意順序排列,每個屬性均只會出現一次。一項特性(property)以一個關鍵字開頭。對大多數的特性(property)來說,屬性名字會跟之前出現的語法元素(element)之一保持一致。
若該語句包含一個語句塊(block),那行語句會以冒號(:)結尾。否則的話,以換行結尾。
Note
本段內容現在可以先跳過不看。當你覺得無法理解某個樣例,或者你覺得需要理解更深層次的運行機制時,可以再返回來看本段內容。
Ren’Py的很多地方都會用到python表達式。例如,定義一個新角色就意味著調用charactre(角色)的函數。由於python表達式功能十分強大,只是用其很小部分就足以實現一個基本的Ren’Py遊戲。
這是一個python表達式的概要。
3 和 42 就都是整數。.5 、 7. 和 9.0 就都是浮點數。True 表示真值, False 表示假值。 None 表示空值。元組(tuple)是一種容器,其元素(item)數量非常重要。例如,我們可以使用一個2維元組(也被稱作pair)來裝寬度和高度數據,或者使用一個4維元組(包含x、y、寬度和高度)來裝一個三角形的數據。
元組(tuple)開頭有一個左括號 ( ,可以由0個或若干個逗號分隔的python表達式,並以一個右括號 ) 結束。比較特殊的是,只有一個元素(item)的元組中,元素後面必須帶一個逗號。各種例子如下:
()
(1,)
(1, "#555")
(32, 24, 200, 100)
列表(list)是一種容器,用來裝各種類型的數據。列表以 [ 開頭,包含一系列逗號分隔的表達式,並以 ] 結束。舉例如下:
[ ]
[ 1 ]
[ 1, 2 ]
[ 1, 2, 3 ]
python表達式中允許使用變數。透過定義語句或者python語句產生的數值可以存放在變數中。變數以字母或者下劃線開頭,後接0個或若干個字母、數據或下劃線。舉例如下:
name
love_love_points
trebuchet2_range
以下劃線“_”開頭的變數是預留給Ren’Py專用,創作者不應使用。
python模組(module)和對象(object)都有欄位(field)的概念,可以在欄位(field)後接一個英文句號“.”和一個表達式(通常是一個變數),實現對欄位的訪問。例如:
config.screen_width
實現了對config中screen_width欄位的訪問。
python表達式可以調用一個函數並獲得一個返回值。函數調用以一個表達式開頭(通常是函數名),後面跟著一對圓括號,括號內有一系列參數。參數列表開頭是個python表達式,也是固定位置參數。後面則是關鍵字參數,由參數名、等號和表達式組成。下面是一個例子:
Character("Eileen", type=adv, color="#0f0")
我們調用了Charactre函數。其給定了一個固定位置參數,也就是字串“Eileen”。其給定了兩個關鍵字參數: type 被賦值為 adv ,而 color 被複製為字串“#0f0”。
構造器是一類專門用於返回一個新對象的函數,且會被使用相同的方式調用。
閱讀此份文件時,你可能會看到這樣的函數聲明:
Sample(name, delay, position=(0, 0), **properties) link這個樣例函數並不真正在Ren’Py中使用,而只存在這份文件中。
這個函數:
由於函數結尾是 **properties, 這意味著其可以使用 樣式特性 作為額外的關鍵字參數。 其他的特殊形式結尾還有*args,表示其可以使用任意數量的固定位置參數,而**kwargs表示在文件中已詳細描述過的固定位置參數。
Python的強大,遠非我們這份文件所能完全展現。若希望學習python的更多細節,我們推薦Python入門教學, python.org 。由於我們認為對於Ren’Py來說,更深一層的python知識不是必要的,了解python語句和表達式通常就足夠了。