腳本標籤(label)和主控流程 link
label語句 link
label語句允許使用自訂的標籤名聲明一個程序點位。這些標籤僅僅用來被調用或者跳轉,可以使用在Ren’Py腳本、python函數及各類界面中。
label sample1:
"這是一個'sample1'腳本標籤。"
label sample2(a="default"):
"這是一個'sample2'腳本標籤。"
"a = [a]"
一個label語句可能只跟某一個語句塊(block)關聯。在那種情況下,主控流程遇到label語句就會進入關聯語句塊(block),並順序執行之後的語句。
總共有兩種腳本標籤(label):global 和 local 。global標籤在所有項目文件中都生效,所以每個遊戲中都不能重複定義。 local標籤可以同名,但需要與不同的global標籤做關聯。 需要聲明一個local標籤的話,在標籤名前綴一個英文句號“.”即可。例如:
label global_label:
"這在一個global腳本標籤裡。"
label .local_label:
".這裡屬於local腳本標籤。"
jump .another_local
label .another_local:
"另一個local腳本標籤"
jump .local_label
local腳本標籤在關聯的global標籤內部可以直接引用。其他地方則需要使用標籤全名,由關聯的globle標籤和local標籤組成。 一個關於global標籤和local標籤的例子如下:
label another_global:
"現在讓我們跳轉進入其他地方的local腳本標籤。"
jump global_label.local_name
lable語句可以帶一些可選參數。這些參數的處理在 PEP 3102 中有詳細說明,這裡僅說兩種例外:
語句被調用時,才計算默認參數的值。
變數具有動態生命週期。
如果某個變數具有動態生命週期,它的值會持續到其所屬的label標籤中出現一個return語句為止。 嘗試使用jump或previous語句傳遞該變數的值都是不明智的。 帶有參數的label樣例,詳見 call語句 。
jump語句 link
jump語句用於將主控流程轉入指定的腳本標籤(label)處。
若出現了 expression
(表達式)關鍵字,關鍵字後面的表達式將被賦值,而被計算後的對應字串則會被用作跳轉目標的標籤語句。若未出現 expression
(表達式)關鍵字,跳轉目標的標籤名字就必須精確指定。
與call語句不同,jump語句不會將下一個語句放入棧(stack)中。因此,執行完跳轉標籤對應的語句塊之後,主控流程不會回到跳轉前的腳本位置。
label loop_start:
e "哦,不!看起來我們陷入了一個無限循環之中。"
jump loop_start
call語句 link
call語句用於將主控流程轉入給定的腳本標籤(label)處。call語句會將下一條語句壓入到調用棧(stack)中,並允許主控流程在執行完這次調用後,回到調用發生的腳本位置。
若出現了 expression
(表達式)關鍵字,關鍵字後面的表達式將被賦值,而被計算後的對應字串則會被用作跳轉目標的標籤語句。若未出現 expression
(表達式)關鍵字,跳轉目標的標籤名字就必須精確指定。
from
分句是可選的,在label語句後面直接添加入參名和值,並直接在該label下直接使用。一個命名直接的標籤(lable)有助於我們能利用棧(stack)回到腳本裡合適的地方,就算載入的是修改過的腳本。
call語句可以使用參數,詳見 PEP 448。
當我們使用一個帶入參列表的調用表達式時,必須在表達式和入參列表之間插入關鍵字 pass
。
否則,入參列表會被當作表達式的一部分,而不是call語句的一部分。
label start:
e "首先,我們調用一個支線。"
call subroutine
call subroutine(2)
call expression "sub" + "routine" pass (count=3)
return
label subroutine(count=1):
e "我來過這裡 [count] 次了。"
e "接著,我們會從支線返回。"
return
Warning
每條 call
語句後面都不加上 from
從句就發布遊戲是危險的。當然也可以通過發布更新補丁解決。
在沒有 from
從句的情況下,編輯 call
相關的腳本,可能會有存檔損壞的風險。
構建發行版時,將選項“向call語句添加from從句”勾選上就能解決以上問題。
return語句 link
return語句會在調用棧中彈出最頂層的那條語句,並將主控流程轉到那條語句。若調用棧為空,返回語句將重啟Ren’Py,將主控流程切換至主選單。
若返回語句帶有可選項表達式,表達式會被計算求值,並且結果會被儲存在_return變數中。_return變數依賴於各種場景動態變化。
特殊腳本標籤(label) link
以下腳本標籤(label)會在Ren’Py中使用:
start
默認情況下,Ren’Py在遊戲啟動後會跳轉至這個標籤。
quit
若該標籤存在,當用戶退出遊戲時該標籤內容會被調用。
after_load
若該標籤存在,當遊戲讀檔後會調用這個標籤內容。其可能被用於遊戲內容更新後的數據修復。 如果數據從此標籤後發生變化,應該調用
renpy.block_rollback()
函數防止用戶從該存檔點回滾。splashscreen
若該標籤存在,遊戲首次運行時,在主選單出現前,該標籤內容會被調用。 詳見 添加啟動畫面 。
before_main_menu
若該標籤存在,在主選單出現前,該標籤內容會被調用。在少數情況下,其用來設置主選單,例如背景播放一段影片。
main_menu
若該標籤存在,標籤內容會被調用,用來替代預設的主選單。若其內容中包含return語句,Ren’Py將從start標籤處開始遊戲。例如,下面這段腳本在不顯示主選單的情況下開始遊戲。
label main_menu: return
after_warp
若該標籤存在,則調用warp語句時,此標籤至傳送(warp)點前的語句都將被執行。詳見 傳送至某行
hide_windows
若該標籤存在,當玩家使用滑鼠右鍵或鍵盤H鍵隱藏對話窗口時,將調用此標籤。 若標籤返回值為True,隱藏對話窗口行為將取消(依然當作隱藏已經發生)。否則,繼續隱藏對話窗口。
腳本標籤(label)和主控流程函數 link
- renpy.call_stack_depth() link
返回當前上下文(context)中調用棧的深度——即調用棧中還沒有返回或彈出(pop)的call語句數量。
- dynamic(*variables, **kwargs) link
該函數可以將若干個變數名作為入參,並根據當前調用動態調整這些變數。當調用返回後,變數的值會恢復為該函數調用之前的值。
命名儲存空間 中的變數都可以支持。
如果變數以關鍵字入參形式傳入,入參的值等於其關聯的變數名對應的值。
調用樣例如下:
$ renpy.dynamic("x", "y", "z") $ renpy.dynamic("mystore.serial_number") $ renpy.dynamic(players=2, score=0)
- renpy.get_all_labels() link
返回程序中定義所有標籤(lable)的集合,包括在庫(library)中定義為僅限內部引用的標籤。
- renpy.get_return_stack() link
返回一個當前返回(return)棧(stack)的列表。返回棧是一個語句名組成的列表。
該語句名應是字串(針對標籤),或者非空元組(針對非標籤型語句)。
- renpy.has_label(name) link
若參數name是一個程序內的合法腳本標籤(label)就返回True,否則返回False。
- name
name應該是一個字串,用於檢查某個腳本標籤(label)是否存在。name也可以是一個非空元組,給定非標籤型語句名。
- renpy.mark_label_seen(label) link
在當前用戶系統內,將名為label的標籤語句設置為已執行過。
- renpy.mark_label_unseen(label) link
在當前用戶系統內,將名為label的標籤語句設置為未執行過。
- renpy.pop_call() link
從調用棧頂部彈出(pop)當前call,但不返回到對應call的位置。 該函數與Ren’Py的return語句一樣,都會恢復
dynamic
函數用到的參數。當確信某個腳本標籤(label)不會返回到其調用點時,可以使用此函數。
- renpy.seen_label(label) link
在當前用戶系統內,名為label的標籤語句至少被執行了一次,則返回True,否則返回False。該概述常用於解鎖場景畫廊(gallery)等。
- renpy.set_return_stack(stack) link
設置當前返回(return)棧(stack)。返回棧是一個語句名組成的列表。
語句名可能是字串(針對標籤)或者非空元組(針對非標籤語句)。
常用方法為:
renpy.set_return_stack([])
可以清空返回棧。
上下文 link
上下文(context)是Ren’Py用於管理遊戲中可以修改並且可以存檔的各種狀態值,具體包括:
當前Ren’Py運行狀態
調用棧,已經上面提到的
renpy.dynamic()
使用的各種動態變數名和變數值。當前顯示的所有圖像資訊(包括圖像屬性和用到的各種變換等)
當前顯示的界面和界面中的各種變數
正在播放或在播放隊列中的音訊
大多數時候遊戲中僅有一個上下文,上下文中的各項也僅存在一個實例。 進入主選單或遊戲內菜單時,上下文中的各項可能會改變,但在離開菜單後各項會恢復。 其中一些改變是自動處理的,比如screen圖層在上下文內容變化時會清空。
使用 重播 功能和 隱藏UI
函數時,Ren’Py會創建新的上下文。
界面語言 的創立,很大程度上就是為了減少頻繁創建上下文。
僅在基本上下文(即僅有一個上下文時的那個)中才能使用回滾(rollback)。也只有基本上下文才可以存檔,這是遊戲菜單會用到上下文。
- renpy.call_in_new_context(label, *args, **kwargs) link
該函數創建一個新的上下文(context),並從這個上下文(context)中給定的腳本標籤(label)處開始執行Ren’Py腳本。新的上下文(context)中禁用了回滾功能,並且存檔/讀檔會發生在頂層的上下文(context)中。
使用該函數可以在原有交互中啟動第二層交互。
- renpy.context() link
返回一個唯一對象,指向當前上下文。進入某個新的上下文時,該對象也將被賦值為新的上下文。但對該對象的修改不會影響其指向的原上下文內容。
該對象可以存檔,並參與回滾操作。
- context_dynamic(*variables) link
該函數可以將若干個變數名作為入參,並根據當前上下文調整這些變數。當返回前一個上下文後,變數的值會恢復為該函數調用之前的值。
命名儲存空間 中的變數都可以支持。
調用樣例如下:
$ renpy.context_dynamic("x", "y", "z") $ renpy.context_dynamic("mystore.serial_number")
- renpy.context_nesting_level() link
返回當前上下文的嵌套層級(nesting level)。 最外層的上下文的層級為0(該層上下文可以存檔、讀檔和回滾)。其他上下文的嵌套曾經都不是0,比如菜單和重播的上下文。
- renpy.invoke_in_new_context(callable, *args, **kwargs) link
該函數創建了一個新的上下文(context),並在上下文(context)中顯示調用時指定的python可調用內容(通常是函數)。當函數返回值或者拋出異常時,主控流程會返回到原來的上下文(context)。當我們在同一個句柄(handle)中向玩家展示一些資訊(比如確認提示),就可以調用這個函數。
其他額外入參都將傳給callable處理。
該函數創建的上下文無法執行Ren’Py腳本。能改變Ren’Py腳本執行流程的函數,比如
renpy.jump`都會由外層的上下文處理。 如果想要調用Ren'Py腳本而不是Python函數,需要改用 :func:`renpy.call_in_new_context()
.
- renpy.jump_out_of_context(label) link
調用該函數會使主控流程離開當前上下文(context),並轉換到父層上下文(context)中指定的腳本標籤(label)處。
- renpy.reset_all_contexts() link
該函數會上下文棧中的所有元素都彈出(pop off),恢復所有動態變數的值。完成以上內容後,再創建一個新的上下文。 當前語句結束,遊戲從下一條語句繼續執行。遇到異常的數據或起始點時,這樣做能將Ren’Py設置為初始狀態。
該函數可用於重設遊戲內的一切——包括顯示的圖像、播放的音樂等,就像遊戲剛開始運行。
由於該函數會重設Ren’Py,當前語句會立刻結束。
該函數設計用在after_load腳本標籤後面,可以將遊戲的狀態數據重設為初始值。接著遊戲可以重新繪製場景、播放音樂等,最後跳轉到目標腳本標籤並繼續。