變換

變換(transform)可以按順序依次使用,將一個 可視組件 變為另一個可視組件。 總共有多種類型的變換,也有多種方式創建變換。 內建的變換常用於控制界面上某個對象的位置,而用戶自訂的變換可以觸發更複雜的效果,比如移動、縮放和旋轉,甚至複雜的色彩效果。

快速入門

在scene和 show 語句後使用at分句就能應用各種變換。 下面樣例中對圖像 eileen happy 應用了 right 變換:

show eileen happy at right

可以同時應用多個變換,不同變換之間用英文逗號分隔。這些變換從左到右依次應用。

show eileen happy at halfsize, right

簡單ATL變換:

transform slide_right:
    xalign 0.0
    linear 1.0 xalign 1.0

label start:
    show eileen happy at slide_right
    pause

使用Python顯示變換:

label start:
    $ renpy.show("eileen happy", at_list=right)
    pause

使用 At() 的簡單Python變換:

init python:
    def show_eileen_rotated():
        rotated = Transform(rotate=45)
        show_stmt = At("eileen happy", rotated)
        renpy.show("eileen", what=show_stmt)

label start:
    $ show_eileen_rotated()
    pause

內建變換

Ren’Py附帶了一些默認定義好的變換。這些變換定義了界面上的位置資訊。這裡有一個默認變換一下圖像位置的描述:

             +-----------------------------------------------------------+
             |topleft, reset               top                   topright|
             |                                                           |
             |                                                           |
             |                                                           |
             |                                                           |
             |                          truecenter                       |
             |                                                           |
             |                                                           |
             |                                                           |
             |                                                           |
offscreenleft|left                   center, default                right|offscreenright
             +-----------------------------------------------------------+

offscreenleft 和 offscreenright 變換會讓圖像顯示在界面之外。這兩個變換可以用於將物體從界面移除(記得之後隱藏這些物體,並確認他們不再消耗系統資源)。

這些變換(transform)的詳細資訊如下:

center

水平居中,並與界面底部對齊。

default

水平居中,並與界面底部對齊。default可以通過 config.default_transform 重定義,這樣show和scene語句顯示的圖片默認位置也會改變

left

與界面左下角對齊。

offscreenleft

將可視組件置於界面左外側,與界面底部對齊。

offscreenright

將可視組件置於界面右外側,與界面底部對齊。

reset

將所有變換特性的值都重設為預設值。

right

與界面右下角對齊。

top

水平居中,與界面頂部對齊。

topleft

與界面左上角對齊。

topright

與界面右上角對齊。

truecenter

水平和垂直都居中。

動畫和變換語言

動畫和變換語言(簡稱ATL)提供了一種高級方式,便於創建動畫、界面內移動可視組件、設置組件位置、應用各種變換(等。 ATL語言可以根據時間變化實現效果,也可以根據事件類消息做出響應。

在Python中,與ATL變換等效的是 Transform() 類組件。目前沒有辦法通過編程創建一個ATL變換效果。

可以使用 transform語句 創建ATL變換對象。創建結果可用作可視組件(可能沒有能被看到的子組件所以透明)。 ATL變換對象可以使用 add 傳入某個界面,或者使用 show expression語句 或 renpy.show() 函數直接顯示。

Ren’Py腳本語句

ATL可以包含在Ren’Py腳本語句中。

transform語句

transform 語句會創建一個新的變換,可以在遊戲中用於可視組件設置坐標和動畫。 變換是可以復用的,使用 show 或 scene 加上 at 從句就能將變換應用在圖像和其他可視組件上。

變換也可以像 可視組件 一樣直接顯示。與可視組件儲存在全局image命名空間(詳見 定義圖像(image))中不同,變換會以變數的形式儲存在各合適的 命名儲存區 中(或默認儲存區)。

遊戲啟動時在 初始化階段 創建變換。

語法

基本格式:

transform <transform_name>:
    <atl_block>

帶參數的格式:

transform <transform_name>( <parameters> ):
    <atl_block>

使用方法

名稱

類型

描述

transform_name

word

變換的名稱。

必須是合法Python名,可使用英文符號“.”分隔。

(例如,my_transform 或 sprites.bounce)

parameters

–

(可選)變換的參數。

atl_block

block

ATL代碼塊,定義變換。

創作者可以給變換添加參數,提高其靈活性和可復用性。參數的用法與Python中函數的參數類似。

目前不支持的參數用法如下:

  • 只有固定位置參數 (使用 /)。

  • 只有關鍵字參數(位於 * 之後且無預設值)。

  • *args (可變的固定位置參數)。

  • **kwargs (可變的關鍵字參數)。

Note

樣例

transform left_to_right:
    xalign 0.
    linear 2 xalign 1.
    repeat

transform ariana.left:
    xalign .3

transform animated_ariana_disp(duration=1.0):
    "ariana"
    pause duration
    "ariana_reverse"
    pause duration
    repeat

label start:
    show eileen happy at left_to_right
    pause
    show animated_ariana_disp
    pause

帶ATL語句塊的image語句

使用ATL的另一種方法是,在 images 語句中包含ATL語句塊。這將某個圖像與給定的transform綁定。由於沒有辦法向該transform傳入參數,所以只在transform自身定義了某個動畫的情況下才有用。

語法

image <image_name>:
    <atl_block>

使用方法

名稱

類型

描述

image_name

word(s)

圖像名稱

atl_block

block

ATL代碼塊,定義變換。

樣例

image animated_ariana_img:
    "ariana"
    pause 1.
    "ariana_reverse"
    pause 1.
    repeat

帶ATL語句塊的scene和show語句

最後一種使用ATL的方法是,包含在 scene 或者 show 語句中。這種方法可以通過ATL改變圖像。

語法

show <image_name>:
    <atl_block>

scene <image_name>:
    <atl_block>

使用方法

名稱

類型

描述

image_name

word(s)

圖像名稱

atl_block

block

ATL代碼塊,定義變換。

樣例

show eileen happy:
    xalign 1.

scene bg washington:
    zoom 2.

ATL語法和語義

ATL語句可能是單行的,也可能是多行組成的語句塊(block)。 除了後面會提到的少數例外,ATL語句塊中的語句按從上到下的順序執行。

如果某個ATL語句需要計算某個表達式,那麼對應的整個變換首次執行時(例如使用 show 語句或將該變換顯示為某個界面的一部分時)將計算該表達式, 而不是執行某部分ATL語句時才計算。

下面列出各種ATL語句。

特性值語句

該語句可以將設置變換特性的值。

語法

<property_name> <property_value>

使用方法

名稱

類型

描述

property_name

word

變換特性的名稱(例如 xalign,alpha 等)。

property_value

Varies

特性的值

“特性名”+“新的特性值”是該語句的用法。詳見 變換特性 中使用列表形式同時給多個特性複製的方法。

樣例

transform rightoid:
    xalign .9

transform ariana.left:
    xanchor .3 xpos 100

數值語句

數值語句可以暫停ATL語句塊的執行一段時間,具體時間由給定的數值決定。關鍵字“pause”可以省略。

語法

pause <duration>

使用方法

名稱

類型

描述

“pause”

keyword

(可省略)關鍵字,提示此處暫停。

duration

float, int (expr)

暫停時間,單位為秒。

樣例

transform pause_example(duration=0.5):
    xalign 0.0

    # 暫停2秒。
    pause 2.0
    xalign 1.0

    # 暫停 `duration` 秒。
    pause duration
    xalign 0.5

    # 暫停3秒。
    3.0

    repeat

插值語句

插值語句主要用於獲取平滑的動畫效果。數值將隨著時間從初始值變化為指定值。

warp函數 用於控制插值結果與時間的關係。

語法

基本格式:

<warper_name> <duration> <atl_property> [<atl_property> ...]

使用warp函數:

warp <warper_function> <duration> <atl_property> [<atl_property> ...]

語句塊格式:

<warper_name> <duration>:
    <atl_property>
    <atl_property>
    ...

使用方法

名稱

類型

描述

warper_name

word

內建warper 名稱。

warper_function

str, function (expr)

warp函數和簽名 (t: float) -> float

duration

float, int (expr)

整個插值過程總時長,單位為秒。

atl_property

特性值語句

待插值的特性。

整個插值語句的持續時長由給定的時間決定,至少為1幀。

指定的 變換特性 會逐漸逼近終值,並在插值語句結尾達到該終值。

如果某個 變換表達式語句 中只有一條特性(property)語句,也可以進行插值計算。 起始值就是ATL變換中對應特性的值,跟直接設置起點的值效果相同。

樣例

基本用法:

show logo base:
    xalign 0.0 yalign 0.0

    # 耗時2秒,讓logo移動到左下角。
    linear 2.0 yalign 1.0

使用warp函數:

show logo base(warper_expr="easein"):
    xalign 0.0 yalign 0.0

    # 耗時1秒,使用作為參數傳入的warp函數將logo移動到界面最右側。
    warp warper_expr 1.0 xalign 1.0

處理多個特性:

show logo base:
    xalign 0.0 yalign 0.0

    # 同時改變xalign和yalign
    linear 2.0 xalign 0.5 yalign 0.5

    # 使用語句塊實現相同效果。
    linear 2.0:
        xalign 0.5
        yalign 0.5

使用創作者自訂的warp函數:

init python:
    def my_warper(t):
        return t**4.4

    my_warpers = [my_warper]

transform custom_warper_example:
    xpos 0
    warp my_warper 3 xpos 100
    warp my_warpers[0] 5 xpos 520

特性插值

使用樣條運動(曲線路徑):

<atl_property> knot <knot_value> [knot <knot_value> ...]

名稱

類型

描述

knot_value

Varies (expr)

控制節點上對應特性的值

起始點就是插值開始時對應特性的值,結束點表示指定 <atl_property> 的終值。中間的節點(knot)用於控制樣條(spline)。

二階 貝茲曲線 只使用1個控制節點(knot),三階貝茲曲線使用2個控制節點。 貝茲曲線中間的knot是純粹的控制節點,通常不在曲線路徑上。 Catmull-Rom樣條使用3個或更多控制節點,只有首尾兩個knot是控制節點(通常不在曲線路徑上),其他knot則都在曲線路徑上。

transform spline_motion_single_property:
    # 右下角略微放大一點。線性變換。
    zoom 0.5 xalign 1.0 yalign 1.0

    # 逐漸移動到底部中央,略微超過一點再彈回來。使用二階貝茲曲線。
    linear 2.0 xalign 0.5 knot 0.0

    # 移動到頂部,在緩慢回到中心。使用三階貝茲曲線。
    linear 2.0 yalign 0.0 knot 0.2 knot 0.8

    # 移動到左端,往復擺動。使用Catmull-Rom樣條。
    linear 2.0 xalign 0.0 knot 1.0 knot 0.5 knot 0.0

transform spline_motion_multi_property:
    # 右下角略微放大一點。線性變換。
    zoom 0.5 align (1.0, 0.0)

    # 使用樣條運動,讓坐標(x, y)沿輕微的S形軌跡同時移動。
    linear 2.0 align (0.5, 1.0) knot (0.0, .33) knot (1.0, .66)

使用圓周運動:

<atl_property> clockwise
<atl_property> counterclockwise
<atl_property> circles <number_of_circles>

名稱

類型

描述

number_of_circles

int (expr)

圓周運動的圈數(一圈等於360度)

Ren’Py處理圓周運動時,首先比較起點與終點位置(通常使用 pos、align、angle 和 radius 設置), 然後找到極坐標原點(通常使用 around 設置)。接著計算指定方向需要旋轉的角度值,單位為度。 如果出現了“circle”從句,Ren’Py則會加上對應數量的整圈。

show logo base:
    xalign 1.0 yalign 0.0

    # 設置旋轉中心。
    anchor (0.5, 0.5)

    # 使用圓周運動將logo螺旋轉到螢幕頂部。耗時2秒。
    linear 2.0 yalign 0.0 clockwise circles 3

使用transform表達式:

<transform_expression>

名稱

類型

描述

transform_expression

Transform (expr)

待插值的變換

如果插值目標是一個表達式,則該表達式應是一個ATL變換且只含有單一特性。 計算時,變換中的單一特性會與直接將該特性寫在插值語句中的效果一樣。

show logo base:
    xalign 1.0 yalign 0.0

    # 耗時1秒,將logo從當前坐標移動到畫面中心。
    ease 1.0 truecenter

pass語句

pass 語句不會觸發任何效果:一種 no-op 。

語法

pass

pass語句可以用於分隔其他語句。比如出現兩套choice語句的時候(後面會提到),如果不用pass語句,選項會混在一起。 pass語句還可以用在一些語法層面需要出現語句塊,但創作者只想要空著的地方,比如某些選項語句後面必須寫點什麼。

(譯者註:pass就是腳本中的占位符。空著不寫會報錯,寫個pass就能運行了。)

repeat語句

repeat 語句會跳轉到包含repeat的語句塊的開頭,並重新開始執行。

語法

基本格式:

repeat

使用count參數:

repeat <count>

使用方法

名稱

類型

描述

count

int (expr)

(可選參數)語句塊重複執行次數

以 repeat 2 結尾的語句塊至多執行2次,以 repeat 1 結尾則不會重複執行。

repeat語句必須是一段語句塊的最後一條語句。

樣例

show logo base:
    xalign 0.0
    linear 1.0 xalign 1.0
    linear 1.0 xalign 0.0
    repeat

block語句

block 語句可以將一些語句組織為一個ATL語句塊。用於對需要重複運行的語句分組。

語法

block:
    <atl_block>

樣例

show logo base:
    alpha 0.0 xalign 0.0 yalign 0.0
    linear 1.0 alpha 1.0

    block:
        linear 1.0 xalign 1.0
        linear 1.0 xalign 0.0
        repeat

parallel語句

parallel 語句用於定義一個可以並行執行的ATL語句塊的集合。

語法

parallel:
    <atl_block>

用法

名稱

類型

描述

“parallel”

keyword

一個或更多並行語句塊

atl_block

block

該並行分支內的ATL語句塊

使用多個並行語句塊時,所有語句塊將同時執行。所有並行語句塊都運行結束後,parallel語句才算運行結束。

語句塊中的所有並行語句都應各自獨立,並修改不同的 變換特性。例如,一個語句塊控制水平方向的移動(xalign),另一個語句塊控制垂直方向的移動(yalign)。當兩個並行分支修改了同一項特性(property),會產生無法預料的結果。

parallel語句會盡可能多得將同一個語句塊中的並行語句塊加入到同一個並行集合中。

樣例

show logo base:
    parallel:
        xalign 0.0
        linear 1.3 xalign 1.0
        linear 1.3 xalign 0.0
        repeat
    parallel:
        yalign 0.0
        linear 1.6 yalign 1.0
        linear 1.6 yalign 0.0
        repeat

choice語句

語句定義了一個所有可能選項的集合。Ren’Py會挑選其中一個選項,執行對應選項相關的ATL語句塊(block),之後跳轉到choice語句塊結束處。

語法

基礎格式:

choice:
    <atl_block>

選項帶權重:

choice <weight>:
    <atl_block>

使用方法

名稱

類型

描述

“choice”

keyword

一個或多個選項

weight

float (expr)

(可選)選項權重,預設值1.0.

atl_block

block

選項對應的ATL語句塊

出現多個choice語句時,會盡可能多得將同一個語句塊中的choice語句加入到同一個選項集合中。 如果使用 simple_expression 指定選項權重,該表達式結果必須是浮點數值,否則會變成預設值1.0。

pass 語句可以用於按順序將幾個選項語句塊分割為幾個choice語句,或產生一個空的選項語句塊。

Example

image eileen random:
    choice:
        "eileen happy"
    choice:
        "eileen vhappy"
    choice 2.0:
        # 更高機率被選用。
        "eileen concerned"

    pause 1.0
    repeat

animation語句

使用 animation 語句時,必須將其放在整個ATL語句塊的開頭,告訴Ren’Py該語句塊要使用動畫時間軸(at)而不是顯示時間軸(st)。詳見 時間軸

語法

animation

使用方法

帶有相同標籤(tag)的圖像或界面開始顯示的那一刻,animation時間軸就將進行計時並被所有相同標籤(tag)的圖像和界面共享。 animation時間軸常用於動畫過程中的圖像替換。

樣例

image eileen happy moving:
    animation
    "eileen happy"
    xalign 0.0
    linear 5.0 xalign 1.0
    repeat

image eileen vhappy moving:
    animation
    "eileen vhappy"
    xalign 0.0
    linear 5.0 xalign 1.0
    repeat

label start:
    show eileen happy moving
    pause
    show eileen vhappy moving
    pause

這個例子中,艾琳的立繪表情將在第一個 pause 語句處改變,但她的位置不會改變。因為兩個動畫使用相同的animation時間軸,避免了更換立繪後出現圖像位置不連續。不使用 animation 語句的話,用戶通過點擊滑鼠或螢幕後,角色的立繪位置將發生一次重設。

on語句

on 語句會定義一個事件處理器(handler)。

語法

單一事件:

on <event_name>:
    <atl_block>

多個事件:

on <event_name>, <event_name>, ...:
    <atl_block>

使用方法

名稱

類型

描述

event_name

word

一個或多個 事件 名。

atl_block

block

獲得事件後執行的ATL代碼塊。

on 語句會將語句塊(block)中連續出現的多個on項都放入一個事件集之中。on語句可以只處理某一個事件名,或者使用逗號分隔的事件名列表。

on語句用於處理各種事件(event)。當某個事件被處理後,其他的事件處理就會停止,並且會立即進入新事件的處理流程。當某個事件處理器沒有新的待處理事件,就會產生 default 事件(已經處理 default 事件的情況除外)。

on語句的執行不會自然終止。(但是其可以被time語句,或者關聯的事件處理器終止。)

樣例

show logo base:
    on show:
        alpha 0.0
        linear .5 alpha 1.0
    on hide:
        linear .5 alpha 0.0

transform pulse_button:
    on hover, idle:
        linear .25 zoom 1.25
        linear .25 zoom 1.0

可視組件語句

執行可視組件語句會設置或替換某個變換的 displayable 型子組件。

語法

基本格式:

<displayable>

帶轉場:

<displayable> with <transition>

使用方法

名稱

類型

描述

displayable

Displayable (expr)

需要顯示的子組件:圖像或可視元素。

transition

Transition (expr)

(可選)轉場(例如, dissolve,fade)。

Note

需要注意的是,並非所有轉場都能在此處正常使用。特別是 字典轉場(Dict Transitions) 、 move- 和 ease- 類轉場都不能在這裡使用。

將變換用作可視組件: 如果使用需要顯示的元素是ATL變換且變換中使用可視組件作為子組件,那當前ATL語句塊會暫停執行並等待ATL變換中的動畫跑完,再繼續執行。

Warning

如果要顯示的元素是一個不帶子組件的變換,顯示為透明內容,最終將看不到任何東西。 傳入無子組件的ATL變換可能會被當作 變換表達式語句,產生與預期不同的效果。

對初學者的建議: 總是讓可視組件中有點東西能被看到,比如圖片文件("logo.png")或有實際內容的可視組件。

樣例

image atl example:

    "logo_base.png"

    pause 1.0

    "logo_bw.png" with Dissolve(0.5, alpha=True)

變換表達式語句

變換表達式語句可以包含另一個ATL變換,並用作自身ATL語句塊的一部分。

語法

<transform_expression>

使用方法

名稱

類型

描述

transform_expression

Transform (expr)

插入的變換

該語句只有在ATL變換自身 沒有 子組件時才有效。否則,同樣的語句會被當作 可視組件語句 處理。變換表達式語句中的內容會替換變換名,並執行對應的變換。

樣例

transform move_right:
    linear 1.0 xalign 1.0

image atl example:
    # 顯示logo_base.png。
    "logo_base.png"

    # 運行move_right變換。
    move_right

單行contains語句

該語句會把當前ATL變換的某個子組件設置(或替換)成表達式計算結果,用作動畫。

語法

contains <displayable>

使用方法

名稱

類型

描述

displayable

Displayable, Transform (expr)

用作子組件的可視組件或變換

可視組件語句 不夠直觀,且容易與變換表達式語句混淆,但它允許使用 transition 替換子組件。當某個ATL變換希望將另一個ATL變換用作自身顯示內容的一部分(而不是完全替換所有顯示內容)時,該語句尤其有用。

Note

想要ATL變換將另一個ATL變換作為其子組件時,請使用此語句。當子項需要作為獨立的變換對象,而不是直接引用代碼時,這一點尤其有用。

否則,:ref:displayable-atl-statement 是更簡單的設置子顯示對象的方式,其優勢在於可指定播放 轉場 將舊子對象替換為新子對象時。

樣例

transform an_animation:
    "1.png"
    pause 2
    "2.png"
    pause 2
    repeat

image move_an_animation:
    contains an_animation

    # 如果不使用contains語句,就無法跳出循環並執行後續代碼。
    xalign 0.0
    linear 1.0 yalign 1.0

與變換表達式語句相比,可視組件語句 定義更明晰,但其可以使用 transition 來替換子組件。 contains語句適合用在某個ATL語句塊中容納另一個變換效果,而不是單純復用某個變換的代碼塊。

contains語句塊

contains語句塊,類似於 單行contains語句,可以設置變換的子組件,但方式不同。

語法

contains:
    <atl_block>

使用方法

一個或多個contains語句塊會被盡可能多得組成單個contains語句,並放在一個 Fixed() 組件中,設置為該變換的子組件。

每個語句塊都必須定義一個可用的可視組件,否則會報錯。 所有contains語句會立刻並行執行,並不會等待所有子組件內的代碼都執行完畢才執行下一條contains。

樣例

image test double:
    contains:
        "logo.png"
        xalign 0.0
        linear 1.0 xalign 1.0
        repeat

    contains:
        "logo.png"
        xalign 1.0
        linear 1.0 xalign 0.0
        repeat

function語句

function 語句允許ATL使用Python代碼。

語法

function <func>

使用方法

名稱

類型

描述

func

function (expr)

調用的函數,簽名為 (trans: Transform, st: float, at: float) -> float | None

這些函數與 Transform() 具有相同的入參和返回結果:

  • 第一個入參是一個transform對象。可以設置該對象的 變換特性。

  • 第二個入參是顯示 時間軸,表示函數開始執行到現在經過的秒數。

  • 第三個入參是動畫 時間軸,表示具有相同標籤(tag)的對象在整個界面上已存在的秒數。

  • 如果函數返回一個數值,其會在數值對應的時間(秒)後再次被調用。(0秒表示盡可能快地調用該函數。)如果函數返回None,主控流程會跳到下一個ATL語句。

除了修改第一個入參中的Transform對象之外,該函數不應產生副作用。 並可以在任意時間傳入任意值並調用,能配合預載入功能。

注意,function 不是一個變換特性,並且其跟 Transform() 的 function 參數也不完全一致。

樣例

init python:
    def slide_vibrate(trans, st, at, /):
        if st > 1.0:
            trans.xalign = 1.0
            trans.yoffset = 0
            return None
        else:
            trans.xalign = st
            trans.yoffset = random.randrange(-10, 11)
            return 0

label start:
    show logo base:
        function slide_vibrate
        pause 1.0
        repeat

time語句

time 語句是一種控制語句。

語法

time <value>

使用方法

名稱

類型

描述

value

float/int (expr)

開始執行這段代碼塊的時間點,單位為秒。

當time語句中給定的“time”結束後,後面的語句才會開始執行。在上一個語句還在執行的情況下,這種控制轉換依然會執行,也能強行終止任意優先度的語句。

表示如果主控流程提前執行到time語句處,它就會暫停並等到time語句獲取流程控制權。

當一個語句塊中存在多個time語句時,它們各自的結束時間點必須按順序嚴格遞增。

樣例

image backgrounds:
    "bg band"
    xoffset 0
    block:
        linear 1 xoffset 10
        linear 1 xoffset 0
        repeat # control would never exit this block

    time 2.0
    xoffset 0
    "bg whitehouse"

    time 4.0
    "bg washington"

event語句

event 語句會使用給定的名稱產生一個事件(event)。

語法

event <event_name>

使用方法

名稱

類型

描述

event_name

word

待生成的事件名

當在某個語句塊(block)運行過程中出現某個事件(event)時,語句塊會檢查自身是否存在對應事件名的處理器(handler)。如果處理器存在,主控流程會切換到對應的事件處理器。否則,事件會廣播至所有事件處理器。

外部事件

下列事件會在ATL變換中自動觸發:

start

一種偽事件,進入 on 語句時觸發,前提是沒有更高優先度的事件出現。

show

使用 show 或者 scene 語句顯示transform,並且給定標籤(tag)沒有對應已顯示的圖像時觸發。

replace

使用 show 語句中的transform根據給定標籤(tag)替換某個圖像時觸發。

hide

使用 hide 語句或等效的python語句中的transform時觸發。

需要注意的是,transform被 scene語句 清除,或者退出其所在的 上下文 時,hide事件是不會觸發的。

replaced

transform被另一個transform替換時觸發。原transform的圖像實際上並不會隱藏或移除,直到整個ATL語句塊(block)執行完。

hover、idle、selected_hover、selected_idle、insensitive、selected_insensitive

當包含此transform的按鈕或者被此transform包含的按鈕,出現對應的狀態名稱時觸發。

ATL的柯里化和部分入參傳遞

使用 transform語句 定義的ATL變換可以設置多種不同的入參列表。 如同調用函數一樣調用ATL變換時,返回結果依然是一個transform,入參則可以改變原transform中同名參數的值。

例如:

transform screamer(child, screamee, wait_time=2, flash_time=.1):
    child
    pause wait_time
    screamee
    pause flash_time
    child

# 這樣寫不會報錯(類似於引用Python函數返回結果)。
define shorter_screamer = screamer(wait_time=1)

define eileen_excited_screamer = screamer(screamee="eileen excited", flash_time=.2)

label start:
    show hhannahh happy at screamer(screamee="hhannahh surprised", wait_time=1.5)
    "這是一種方法。"

    show eileen vhappy at eileen_excited_screamer
    "這是另一種方法。"

    show patricia sad at eileen_excited_screamer(screamee="patricia wow")
    "並且你也可以這樣做。"

需要注意,變換 shorter_screamer 雖然源自 screamer,但不能直接像 show eileen at screamer 這樣直接用。 因為其 screamee 參數未賦值。

還要注意,類似腳本標籤(label)和界面(screen)定義,使用 transform語句 定義的transform的入參預設值, 是在transform 被調用 時才計算的,而不是 被定義 時就計算好的。

總之,transform只有在調用另一個變換(例如上例中的 shorter_screamer 或部分入參傳遞)時,才會計算所有入參的預設值。 無論預設值來自原始的transform(比如 shorter_screamer 的 flash_time 參數或部分入參傳遞的 wait_time 參數), 還是來自更早執行的腳本中的調用(比如 shorter_screamer` 中的 wait_time 參數或部分入參傳遞的 screamee 和`flash_time` 參數)。

特殊child參數

如果某個ATL變換有一個入參名為“child”,並且該入參獲得了一個值,那麼將 無視該入參值的類型和賦值方式 , 該變換的子組件將被設置為child參數的值。 (無視入參值類型和賦值方式是指,不需要考慮參數是固定位置入參是還是關鍵字入參,也不需要考慮該參數有預設值還是要求必須重新賦值。)

需要注意,child入參的預設值不會生效,還是需要從外部傳入一個新的值。

另外,ATL變換用作一個transform時,默認不會將 child= 作為關鍵字參數傳遞並設置目標的child,除非目標有個同名的child入參。

例如,下面的腳本能在child與另一個可視組件之間來回切換:

transform lucy_jump_scare(child):
    # child的值會隱式設置為transform的子組件。
    pause 5

    # “jump scare”式驚嚇。
    "lucy mad"
    pause .2

    # 再顯示原來的子組件。
    child

還可以在 contains 語句塊中放置原來的子組件:

transform marquee(width, height=1.0, duration=2.0, child=None):
    xcenter 0.5
    ycenter 0.5

    crop (0, 0, 0.5, 500)

    contains:
        child
        xanchor 0.0 xpos 1.0
        linear duration xanchor 1.0 xpos 0.0

old_widget 和 new_widget 兩個“關鍵字限定”入參(即不能用於固定位置入參)在 ATL轉場 中有特殊用法。

warpers

warper是一類函數,其可以改變插值語句中用到的時間值。他們將時間t轉換為t’,t和t’都是浮點數,t會將給定的時間值歸一化為0.0到1.0。 (如果該語句給定的原時長是0,那運行時t就是1.0。) t’的初始取值範圍也是0.0到1.0,不過可以超出這個範圍。 以下warper都是默認定義好的。

pause

暫停,然後跳變成新值。如果 t == 1.0,則 t' = 1.0;否則 t' = 0.0。

linear

線性插值。t' = t

ease

開頭慢,中間加速,之後又減速。t' = .5 - math.cos(math.pi * t) / 2.0

easein

開頭快,然後減速。t' = math.cos((1.0 - t) * math.pi / 2.0

easeout

開頭慢,然後加速。t' = 1.0 - math.cos(t * math.pi / 2.0)

除此之外,Robert Penner的easing函數都是支持的。為了避免與上面的幾個函數名重複,有些函數名字修改過。這些標準函數的圖像可以在這個網站上查看 http://www.easings.net/

Ren’Py 函數名

easings.net 函數名

ease_back

easeInOut_back

ease_bounce

easeInOut_bounce

ease_circ

easeInOut_circ

ease_cubic

easeInOut_cubic

ease_elastic

easeInOut_elastic

ease_expo

easeInOut_expo

ease_quad

easeInOut_quad

ease_quart

easeInOut_quart

ease_quint

easeInOut_quint

easein_back

easeOut_back

easein_bounce

easeOut_bounce

easein_circ

easeOut_circ

easein_cubic

easeOut_cubic

easein_elastic

easeOut_elastic

easein_expo

easeOut_expo

easein_quad

easeOut_quad

easein_quart

easeOut_quart

easein_quint

easeOut_quint

easeout_back

easeIn_back

easeout_bounce

easeIn_bounce

easeout_circ

easeIn_circ

easeout_cubic

easeIn_cubic

easeout_elastic

easeIn_elastic

easeout_expo

easeIn_expo

easeout_quad

easeIn_quad

easeout_quart

easeIn_quart

easeout_quint

easeIn_quint

可以通過只讀模組 _warper 訪問這些warper效果。該模組包含了上述所有函數。 在Ren’Py內建效果中使用時間warp函數很有用,比如可以這樣用:

with Dissolve(1, time_warp=_warper.easein_quad)

我們可以在一個 python early 語句塊中,使用 renpy.atl_warper 裝飾器定義新的warper函數。定義warper函數文件需要在使用那個函數的其他任何文件之前被處理。定義的代碼如下:

python early hide:

    @renpy.atl_warper
    def linear(t):
        return t

替換變換

某個ATL變換、內建變換或使用 Transform 定義的變換對象被同類變換替換時, 同名特性的值會從前一個變換繼承到新的變換。不同類型的變換無法繼承。

如果 show語句 中的at關鍵字後列出了多個變換待替換,則新變換列表從後往前依次替換,直到新替換變換列表全部換完。例如:

show eileen happy at a, b, c
"我們稍等一下。"
show eileen happy at d, e

e 變換替換了 c, d 變換替換了 b,而沒有變換會替換 a。

替換時,舊變換的特性值由新變換繼承。如果舊變換正處於動畫中,則新變換繼承的可能是中間的某個值。例如:

transform bounce:
    linear 3.0 xalign 1.0
    linear 3.0 xalign 0.0
    repeat

transform headright:
    linear 15 xalign 1.0

label example:
    show eileen happy at bounce
    pause
    show eileen happy at headright
    pause

這個例子中,圖像會左右彈跳,直到用戶點擊滑鼠。 當用戶點擊滑鼠後, bounce 中的 xalign 特性值將被 headright 繼承。 精靈在x軸方向坐標移動的初始值,即是用戶點擊滑鼠時的值。

位置相關特性(包括 xpos、ypos、xanchor 和 yanchor,以及等效的:tpref:xalign、radius 和 angle))繼承時有一項特殊規則: 子組件設置的值會覆蓋父組件的值。這樣設計是考慮到可視組件往往只有一項位置資訊,需要優先保證設置的值不受影響。 對位置特性的設置有多種方式,例如,xalign 會同時設置xpos和xanchor。

最後,如果某個 show 語句不包含 at 從句,則不需要搞特性值繼承問題。若要重設所有變換特性,可以先隱藏再顯示對應的可視組件。 若要中斷動畫效果,可以這樣:

show eileen happy at some_animation
"Wow, so this is what antigravity feels like !"

show eileen:
    pass
"But I'm happy when it settles down."

時間軸

Ren’Py中有兩個時間軸,很容易混淆:

  • st (顯示時間軸):可視組件第一次顯示在界面上就開始計時。

  • at (animation timebase): 具有相同tag的圖像顯示後開始計時,不算圖像隱藏的時間。

可視組件不帶任何tag顯示時,st 和 at 的值是一樣的。

Note

默認情況下,變換使用 st。 可以使用 animation語句 切換為 at。

Transform類

ATL變換在Python中等效於一個Transform對象。

class Transform(child=None, *, function=None, reset=False, **properties)

創建一個Transform對象,並將各種操作應用到其子組件,操作包括:剪裁、旋轉、縮放和alpha混合等。 一個Transform對象的欄位一一對應 變換特性 ,並都將應用到子組件。

child

應用變換的子組件。

reset

若為True,顯示時會重設所有變化特性為預設值,而不是繼承其替代的那個變換。

function(trans: Transform, st: float, at: float, /) → int | None

若不是None,這是渲染變換效果時調用的函數。調用這個函數時使用3個固定位置入參:

  • Transform對象。

  • 顯示時間軸,單位為秒。

  • 動畫時間軸,單位為秒。

函數會返回一個延遲時間,單位為秒。在運行延遲時間之後這個函數會被再次調用。如果延遲時間是None,則會在下次互動之後立刻調用。

該函數除了修改第一個入參的變換對象之外不應有其他副作用,並且要求可以在任何時間點使用任何值調用以配合預載入。

其他關鍵字入參都會作為對應變換特性的值。 繪製變換效果時,對應的變換特性都會根據入參設置值,但在變換對象創建後不再更改。 使用 function 參數傳入的函數或調用 update() 方法,可以改變對應的變換特性。

其他參數被視為設置變換特性的值。

hide_request

當function函數被調用時,這項會被設置為True,標識變換效果被隱藏。

hide_response

如果hide_request為True,這項會被設置為False,防止變換效果被隱藏。

original_child

創建變換對象時就設置的子可視組件,早於調用set_child。 如果創建時沒有子組件,可以設置為None.

set_child(child)

使用一個新的 child 調用這個方法,child 成為變換的子組件。

update()

當變換特性(property)欄位在 function 參數指定的回調方法之外被更新時,這個方法會被調用,確保修改生效。

unique():

新創建的transform對象可以調用該方法將自身標記為唯一。通常transform對象被添加到某個可視組件時會複製自身,並重設自身狀態。調用該方法後可以避免出現這種情況。還可以在需要創建的transform對象用在多處而不發生改變,或從外部獲取 function 參數的情況。

該方法返回結果是transform對象自身。

在Python中對可視組件應用變換

若要在Python中對可視組件 d 引用變換 t 有好幾種方法:

  1. 最為通用也最推薦的方法是,使用 At(d, t) (下面有樣例)。這種方法適用於所有變換。

  2. d(child=t) 適用於所有 ATL變換。

  3. t(d) 適用於 Python變換,以及不需要坐標作為參數的ATL變換。

At(d, *args)

對指定的源可視組件 d ,將 args 中所有變換應用於該組件。變換的應用順序是從左到右,所以最外層的變換效果是最右邊的入參。

transform birds_transform:
    xpos -200
    linear 10 xpos 800
    pause 20
    repeat

image birds = At("birds.png", birds_transform)

Note

如果某些變換沒有傳入需要的參數,變換結果可能會導致無法正常顯示。 這種情況下需要檢查使用 transform語句 定義的變換到底需要什麼參數。

Note

變換結果可能還是一個變換,可以進一步應用於另一個可視組件(及其子組件); 這種情況下ATL變換依然可以如其他變換一樣使用,不影響其子組件。

可調用對象用作變換

最後,Python中的可調用對象可以用作變換。這些可調用對象必須能使用 可視組件 作為入參, 並且能返回一個新的可視組件。例如:

init python:

    # 這是一個使用right和left兩個默認變換的自訂變換。
    def right_or_left(d):
        if switch:
            return At(d, right)
        else:
            return At(d, left)

某些內建對象可以也符合入參為可視組件並返回可視組件的要求,例如 Flatten(),也可以直接用作變換。