腳本標籤(label)和主控流程 link

label語句 link

label語句允許使用自訂的標籤名聲明一個程序點位。這些標籤僅僅用來被調用或者跳轉,可以使用在Ren’Py腳本、python函數及各類界面中。

label sample1:
    "這是一個'sample1'腳本標籤。"

label sample2(a="default"):
    "這是一個'sample2'腳本標籤。"
    "a = [a]"

一個label語句可能只跟某一個語句塊(block)關聯。在那種情況下,主控流程遇到label語句就會進入關聯語句塊(block),並順序執行之後的語句。

總共有兩種腳本標籤(label):globallocal 。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腳本標籤後面,可以將遊戲的狀態數據重設為初始值。接著遊戲可以重新繪製場景、播放音樂等,最後跳轉到目標腳本標籤並繼續。