变换
变换(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
如果创建的变换中有一些参数没有默认值,那在使用该变换的每一处地方都需要指定参数的值。
See also: ATL的柯里化和部分入参传递 。
样例
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>
使用方法
样例
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) -> floatduration
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 。
语法
passpass语句可以用于分隔其他语句。比如出现两套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>
用法
样例
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 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时触发。replacedtransform被另一个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' = tease开头慢,中间加速,之后又减速。
t' = .5 - math.cos(math.pi * t) / 2.0easein开头快,然后减速。
t' = math.cos((1.0 - t) * math.pi / 2.0easeout开头慢,然后加速。
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 有好几种方法:
最为通用也最推荐的方法是,使用
At(d, t)(下面有样例)。这种方法适用于所有变换。d(child=t)适用于所有 ATL变换。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(),也可以直接用作变换。