在 Divooka 中使用 Novella
Divooka.Novella 包將 Novella 的每個概念都做成了節點,這些節點可以在全部四種圖中組合使用(見圖上下文):
| 圖 | 它如何使用 Novella |
|---|---|
| Routine | 一個過程:建立遊戲、配置遊戲、載入其內容並執行它。 |
| Events | 以類形式編寫的遊戲:圖的基型別為 Novella Application,圖實現遊戲的回撥。 |
| Function | 以資料形式描述遊戲:序列、條件、效果、標籤、場景、動畫、介面、樣式、故事、Game Definition。 |
| Flows | 呼叫這樣的函式並預覽其返回值。 |
過程式圖是基礎:遊戲之所以能執行,是因為有一個圖建立並啟動了它。函式式圖是編寫和預覽故事的便捷方式,其結果交給過程式圖來真正執行。哪些發行版包含此包,見安裝。
Novella 工具箱
所有節點都在一個名為 Novella 的工具箱中,每種型別一個類別。下文中的節點名稱就是節點面板中顯示的名稱。
Novella Game
遊戲本身,用於過程式圖。除兩個構造節點外,每個節點都以遊戲作為接收者(在 Routine 圖中通過連線傳入,在 Events 圖中則是隱式的)。
| 節點 | 作用 |
|---|---|
| Make Novella Game | 一個具有標題、寬度和高度的遊戲。 |
| Make Novella Game From Definition | 由函式式圖構建的 Game Definition 建立的遊戲。 |
| Set Resolution、Set Title | 所有內容據以佈局的解析度,以及標題。 |
| Set Config、Set Theme | 一項配置或主題設定,寫法與指令碼中相同;它優先於指令碼自身對同一鍵的 define。 |
| Add Library Assets | 嵌入在本文件庫中的檔案。庫輸入由文件提供,無需連線。 |
| Add Asset Folder、Add Asset | 磁碟上的一個資料夾,或來自位元組資料的單個檔案。 |
| Load Script、Load Script File、Load Scripts From Assets | 指令碼文字、一個指令碼檔案,或資源中的每個 .novella 檔案(可選限定在某個資料夾下)。 |
| Add Story | 由函式式節點構建的故事。 |
| Add Scene | 來自 Scenes 節點的一個 Scene,以其名稱作為標籤新增。 |
| Define Character、Define Image、Set Default | 無需指令碼的定義。 |
| Register Command | 將一個 run 命令名稱繫結到一個沒有輸入也沒有輸出的函式(見函式引用)。 |
| Register Command Function | 將一個 run 命令名稱繫結到一個函式,該函式以文字形式接受命令的實參並以文字應答,故事將應答讀作 _return:數字、true 或 false,否則為文字。 |
| Register Expression Function | 將一個可由條件、$ 行和 [interpolation] 呼叫的名稱(例如 [title_for(trust)])繫結到一個函式,該函式以文字形式接受實參並以文字應答,應答的解讀方式相同。 |
| Validate | 靜態檢查(lint):每個問題一行。 |
| Run | 在視窗中開啟遊戲,並在玩家退出時返回。 |
同一類別中還有即時指令碼節點,它們在即時指令碼執行時會立即播放(見 Events 圖):Say、Narrate、Show、Scene、Hide、With、Pause、Play、Stop、Menu(返回所選項的索引)、Input(返回輸入的文字)、Call Label、Notify、Achieve、Set Variable、Get Variable、Get Number 和 Random Integer。Random Integer 從故事自身的生成器中抽取,因此回滾後再次選擇會抽到相同的數。另有兩個節點服務於 Command 事件:Set Result 應答正在處理的命令,Translate Text 讓文字經過故事的字串翻譯。
Story Writing
構建 Sequence 的純節點:每個節點接受一個序列,並返回一個多了一條語句的新序列,因此一條鏈從上到下讀起來就像指令碼。
| 節點 | 語句 |
|---|---|
| Start Sequence | 一個可在其上構建的空序列。 |
| Say、Narrate | 一句對話(角色 id、文字、可選的影像屬性),或旁白。 |
| Show、Scene、Hide、With | 舞臺變化,帶有位置(left、right、已定義的變換)和轉場(dissolve、fade(1.0))。 |
| Pause | 等待一次點選,或若干秒。 |
| Play Music、Play Sound、Play、Stop | 在音樂通道、音效通道或任意通道上的音訊。 |
| Menu | 一句提示文字和兩到四個 Choice 值,每個值都攜帶其後續的序列。 |
| If | 一個來自 Conditions 節點的 Condition、條件成立時的序列,以及可選的條件不成立時的序列。 |
| Apply Effect | 一個來自 Effects 節點的 Effect,例如 Add To Variable:故事的變數在此處發生變化。 |
| Jump、Call、Return | 標籤之間的流程。 |
| Input、Notify、Achieve、Movie、Voice、Window | 對應的語句。 |
| Run Command | 一個 run 命令,帶有以逗號分隔的實參表示式。 |
| Script | 以指令碼形式編寫的任意語句,用於其他節點未涵蓋的內容。 |
| Concatenate | 一個序列後接另一個序列。 |
| Sequence To Script | 將序列轉為指令碼文字,用於檢視一條鏈寫出了什麼。 |
上面的節點涵蓋了大多數故事所需的內容。下面這些節點則逐個選項地表達指令碼能表達的其餘內容:
| 節點 | 語句 |
|---|---|
| Say Line | 一句臺詞,帶有持續的屬性、僅對本句有效的屬性、臺詞出現時播放的轉場,以及用於翻譯的 id。 |
| Say Briefly、Say As、Extend、Centered、NVL Clear | 一句屬性僅在其顯示期間有效的臺詞;一句來自一次性說話者的臺詞;接續上一句臺詞;螢幕正中的文字;一個新的 NVL 頁面。 |
| Show With Options | 指令碼 show 的每個子句:at、with、behind、zorder、as 和 layer,以及一個來自 Animation 節點、作為其自身時間線的 Animation。 |
| Scene With Options、Hide With Options | 在某個圖層上、經過定位或帶動畫的 scene;在某個圖層上的 hide。 |
| Hard Pause、Window With Transition | 無法通過點選跳過的暫停;帶轉場地顯示、隱藏對話視窗或將其設為自動。 |
| Show Screen、Hide Screen、Call Screen | 一個介面:在故事繼續的同時覆蓋在遊戲上方、將其移除,或者顯示並等待其應答,應答隨後位於 _return 中。每個節點接受一個實參,型別為數字、true、false 或文字。 |
| Play With Options、Queue | 帶有指令碼 play 所有選項(淡入、淡出、迴圈、音量、if_changed)的音訊;排隊在目前播放內容之後播放的檔案。 |
| Voice Sustain、Movie With Options | 讓語音在下一句臺詞期間繼續播放;一部可以讓音樂保持播放的影片。 |
| Input With Options | 帶有預設值、長度限制和允許字元的輸入。 |
| Menu From Choices | 一個具有任意數量選項的選單,選項用 Start Choices 和 Add Choice 收集,可選命名(以便跳轉可以回到它),並可指定一個列表變數來隱藏已選過的選項,與 menu set 的做法相同。 |
| While | 在 Condition 成立時重複一個序列。 |
| Call With Arguments | 呼叫一個標籤,為其參數傳入最多三個實參,每個都指定型別。 |
| Jump To Variable、Call Variable | 跳轉到或呼叫某個變數所指明的標籤。 |
| Jump From Function | 跳轉到某個 Function 圖所給出名稱的標籤(見在 Function 圖中實現邏輯)。 |
| Return Value、Return Variable | 以一個指定型別的值或某個變數的值從呼叫中返回,呼叫方將其讀作 _return。 |
| Run Command With Values | 一個 run 命令,帶有最多三個實參,每個都指定型別。 |
| Python Block | 一個 Python 塊,行數不限,在序列執行到此處時針對故事的變數執行;它所設定的、故事能夠儲存的內容會寫回故事。此包自帶 Python,因此文件無需為此做任何額外準備。 |
Choice
Make Choice 由文字、其後續的 Sequence 以及一個可選的 Condition(例如 Variable At Least(affection、3))構建一個選單選項;沒有條件時,該選項總會顯示。選項輸入到 Menu 節點,或輸入到用於 Menu From Choices 的 Add Choice。Choice With Id 為選項指定一個作者自選的 id,這樣即使選項文字改寫了,它仍會被記為已選。
Conditions
Condition 是故事所做的一次判斷,由各個部分構建而成,而不是寫成文字。它可以輸入到 If、While、Make Choice、Scene Choice、Branch To Scene、Set To Condition,以及影像、圖層、音樂曲目、畫廊條目和介面元素的條件中。它會變成與指令碼 if 中相同的表示式,因此可以存檔、回滾、接受靜態檢查,並能讀回為指令碼;唯一的例外是 Condition From Function,它沒有指令碼形式。
| 節點 | 何時成立 |
|---|---|
| Always | 始終成立。 |
| Compare Variable | 變數與某個值的比較結果成立:==、!=、<、<=、> 或 >=。該值的型別為數字、true、false、none 或文字。 |
| Variable At Least | 一個數字變數至少為某個值。 |
| Variable Is Set | 變數有值:為真、非零、非空。 |
| Has Visited | 在本週目中已到達過某個標籤或場景。 |
| List Contains | 一個列表變數包含某個值,例如某件禮物在已送出的禮物之中。 |
| All Of、Any Of | 兩到四個條件全部成立,或至少一個成立。 |
| Not | 某個條件不成立。 |
| Compare Variables | 兩個變數的比較結果成立:trust > doubt。 |
| Visited At Least | 在本週目中到達某個標籤至少達到指定次數:例如第三次去集市。 |
| Ever Reached | 在任意周目中曾到達過某個標籤,例如一個曾經見過的結局。 |
| Has Seen Image、Has Heard | 在任意周目中曾看到過某個影像,或聽到過某段音訊。 |
| Has Achievement | 已獲得某項成就。 |
| Is Showing | 帶有某個標記的影像此刻在舞臺上。 |
| In Language | 玩家以某種語言閱讀遊戲,例如 zh-Hans。 |
| By Chance | 以 0 到 1 的概率隨機成立,抽取方式保證回滾後結果相同。 |
| Condition From Function | 一個接收故事變數的成員 Function 圖給出 true 或 false;見在 Function 圖中實現邏輯。 |
| Condition From Script | 以指令碼形式編寫的條件,例如 affection >= 3 and gift == "fan",用於其他節點無法表達的情況。 |
Effects
Effect 是對故事變數的一次更改。Apply Effect 在序列中的某一點進行更改,Scene Choice 則在選項被選中時進行更改。效果會變成與指令碼 $ 行相同的賦值,因此會隨故事一起回滾和存檔。
| 節點 | 更改的內容 |
|---|---|
| Set Variable | 將變數設為一個指定型別的值。 |
| Add To Variable | 對數字變數做加法(除非另行指定,否則加 1)。 |
| Add To List | 向列表變數新增一個值。 |
| Subtract From Variable | 對數字變數做減法(除非另行指定,否則減 1)。 |
| Remove From List | 從列表變數中移除一個值。 |
| Change Variable | 用運算子更改變數:=、+=、-=、*=、/=、//= 或 %=。 |
| Change Variable By Variable | 用另一個變數的值、以相同的運算子更改變數:bag -= chosen 從包中取出所選的禮物,coins += reward 加上一份獎勵。 |
| Copy Variable | 將變數設為另一個變數的值。 |
| Toggle Variable | 將為真的變數變為假,為假的變為真。 |
| Random Number | 將變數設為介於最小值和最大值之間(包含兩端)的整數,抽取方式保證回滾後結果相同。 |
| Set To Condition | 將變數設為某個 Condition 此刻是否成立。 |
| Number From Function、Text From Function | 將變數設為某個成員 Function 圖根據故事變數給出的數字或文字。 |
| Effect From Function | 按某個過程式圖(例如 Routine)的指示,用 Set Number、Set Text、Set Flag 和 Add 更改故事的變數。 |
| Combine Effects | 兩到四個效果,按順序執行。 |
| Effect From Script | 以指令碼形式編寫的更改,相當於 $ 之後的部分:affection += 1。 |
Story Variables
交給 From Function 節點的圖所接收到的東西:故事的變數,作為一個 Story Variables 值。
| 節點 | 作用 |
|---|---|
| Number、Integer、Text、Flag、List | 將變數讀取為數字(未設定時讀作 0)、整數、文字(未設定時讀作空)、是否有值(為真、非零、非空),或列表的各項。 |
| List Contains | 列表變數是否包含某個值,按文字比較。 |
| Visited | 在本週目中是否進入過某個標籤。 |
| Set Number、Set Text、Set Flag、Add | 將變數設為數字、文字或布林值,或對數字做加法。 |
它們是 Story Variables 的成員,Divooka 根據成員的行為決定在哪些圖中提供它。Function 圖是資料流:它可能在任何需要其結果的時候被求值,並且結果會被快取,因此它只接受不改變任何東西的成員。讀取類成員標記為 const,這告訴 Divooka 它們不改變任何東西,因此它們既出現在 Function 圖中,也出現在過程式圖中。寫入類成員會改變故事,因此只在過程式圖中提供,例如交給 Effect From Function 的 Routine 圖。任何 C# 成員以節點形式出現在何處,都由同一條規則決定;見 C# 技巧。(過去代替讀取類成員的 Read Number、Read Text、Read Flag、Read List Contains 和 Read Visited 節點已被移除;請使用這些成員。)見在 Function 圖中實現邏輯。
Scenes
Scene 是編寫遊戲的配置式方法,也就是 Novella One 構建遊戲的方式:每個場景指明一個背景、音樂、其臺詞以及故事接下來的去向,不需要手動連線標籤、跳轉或選單。場景會變成一個以其名稱命名的普通標籤,因此可以存檔、回滾並與標籤和指令碼混用,名為 start 的場景開始遊戲。見概念。(Story Writing 節點 Scene 是另一回事:它是一條清空舞臺並顯示背景的語句。)
| 節點 | 作用 |
|---|---|
| Make Scene | 一個場景:其名稱、作為 Sequence 的臺詞(Say、Show 和其他 Story Writing 節點)、一個結尾、一個背景(例如 bg plum_garden;為空時保留目前舞臺)、背景的轉場(預設為 fade)以及音樂(為空時保留正在播放的音樂)。沒有結尾時,遊戲在該場景之後結束。 |
| Go To Scene | 一種結尾:故事前往另一個場景。 |
| Choose Scene | 一種結尾:一句提示文字(可以為空)和兩到四個 Scene Choice 值;由玩家選擇下一個場景。 |
| Scene Choice | 選項的文字、它通向的場景、一個決定何時提供該選項的可選 Condition,以及一個在選中時執行的可選 Effect。 |
| Branch To Scene | 一種結尾:一個 Condition 和兩個場景,條件成立時前往第一個,不成立時前往第二個。 |
| End Game | 一種結尾:遊戲結束。 |
| Add Scene | 新增了一個場景的故事。 |
Animation
Animation 是一條 Ren'Py ATL 風格的時間線,一步一步地構建,就像在指令碼中編寫變換那樣。它可以輸入到 Show With Options 或 Scene With Options 中作為影像自己的動畫,也可以輸入到 Define Transform 中命名,供任何 at 使用。
| 節點 | 作用 |
|---|---|
| Start Animation | 一條可在其上構建的空時間線。 |
| Set Property | 立即設定一個屬性:將 xalign 設為 0.5。 |
| Animate Property | 在若干秒內將一個屬性以動畫方式變化到某個值,由緩動函式(linear、ease、easein、ease_bounce 等)控制緩動。 |
| Also Change | 在前一步中同時更改另一個屬性,使兩者一起變化:例如同時移動和淡出。 |
| Wait | 在下一步之前等待。 |
| Repeat | 重新開始時間線或其所在的塊:重複指定次數,為 0 時無限重複。 |
| Animation Block | 巢狀在本時間線中的一條時間線,使其中的重複只迴圈這一部分。 |
| In Parallel | 同時執行的兩條或三條時間線,每條為自己的屬性製作動畫。 |
| Include Transform | 就地執行另一個變換,例如 left 或故事定義的某個變換,並可帶實參。 |
| Show Picture | 從此處起影像顯示這張圖片,如果給出了轉場,則在轉場時長內交叉淡化:用於眨眼、燭火、飄揚旗幟的各幀。 |
| Choose Between | 兩條或三條時間線之一,每次動畫執行到此處時按權重隨機選取;同一個已顯示影像在同一時刻總是選取相同的一條。 |
| At Time | 後續內容在動畫開始後的這麼多秒開始,並截斷正在執行的內容。 |
| On Event | 影像被顯示、替換或隱藏時的時間線(show、replace、hide,或以逗號分隔的多個)。如果影像的動畫處理了 hide,它會留在舞臺上直到該時間線結束,因此可以淡出或滑出。 |
| Contains Picture | 繪製在此圖片內部的另一張圖片,可帶有自己的時間線:例如燈籠上的閃光。 |
| Call Transform Function | 將影像交給遊戲為動畫註冊的一個 C# 函式處理,持續時間與該函式相同。 |
| Define Transform | 新增了一個具名變換的故事,該變換可以接受參數,例如 height=20。 |
| Add Animated Image | 新增了一個動畫影像的故事:由 Show Picture 步驟和等待組成,無論顯示在哪裡都會播放動畫,與指令碼的 image name: 塊相同。 |
| Animation From Script、Animation To Script | 以指令碼行編寫的時間線,以及以指令碼形式顯示的時間線。 |
值的寫法與指令碼相同:0.5 是舞臺尺寸的比例,100 是像素,(-height) 讀取變換的一個參數。
Images
供 Add Image From Source 使用的影像源,以及供 Add Layered Image 使用的分層影像:
| 節點 | 建立的內容 |
|---|---|
| Image File | 遊戲檔案中的一個影像檔案。 |
| Color Image | 一種純色,除非給出尺寸,否則填滿整個螢幕。 |
| Movie Image | 作為影像播放的影片,除非另行指定,否則循環播放。 |
| Filtered Image | 應用了濾鏡的影像:縮放、翻轉、著色、去飽和、亮度、模糊和不透明度。 |
| Composite Image | 在一塊指定尺寸的畫布上,按偏移量繪製一個底圖和最多兩個其他影像。 |
| Switch Image | 在某個 Condition 成立時顯示一個影像,否則顯示另一個,在繪製時決定:例如白天和夜晚的房間。 |
| Start Layered Image、Add Always Layer、Add Layer Attribute | 一個分層影像:一個標記、始終繪製的圖層,以及分組的屬性,每個屬性帶有一個檔案、是否為該組的預設值、該組是否允許同時選中多個,以及一個可選的 Condition。 |
Transitions
每個節點都生成任何節點的 with 所接受的轉場文字,並填好其時間參數:Dissolve(秒數)、Fade(淡出、保持、淡入時間和顏色)、Flash、Image Dissolve(灰度遮罩、秒數、漸層範圍和方向)、Move(秒數和緩動函式)以及 Timed Transition(任何內建或已定義的轉場,使用自己的時長,例如兩秒的 slideleft)。
Screens
Screen Layout 是以資料形式表示的自訂介面,是指令碼 screen 定義的節點形式:放置在舞臺上或在容器、分支和迴圈中佈局的元素,每一幀都根據故事的變數重新計算。Add Screen 將它放入故事,Show Screen、Hide Screen 和 Call Screen 按名稱使用它。
| 節點 | 作用 |
|---|---|
| Start Screen | 一個介面,帶有名稱、是否使其後方的遊戲畫面變暗(預設開啟)、背景、顯示的介面是否截獲所有點選(模態),以及寫法與標籤參數相同的參數(question="Who?")。 |
| Start Contents | 一組本身不構成介面的元素,用於填充容器、分支或迴圈;它和介面一樣用 Add 節點構建。 |
| Add Screen Text | 文字,可以用 [name] 顯示變數和參數,帶有字型大小、顏色和換行寬度。 |
| Add Screen Image | 一張圖片:影像名稱或檔案,帶有縮放比例。 |
| Add Screen Button | 一個帶文字的按鈕,包括按下時執行的操作、以像素為單位的尺寸(0 表示適應文字),以及一個用於 sensitive 的 Condition:僅在其成立時可按,否則顯示為灰色。 |
| Add Picture Button | 一張可按的圖片,例如地圖上的一個地點,指標懸停時顯示另一張圖片,並帶有一個用於 sensitive 的 Condition。 |
| Add Screen Bar | 一個相對於最大值顯示變數的進度條,例如滿分十分的信任度。 |
| Add Screen Input | 一個將輸入寫入變數的文字方塊,帶有長度限制、允許的字元和寬度。 |
| Add Screen Space | 一塊指定尺寸的空白區域,用於在容器中隔開各項內容。 |
| Add Screen Timer | 經過若干秒後執行,就像限時選項到時一樣;設為重複時,每次到時都執行。 |
| Add Screen Key | 介面顯示期間按下某個鍵時執行:escape、enter、space、left、一個字母、f1。 |
| Add Box | 一個容器,裝著來自 Start Contents 的元素,按種類排列:vbox 上下排列,hbox 左右並排,grid 按指定列數分行,frame 放在一個使用主題顏色的面板上,fixed 各自放在其位置所指定的地方,viewport 上下排列、超出部分被裁剪並可用滾輪滾動。它接受間距、內邊距、背景顏色或影像,以及尺寸(0 表示適應其所含內容)。 |
| Add For Each | 對一個列表變數中的每一項,各生成一次來自 Start Contents 的元素,該項放在其自己的變數中:例如為 bag 中的每件禮物生成一個按鈕。 |
| Add If | 在某個 Condition 成立時顯示一些元素,並可選在其不成立時顯示另一些元素。 |
| Add Use Screen | 就地使用另一個介面的元素,例如多個介面共用的狀態列,其參數的實參按指令碼的寫法填寫,以逗號分隔("Wen", trust + 1)。它們是表示式,因此 Add For Each 的行可以把它的項傳下去。 |
| Add Screen Variable | 介面自己的變數及其初始值(按輸入的型別);介面的按鈕可以更改它,它與介面同存續。 |
| Anchor Last Element | 以元素自身中心以外的某個點來放置最後新增的元素,該點以 X Anchor 和 Y Anchor 表示其尺寸的比例:(0, 0) 將其左上角放在其位置上,(1, 1) 則是右下角。結合元素自身的位置,這就相當於指令碼的 anchor,進而相當於其 pos 和 align:(1, 1) 放在 (1, 1) 處會使元素位於角落,與 align (1.0, 1.0) 相同。在 vbox、hbox 或 grid 中,它改為在元素所佔的位置內對齊該元素。 |
| Style Last Element | 為最後新增的元素指定故事中的一個樣式,相當於指令碼的 style "card";對於容器,還可為其所含內容的樣式指定字首,相當於 style_prefix "gold"。樣式為空時保留其種類的樣式。 |
| Set Last Element Style Property | 在最後新增的元素本身上設定一個樣式屬性,疊加在其樣式之上,值按指令碼的寫法填寫:outline_width 2。在按鈕上,以 text_ 開頭的屬性用於設定其標籤文字的樣式:text_color "#ffffff"。 |
| Set Screen Style Prefix | 介面上所有內容的樣式字首:使用 gold 時,如果故事中有 gold_button 和 gold_button_text,介面的按鈕就用前者繪製,按鈕的標籤文字用後者繪製。 |
| Screen To Script | 以指令碼形式寫出的介面。 |
容器、分支或迴圈包含一條 Start Contents 鏈,該鏈本身也可以包含容器,因此介面是在 Add Screen 之下以一棵輸入樹的形式構建的。直接位於介面中、fixed 或 frame 中的元素接受一個位置,而位於 vbox、hbox、grid 或 viewport 中的元素由其容器放置。0 到 1 之間的位置表示區域的比例,大於 1 的位置表示像素,因為節點中的數字沒有小數點可供區分;除非 Anchor Last Element 指定以另一個點放置,否則每個元素都以其位置為中心。大多數元素接受一個可選的 Condition,僅在其成立時顯示。
按鈕、計時器或按鍵執行的操作是一個 Button Actions 值:
| 節點 | 作用 |
|---|---|
| Answer | 以一個值(按輸入的型別)應答被呼叫的介面,故事將其讀作 _return。 |
| Go To Label | 關閉介面,並在某個標籤處繼續故事。 |
| Set Variable Action | 將變數設為一個值(按輸入的型別):如果介面自己有同名變數則設定它,否則設定故事的變數。 |
| Set Variable To Action | 在按下按鈕時將變數設為某個表示式的結果,例如 Add For Each 行中的項:item。 |
| Toggle Variable Action | 將為真的變數變為假,為假的變為真。 |
| Notify Action | 顯示一條通知。 |
| Play Sound Action | 播放一次音效。 |
| Open Menu Action | 開啟遊戲的某個選單:save、load、preferences、history、gallery、music_room、achievements 或 main_menu。 |
| Close Screen | 關閉介面;被呼叫的介面應答為空值。 |
| Show Screen Action、Hide Screen Action | 顯示或隱藏另一個介面。 |
| Run Command Action | 執行遊戲註冊的一個命令。 |
| Then Action | 先執行一個操作,再執行另一個:例如先設定變數,再前往某個標籤。 |
Story
| 節點 | 作用 |
|---|---|
| Make Label | 由名稱和序列構成的標籤;遊戲從 start 開始。 |
| Start Story | 一個空故事。 |
| Add Label、Add Character、Add Image、Add Default | 多了一個標籤(替換同名標籤)、角色、影像或變數預設值的故事。 |
| Make Label With Parameters | 一個接受實參的標籤,參數按指令碼標籤行的寫法填寫(who, times=1),由 Call With Arguments 傳入,標籤將其作為變數讀取。 |
| Add Image From Source、Add Layered Image | 新增了一個來自 Images 節點的影像或一個分層影像的故事。 |
| Add Transition | 新增了一個由內建轉場構成的具名轉場的故事:例如將 slow 定義為 dissolve(2)。 |
| Add Audio Name、Add Channel、Add Music Track | 新增了一個音訊檔名稱、一個自己的音訊通道,或一首音樂空間曲目(在聽到時或某個 Condition 成立時解鎖)的故事。 |
| Add Constant | 新增了一個常量的故事,該常量在遊戲開始時設定,並在讀檔後再次設定,因此更改後的值也會作用於舊存檔。 |
| Add Gallery Entry When | 新增了一個畫廊條目的故事,該條目在某個 Condition 成立時解鎖,而不是在其圖片被看到時解鎖。 |
| Add Screen | 新增了一個來自 Screens 節點的介面的故事。 |
| Add Style | 新增了一個來自 Styles 節點的樣式的故事:一種自己的外觀,或者在使用 Novella 自帶名稱(例如 say_window)時,對遊戲相應部分的細化。同名的第二個樣式會疊加到第一個之上。 |
| Add Python Definitions | 新增了在遊戲開始時執行一次的 Python 的故事,相當於指令碼的 init python::其中定義的函式可以在任何條件、文字或效果中呼叫,例如 [title_for(trust)]。 |
| Translate Line、Translate Line By Id、Translate String | 新增了翻譯的故事:翻譯一句臺詞(通過其標籤、說話者和文字,或通過 Say Line 為其指定的 id 尋找),或翻譯任何其他文字:選項、名稱、提示、通知。 |
| Story From Script | 從指令碼文字讀取的故事。 |
| Story From Library | 從文件庫中的指令碼檔案讀取的故事。 |
| Combine Stories | 將兩個故事合為一個。 |
| Story To Script、Label Names | 以指令碼文字表示的故事,以及其標籤的名稱。 |
| Check Story | 單獨檢查一個故事:未定義的標籤、角色、變換和轉場。 |
Characters
Make Character 由 id、顯示名稱、名稱顏色、影像標記,以及是否使用側邊影像或在 NVL 頁面上說話來建立一個角色。Style Character 返回一個使用不同文字顏色、字型或引號的副本。
另有兩個節點為角色的臺詞賦予自己的外觀,相當於指令碼的 window_style 和 what_size 40(見樣式)。臺詞的組成部分有 window(對話視窗)、namebox(名稱標籤)、who(名稱)和 what(臺詞)。
| 節點 | 作用 |
|---|---|
| Character Part Style | 一個角色,其臺詞的某一部分使用故事中的一個樣式繪製:window 使用 ghost_window。 |
| Set Character Style Property | 一個角色,其臺詞的某一部分上設定了僅對該角色有效的樣式屬性:what、size、40,或 window、background、"#200000"。 |
Styles
Style 是用於文字和容器的具名外觀,是指令碼 style 定義的節點形式:一組屬性,帶有一個用於繼承其餘屬性的父樣式,以及針對元素所處各種狀態的變體。Add Style 將它放入故事。與 Novella 自帶樣式(say_window、say_dialogue、choice_button、menu_button 等)同名的樣式會細化每個遊戲介面的相應部分;任何其他名稱都是故事自己的外觀,可由介面元素、角色或臺詞中的 {style=name} 片段指明。
| 節點 | 作用 |
|---|---|
| Start Style | 一個帶有名稱和可選父樣式的樣式:例如由 button 派生的 gold_button。 |
| Set Style Property | 設定了一個屬性的樣式,值按指令碼的寫法填寫(顏色要連同引號寫成 "#ffd27a",以及 40、(24, 12)、true、center),作用於所有狀態,或在給出狀態時只作用於該狀態:hover、selected、insensitive、idle 或 visited。不是樣式屬性的名稱會被立即拒絕。 |
| Style To Script | 以指令碼形式寫出的樣式。 |
| Built-in Style Names | Novella 自帶樣式的名稱,以逗號分隔:即故事可以重新設定樣式的部分。 |
Start Style(
gold_button、button)→ Set Style Property(background、"#3a2a10")→ Set Style Property(background、"#6a4a18",狀態hover)→ Set Style Property(corner_radius、12)→ Add Style
樣式列出了每個屬性和每個內建樣式,並說明了如何沿著樣式的父樣式和狀態尋找屬性。
Game Definition
| 節點 | 作用 |
|---|---|
| Make Game Definition | 以資料形式表示的完整遊戲:標題、故事、寬度和高度。 |
| With Config、With Theme | 更改了一項設定的副本,該設定優先於故事自身對同一鍵的 define。 |
| With Library Assets | 從文件庫讀取檔案的副本,可選同時將庫中的指令碼載入到故事中。 |
| With Asset Folder | 從某個資料夾讀取檔案的副本。 |
| With Story | 新增了另一個故事內容的副本。 |
| Check Game | 靜態檢查,同時對照檔案檢查故事。 |
| Run Game Definition | 在視窗中執行一個定義:函式式描述的過程式終點。 |
函式式節點返回新值,從不更改其輸入,因為資料流圖會快取值,並且可能把同一個值交給兩個分支。
Routine 圖
Routine 圖就是以節點形式表示的 C# 程式。在其執行路徑上:

- Make Novella Game:標題
The Red Thread,寬度1920,高度1080。 - Add Library Assets:遊戲的影像、聲音、字型和指令碼,嵌入在文件中。
- Load Scripts From Assets:資料夾
scripts。 - Set Config:
autosave_slots、8。 - Run。
執行這個圖,遊戲就會在視窗中開啟。用 Validate 代替 Run,再列印其結果,就是靜態檢查。
Register Command 將一個 run 命令繫結到一個沒有輸入也沒有結果的函式,適用於只做某件事的命令,例如寫日誌或開啟網頁。Register Command Function 將命令繫結到一個以文字形式接受實參並給出應答的函式,Register Expression Function 則對故事表示式所呼叫的函式做同樣的事。命令也可以由 Events 圖的 Command 事件來應答,The Red Thread 的 run fortune 就是這樣處理的。
Events 圖
在 Events 圖中,遊戲是一個類。將圖的基型別設為 Novella Application(一個 Novella Game),遊戲的回撥就會成為圖可以實現的事件,而每個 Novella Game 節點都作用於圖自己的遊戲,無需連線接收者:

| 事件 | 何時執行 |
|---|---|
| Setup | 在視窗開啟之前執行一次:設定、資源、指令碼、定義。 |
| Script | 如果實現了它,開始遊戲時會將其作為即時指令碼執行,而不是從故事的起始標籤開始。 |
| Command | 用於沒有任何人註冊的 run 命令:它接收名稱和文字形式的實參,不返回任何值;它用 Set Result 應答,故事將應答讀作 _return(未設定時為空值)。 |
| Label Entered | 每當故事進入一個標籤時。 |
| Game Ended | 故事結束時,在返回主選單之前。 |
只有圖實際實現的事件才會生效,因此不實現 Script 就會讓故事的標籤掌控流程,不實現 Command 則會使未知命令成為錯誤。
The Red Thread 的文件這樣應答其故事中的 run fortune:
Command → Set Result,其輸入是對一組籤文中某一張籤的 Translate Text,該籤由 Random Integer 在 0 到最後一個索引之間選出
一個從文件庫載入指令碼的 Setup 就構成了一個完整的遊戲:
Setup → Set Resolution(1920, 1080)→ Add Library Assets → Load Scripts From Assets(
scripts)
要執行它,執行這個圖即可;此包為 Novella Application 註冊的 Novella 框架會開啟視窗。Plugins > Frameworks > Novella > Run Novella Game 選單項對文件的入口圖做同樣的事。
以節點形式編寫的即時指令碼
實現 Script 會使該事件的執行路徑成為故事本身。Say、Show、Scene 等節點逐個播放,並在玩家作出應答後繼續;Menu 返回所選項的索引,供 Branch 或 Switch 使用,Input 返回輸入的內容:

Script → Scene(
bg garden、fade)→ Show(qinglan smile、right、dissolve)→ Say(q、What hangs in the treetop?)→ Menu(A gong、The moon)→ 根據 choice = 1 進行 Branch → Say(q、The moon. Correct.)
這是用節點編寫小遊戲最直接的方式。它的侷限是明確說明的,而非隱藏的:圖的執行位置不是資料,因此即時指令碼無法存檔、讀檔或回滾。Call Label 可以從即時指令碼中執行一個故事標籤,但只要即時指令碼仍在其下層執行,存檔和回滾就仍不可用。對於玩家會存檔的遊戲,請將故事寫成標籤或場景(用指令碼或函式式節點均可),並將 Events 圖留給設定和命令。見概念。
函式式故事構建
函式式節點無需任何指令碼即可編寫故事。一個標籤就是一條鏈:

Start Sequence → Scene(
bg garden、fade)→ Show(qinglan smile、right、dissolve)→ Say(q、You came.)→ Menu(提示文字,帶有自己序列的 Make ChoiceI did.,帶有自己序列的 Make ChoiceI was passing.)→ Make Label(start)
而故事負責收集標籤和定義:
Start Story → Add Label(start)→ Add Label(garden)→ Add Character(Make Character
q、Qinglan、#c0392b、影像qinglan)→ Add Default(affection、0)→ Make Game Definition(The Garden、故事)→ With Library Assets → With Theme(text_size、40)
邏輯也無需指令碼。基於變數的分支和對變數的更改同樣是節點:
Apply Effect(Add To Variable
affection、1)→ If(Variable At Leastaffection、3;then 為包含 Sayq、Then stay.的序列;otherwise 為包含 Sayq、Then go.的序列)
而只在某些情況下才提供的選項,則在其 Make Choice 上接受一個條件:All Of(Has Visited market,Not(Variable Is Set gift))。
兩種風格可以自由混用:在節點用起來不順手的地方,Story From Script 或 Script 節點可以引入指令碼文字,Condition From Script 和 Effect From Script 也可以為單個判斷或更改做到這一點;Combine Stories 將指令碼編寫的故事與節點構建的故事合併;Story To Script 則將其中任何部分顯示為指令碼。由條件和效果節點構建的故事,列印出的指令碼與人手寫的相同,並且該指令碼讀回後也完全相同。
由節點構建的標籤不來自任何檔案,因此不會像指令碼中的標籤那樣落入下一個標籤:執行到其末尾即結束遊戲,或返回到其呼叫方。應當繼續往下走的標籤要以 Jump、Call 或 Return 結尾。當一個由節點構建的標籤可能執行到末尾、而它後面的標籤也是由節點構建的時,靜態檢查會發出警告,因為指令碼中的標籤在那裡會落入下一個標籤。
在 Function 圖中實現邏輯
當 Conditions 和 Effects 節點無法組合出所需的判斷或更改時,可以改用 Function 圖,同樣無需指令碼。Condition From Function、Number From Function、Text From Function 和 Jump From Function 各自接受文件中的一個成員 Function 圖,該圖接收故事的變數(一個 Story Variables),用其 const 成員 Number、Text、Flag 以及其餘 Story Variables 節點讀取這些變數,並給出應答:true 或 false、一個數字、一段文字,或要跳轉到的標籤名稱。Effect From Function 接受一個過程式圖(例如 Routine),該圖用 Set Number、Set Text、Set Flag 和 Add 更改變數;由於這些成員會改變故事,Function 圖不提供它們。該圖在節點的函式引腳上指定,與任何委託引腳指定函式的方式相同。
一個成員 Function 圖 Is Generous,帶有一個型別為 Story Variables 的輸入
Variables:Number(Variables、kindness)→ Bigger Than Or Equal(2)→ 其輸出Holds。在故事中:If(指定 Is Generous 的 Condition From Function;then 為包含 Say 的序列)
該圖讀寫的是故事的變數,因此其更改會隨故事一起存檔、讀檔和回滾。不過,與 C# lambda 一樣,函式沒有指令碼形式:Sequence To Script 會在其位置顯示一段描述,靜態檢查無法檢視其內部,而使用了它的故事也無法從其指令碼讀回。只要 Conditions 和 Effects 節點能夠表達,就請使用它們。
Novella Game 上的 Register Command Function 和 Register Expression Function 為指令碼做同樣的事:由圖實現一個接受實參並給出應答的 run 命令,或一個供故事表示式呼叫的函式。
以場景構成的遊戲
Scenes 節點無需手動連線標籤、跳轉或選單即可編寫遊戲。每個場景就是一個 Make Scene:
Make Scene(
start;臺詞 Start Sequence → NarrateA bridge in the rain.;結尾 Choose Scene(Cross it?,Scene ChoiceCross.→far_side,效果為 Add To Variablecourage,Scene ChoiceWait.→near_side);背景bg bridge)
Make Scene(
far_side;臺詞 NarrateThe far side.;結尾 Branch To Scene(Variable At Leastcourage、1;brave;near_side))
而故事負責收集這些場景及其使用的變數:
Start Story → Add Default(
courage、0)→ Add Scene(start)→ Add Scene(far_side)→ Add Scene(near_side)→ Add Scene(brave)→ Make Game Definition
在過程式圖中,則改用 Novella Game 節點 Add Scene 將每個場景新增到遊戲中。
描述、預覽、執行
推薦的工作流將遊戲的描述放在一處,並從兩處執行它:

- 在 Function 圖中描述遊戲。用函式式節點構建故事、角色和設定,並從圖中返回一個 Game Definition。
- 從 Flows 圖呼叫它以進行預覽。將該函式放入一個 Flows 圖,選中其輸出,然後在 Properties 面板中開啟 Custom Preview(自訂預覽)。遊戲會在自己的視窗、自己的執行緒中執行,存檔儲存在記憶體中(預覽從不觸及玩家的真實存檔),並開啟開發者主控台(Shift+O;
jump label可直接跳轉),即使遊戲的指令碼將developer_mode設為 false 也是如此。 - 將同一個定義交給過程式圖來真正執行它:Make Novella Game From Definition → Run,或 Run Game Definition。
Custom Preview 能執行的不只是完整的遊戲。沒有 start 標籤的 Story 從其第一個標籤開始,Label 作為單標籤故事執行,Sequence 作為 start 標籤執行,Scene 作為單場景故事執行,Novella Game 執行其定義,因此鏈上的任何節點都可以單獨試執行。不使用自訂預覽時,普通預覽會將值顯示為指令碼:序列、標籤或故事顯示為其對應的指令碼,角色顯示為其 character 行,遊戲定義則顯示為一段摘要及其後的指令碼。
文件中的資源
Divooka 文件可以攜帶其遊戲:嵌入在文件資源庫中的影像、聲音、字型、影片和指令碼(在 Divooka Compute 中為 Asset library,快捷鍵 Ctrl+Shift+A,使用 Import files… 匯入)。庫中的路徑就是指令碼所引用的路徑,因此請保留指令碼所期望的資料夾結構(bg/、sprites/qinglan/、audio/bgm/),並且影像在庫中按其路徑命名的方式與在磁碟上完全相同。
| 風格 | 節點 | 讀取的內容 |
|---|---|---|
| 過程式 | Add Library Assets | 庫中的每個檔案都成為遊戲的一個檔案;之後接上 Load Scripts From Assets 以載入指令碼。 |
| 函式式 | With Library Assets | 對定義做同樣的事;開啟其指令碼選項,即可同時將庫中的指令碼載入到故事中。 |
| 函式式 | Story From Library | 庫中的一個指令碼檔案,作為故事。 |
這三個節點都會自動取得文件的庫。庫檔案和資料夾可以組合使用:對於同一路徑,後新增的來源優先,因此在測試時,在庫之後新增的資料夾可以覆蓋庫中的部分檔案。
在 Asset library 中選中一個文字資源,會在預覽窗格中顯示其前幾行,而 .novella 指令碼也算作文字,因此無需匯出,就能在那裡分辨和閱讀遊戲的指令碼。
Divooka 無法涉及的部分
指令碼語言能表達的一切都有對應的節點,接受實參的命令和表示式函式也是如此,但有一個區別:節點傳給標籤、命令或介面的實參,是在圖構建故事時就固定下來的值,而指令碼中的實參是在播放時才求值的表示式。Add Use Screen 是個例外,它接受表示式。少數 C# 擴充點沒有對應的節點:以 C# 類編寫的介面(RegisterScreen),用於 Screens 節點無法佈局的任何內容;動畫的 function 語句所呼叫的函式(RegisterTransformFunction),由 Call Transform Function 指定其名稱;直接處理 Value 和執行器而非文字的命令和函式;以及 Events 圖之外的即時指令碼。關於這些內容,見開發。