可视组件是一类可以向用户显示的对象。Ren’Py可视组件具有多种用途。
当Ren’Py函数或者变量需要一个可视组件时,总共可用的东西有5种:
Image() 函数后被作为一个文件名处理。Color,也可能是一个(r, g, b, a)格式的元组,元组中每个元素的值都位于0到255的闭区间内。颜色会被传入 Solid() 函数。字符串中允许存在一个或多个用方括号包含的带替换内容,比如“eileen [mood]”和“eileen_[outfit]_[mood].png”这样形式的。一旦出现了类似的字符串,引擎就会创建出动态图像。动态图像在每次互动行为(比如say语句和菜单)开始阶段,具有 文本内插 的行为表现。最终生成的字符串会按照上文提到的规则处理。
When a string has “[prefix_]” in it, that substitution is replaced with each of the style prefixes associated with the current displayable.
如果某个字符串含有一个子字符串 “[prefix_”] ,就会使用当前可视组件关联样式的前缀替换该子字符串。
最常见的可视组件是通过加载硬盘上的一个文件并显示的图像(image)。由于图像是如此常用,所以每当某个上下文中某字符串给出了一个文件名,并需要将这个文件用作可视组件时,引擎就会自动创建一个图像(image)对象。唯一需要直接使用图像(image)对象的情况是,你想创建一个带样式特性的图像。
Image(filename, **properties) link从文件中加载一个图像。 filename 是文件名的字符串。
filename 应该是一个JPEG或PNG文件。
# 这两行等价。
image logo = "logo.png"
image logo = Image("logo.png")
# 使用Image()允许我们指定一个默认位置截取某个图像的一部分。
image logo right = Image("logo.png", xalign=1.0)
以下三种是推荐使用的图片文件格式:
没有动画的Gif文件和Bmp文件也是支持的,但已经不推荐用在本世代游戏中。
从硬盘加载文件,解码图像并将图像绘制到屏幕上,这一系列工作耗时比较长。因此加载过程需要几十甚至上百毫秒的话,就无法提供一个可接受的帧率,并会让用户觉得恼怒。
因为图像是一个固定尺寸,在大多数情况下都不会更改图像的可视区域,所以可以在图像真正使用之前提前加载,并放入内存的图片缓存中。图片解码并放入缓存之后,就可以很高效地绘制在屏幕上了。
Ren’Py会预测未来使用的图像,加载文件后先放入图像缓存备用。当图像缓存空间不足时,Ren’Py会先删除不会再被使用到的那些图像。
默认情况下,Ren’Py会预先缓存相当于8个界面大小的图像数据。(如果你的界面分辨率是800×600,那一个界面大小相当于一张800×600的图像,两张400×600的图像,以此类推。)这个值可以通过 :var:config.image_cache_size 配置项修改。
尽管精确的数值取决于规则细节,并且也存在一些明确的标准。一个最基础的规则是,图像缓存中的每一个像素,都占用4个字长的主内存和4个字长的显存。
我们将这些可视组件称作“类图像”,是因为他们占用界面中的一块矩形区域但不会对输入做任何反应。 有别于通常的图像,这些“类图像”可以调整尺寸填充某个区域(Frame、Tile、Solid),或者允许用户指定尺寸(Composite、Crop、Null)。这些“类图像”不是图像处理器(Image Manipulator)。
类图像可视组件使用 位置样式特性。
AlphaMask(child, mask, **properties) link可视组件使用入参 child 作为自身的颜色,其alpha通道值使用 child 的alpha通道值与 mask 的乘积。因此,该可视组件具有 child 同样的颜色,当 child 或 mask 之一是透明的情况下该组件也是透明,当 child 和 mask 都不透明的情况下该组件才不透明。
child 和 mask 可以是任意可视组件。AlphaMask的尺寸是 child 和 mask 的重叠区域尺寸。
需要注意,该函数与im.AlphaMask()使用不同的入参,im.AlphaMask()还使用入参mask的颜色通道。
Borders(left, top, right, bottom, pad_left=0, pad_top=0, pad_right=0, pad_bottom=0) linkborder对象提供边界(border)尺寸和码放(tile)给 Frame() 对象。其也可以提供填充( padding() )信息,用于带填充特性的窗口(window)或者框架(frame)。
填充(padding)信息是一个字段(field):
padding link这是一个4元素的元组,包含了矩形4条边的填充(padding)信息。
Composite(size, *args, **properties) link这个函数使用其他可视组件合成并创建一个新的可视组件。新可视组件的尺寸由 size 决定。 size 是一个(width, height)形式的元组,两个元素分别表示宽度和高度。
保留的固定位置参数用于放置LiveComposite中的图像。保留的固定位置参数应该是由两个数据构成的组。组中的第一个元素是一个(x, y)形式的元组;第二个元素是合成用的可视组件,使用前一个元素表示的位置进行合成。
可视组件的合成顺序为从后往前。
image eileen composite = Composite(
(300, 600),
(0, 0), "body.png",
(0, 0), "clothes.png",
(50, 50), "expression.png")
Crop(rect, child, **properties) link这个函数使用 rect 剪裁 child 并创建一个新的可视组件。 rect 是一个(x, y, width, height)形式的元组。
image eileen cropped = Crop((0, 0, 300, 300), "eileen happy")
DynamicImage(name) link动态图像是一种可视组件,这个组件包含文本内插(text interpolation)字符串。那些待内插的文本内容补完后就能生成一个新的可视组件对象。每一项互动行为开始后都会执行文本内插补完字符串。
Flatten(child, **properties) link该对象将可能由多个纹理组成的入参 child ,压成单个纹理。
某些操作,像alpha转换特性,会应用到最终构成可视组件的每一个纹理上。最终的可视组件会剔除错误结果,比如界面上的纹理有重叠。Flatten对象根据多个纹理创建单个纹理的时,能避免这些问题。
Flatten是一个性能消耗高昂的操作,应该在必要的情况下才使用。
Frame(image, left=0, top=0, right=None, bottom=None, tile=False, **properties) linkFrame是一个可视组件,可以调整图像尺寸使其匹配某个可用区域,同时也保存其边界(border)的宽度和高度。Frame通常用于窗口(window)或按钮(button)的背景。
使用框架(frame)将图像增大为原尺寸的两倍。
Border() 对象,这种情况下其他几个参数也都被这个Border对象一块代替。# 文本窗口过小时重新调整背景尺寸
init python:
style.window.background = Frame("frame.png", 10, 10)
Null(width=0, height=0, **properties) link在界面上创建一个空框(box)的可视组件。框的尺寸由 width 和 height 控制。这个对象用在某个可视组件需要一个子组件且找不到合适的子组件时,或者在box里充当空白。
image logo spaced = HBox("logo.png", Null(width=100), "logo.png")
Solid(color, **properties) link将声明的颜色 color 填满自身所有区域的可视组件。
image white = Solid("#fff")
Tile(child, style='tile', **properties) link将 child 以码放形式填充整个可视组件区域。
image bg tile = Tile("bg.png")
动态可视组件会基于游戏状态显示一个子组件。这些组件不使用任何特性,布局则由各子组件返回的特性所决定。
需要注意,动态可视组件总是显示它们的当前状态。因此,动态可视组件参与转场(transition)。(准确的说,转场过程中动态可视组件总是显示同样的东西。)
根据设计,动态可视组件用于从定义到离开界面都很少改变的要素,而不是用于经常变化的内容,比如角色表情。
ConditionSwitch(*args, predict_all=None, **properties) link基于Python条件表达式,改变自身显示内容的可视组件。固定位置入参应该是一组两个值的形式,每组分别包含:
第一条为True的条件表达式会显示自己的可视组件,所以需要保证至少一个条件表达式永远为True。
这里使用的条件表达式不应该有明显的副作用。
config.conditionswitch_predict_all() 的配置。image jill = ConditionSwitch(
"jill_beers > 4", "jill_drunk.png",
"True", "jill_sober.png")
DynamicDisplayable(function, *args, **kwargs) link基于某个Python函数可以改变自身子组件的可视组件,作用范围贯穿于某次互动行为。
使用入参调用的某个函数的名称:
并返回一个(d, redraw)元组。这个元组中:
每次互动后, function 函数都会被调用。
有一个特殊情况, function 可能是一个Python字符串并可以等效为一个可视组件。在那种情况下,每个互动行为中function都只能运行一次。
# 显示一个从5到0的倒计时,每十分之一秒更新直到计时结束。
init python:
def show_countdown(st, at):
if st > 5.0:
return Text("0.0"), None
else:
d = Text("{:.1f}".format(5.0 - st))
return d, 0.1
image countdown = DynamicDisplayable(show_countdown)
ShowingSwitch(*args, predict_all=None, **properties) link基于目前界面上正在显示图像,能更改自身显示内容的可视组件。固定位置入参应该是一组两个值的形式,每组分别包含:
默认图像需要提前指定。
config.conditionswitch_predict_all() 的配置。ShowingSwitch的一个用途是,根据角色感情更改角色边栏头像。例如:
define e = Character("Eileen",
show_side_image=ShowingSwitch(
"eileen happy", Image("eileen_happy_side.png", xalign=1.0, yalign=1.0),
"eileen vhappy", Image("eileen_vhappy_side.png", xalign=1.0, yalign=1.0),
None, Image("eileen_happy_default.png", xalign=1.0, yalign=1.0),
)
)
At函数使用某个可视组件和若干个 变换(transform) 产生一个新的可视组件。
At(d, *args) link对给定的源可视组件 d ,将 args 中所有变换(transform)都应用于该组件。所有变换(transform)参数的应用顺序是从左到右,所以最外层的变换(transform)效果是最右边的入参。
transform birds_transform:
xpos -200
linear 10 xpos 800
pause 20
repeat
image birds = At("birds.png", birds_transform)
布局框是在界面上设置其子组件布局的可视组件。其可以使用水平布局或者垂直布局,也可以使用标准位置算法设置布局。
框式可视组件可以使用任意数量的固定位置参数和关键词参数。固定位置参数会被以子组件的形式加入框体中。关键词参数则是应用于框体的各种样式特性。
框体使用 位置样式特性 和 方框(box)样式特性。
Fixed(*args, **properties) link充满整个界面的框体。该框体成员的布局顺序从后往前,使用自身的位置特性控制显示位置。
HBox(*args, **properties) link框体内成员布局顺序从左到右。
VBox(*args, **properties) link框体内成员布局顺序从上到下。
# 显示两个logo,分别位于左边和右边。
image logo hbox = HBox("logo.png", "logo.png")
# 显示两个logo, 一个在另一个上方。
image logo vbox = VBox("logo.png", "logo.png")
# 显示两个logo。
# 由于默认情况下,其他位置显示的图像与界面左上方显示的一致,
# 我们需要使用其他图片替换那些不需要logo的地方。
image logo fixed = Fixed(
Image("logo.png", xalign=0.0, yalign=0.0),
Image("logo.png", xalign=1.0, yalign=1.0))
坐标布局会在界面上建立一个坐标系,并显示其子组件。其使用
位置样式特性 和 spacing 样式特性。
Grid(*args, **properties) link在一个坐标系中布局可视组件。前两个固定位置参数分别对应坐标中的列号和行号。固定位置参数的 columns * rows 给定了坐标系中所能容纳的可视组件总数。
这些可视组件通常用于创建某种视觉特效。
AlphaBlend(control, old, new, alpha=False) link这种过渡(transition)效果用于从一个可视组件(大多数使用某种动画变化)过渡到另一个。当变换(transform)完全不透明时,新的可视组件会被启用;当变化完全透明时,旧的可视组件会被启用。
图像处理器 本身是一个可视组件。它会接受一个图像或者另一个图像处理器对象,对原有对象进行某些处理。图像处理器只接受图像或其他图像处理器作为输入。
任何能放可视组件的地方也可以放图像处理器,但反过来不一定可行。 Image() 对象是一种图像处理器,所以任何需要使用图像处理器的地方都可以使用image对象。
图像处理的应用具有重大意义。过去的一些图像处理器由于各种的问题不应再使用。
除了使用 im.Data() 的情况,可视组件 Transform() 提供了很多类似的功能,并同时修复了过去的问题,尽管使用这些需要启用gl2配置项。
图像处理器的详情请参见 图像处理器 。
占位组件(placeholder)用于正确显示背景图或者角色图像。在开发者模式下,使用某个未定义的图像时,占位组件会被自动使用。如果你觉得默认的显示有问题,也可以手动指定占位组件的使用。
# 默认情况下,会使用girl占位组件。
image sue = Placeholder("boy")
label start:
show sue angry
"苏" "你还好吗?现在,受死吧!"
Placeholder(base=None, full=False, flip=None, **properties) link该可视组件可以用于显示一个占位角色或背景。
显示图像的类型。应该是以下类型之一:
尝试自动确认图像用途。如果图像名以“bg”、“cg”或者“event”开头,则取值’bg’。
否则,引擎会连接一个web服务器根据角色名字猜测性别并应用。(web服务器也无法判断的情况下,默认为’girl’占位组件。)
可视组件可以使制作者定义他们自己的可视组件,并且涉及到所有Ren’Py可以用到可视组件的地方。
一个带前缀的可视组件名是一个带有英文冒号的字符串。前缀在冒号左边,参数在冒号右边。
config.displayable_prefix 变量将前缀对应到一个函数。函数接受此参数,并返回一个可视组件或None。
比如说,这个例子创建一个big前缀,返回一个原来两倍大的图像。
init -10 python:
def embiggen(s):
return Transform(s, zoom=2)
config.displayable_prefix["big"] = embiggen
init -10 确保前缀在任何图像使用它之前被定义。
然后前缀可以用来定义图像:
image eileen big = "big:eileen happy"
或者其他需要显示可视组件的地方。