繁體中文
English 简体中文 繁體中文
Methodox 首頁

在 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# 程式。在其執行路徑上:

Hello Novella:在 Routine 中建立遊戲、提供指令碼並執行

  1. Make Novella Game:標題 The Red Thread,寬度 1920,高度 1080。
  2. Add Library Assets:遊戲的影像、聲音、字型和指令碼,嵌入在文件中。
  3. Load Scripts From Assets:資料夾 scripts。
  4. Set Config:autosave_slots、8。
  5. 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 節點都作用於圖自己的遊戲,無需連線接收者:

The Red Thread 的 Events 圖:Setup 和 Command

事件 何時執行
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 事件

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 圖留給設定和命令。見概念。

函式式故事構建

函式式節點無需任何指令碼即可編寫故事。一個標籤就是一條鏈:

在 Flows 圖中用 Story Writing 節點構建的場景

Start Sequence → Scene(bg garden、fade)→ Show(qinglan smile、right、dissolve)→ Say(q、You came.)→ Menu(提示文字,帶有自己序列的 Make Choice I did.,帶有自己序列的 Make Choice I 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 Least affection、3;then 為包含 Say q、Then stay. 的序列;otherwise 為包含 Say q、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 → Narrate A bridge in the rain.;結尾 Choose Scene(Cross it?,Scene Choice Cross. → far_side,效果為 Add To Variable courage,Scene Choice Wait. → near_side);背景 bg bridge)

Make Scene(far_side;臺詞 Narrate The far side.;結尾 Branch To Scene(Variable At Least courage、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 將每個場景新增到遊戲中。

描述、預覽、執行

推薦的工作流將遊戲的描述放在一處,並從兩處執行它:

返回 Game Definition 的 Function 圖

  1. 在 Function 圖中描述遊戲。用函式式節點構建故事、角色和設定,並從圖中返回一個 Game Definition。
  2. 從 Flows 圖呼叫它以進行預覽。將該函式放入一個 Flows 圖,選中其輸出,然後在 Properties 面板中開啟 Custom Preview(自訂預覽)。遊戲會在自己的視窗、自己的執行緒中執行,存檔儲存在記憶體中(預覽從不觸及玩家的真實存檔),並開啟開發者主控台(Shift+O;jump label 可直接跳轉),即使遊戲的指令碼將 developer_mode 設為 false 也是如此。
  3. 將同一個定義交給過程式圖來真正執行它: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 圖之外的即時指令碼。關於這些內容,見開發。