NVL 模式
可以一次展示多条对话和旁白,看上去很适合拿来改一个聊天窗口出来,也的确有很多人是这样做的。主要工作就是修改 screen nvl, 自行完成布局。不过,我的版本,应该更优雅一些。
为角色自动配置头像
Ren’Py 默认的 ADV 模式有头像 (Side Image) 这个特性,只需要给 Character 传一个 image 参数,就会自动匹配头像文件,那么 NVL 模式可以这样用吗?
嘛,结论是——并不可以。如果一个 Character 的 kind 是 nvl, 同时传入 image 参数,你会得到一些非常怪异的表现。屏幕左下角固定会展示一个头像,这个大概和 say 有关,这个倒是很好解决。
然后,你肯定要想办法为每一条历史消息获得对应的头像,但是历史消息的类型是 NVL Entry
, 确切来说是 _NVLEntry. 其中没有 image_tag, 总不能用角色的名字去获取头像(虽然维护一个 dict 也是一个方案)吧?而且,renpy.get_side_image 的表现也很怪异。
关于 get_side_image 的表现
本段内容与正文无关,可以跳过。
renpy.get_side_image
的表现很怪,它和 SideImage 一样,看上去都是获取「当前」的头像。
要这样调用 img = renpy.get_side_image("side") 获取「当前」的角色的头像。
试图传递 renpy.get_side_image("side", "alice") 不一定能获得角色的头像,只有当前的角色有过不是默认的表情,之后,才能通过这东西获得默认的头像。
然后再通过 ImageReference(img) 变成 displayable.
……
总的来说,renpy.get_side_image 看上去并不是一个应该暴露给用户的方法。
使用 who_args 传递图像标签
所以目前的问题是,从历史对话中,获得角色对应的图像标签, 再通过图像标签去查找头像文件。
根据 NVL
, NVL Entry 中的 who 只是个字符串。NVL Entry 可以用来传递信息的参数,只有 who_args, what_args, window_args, 甚至不像 DialogueHistory
那样有 show_args
.
至少,NVL Entry 会保留 who_args. 给角色 (who) 改名字的文字颜色和字号,和给角色添加个头像看上去没有什么区别——除了这个 avatar 不是 text 自带的属性。不过无所谓啦,并不会影响 text 的正常工作。于是:
define alice = Character("爱丽丝", avatar="alice")
然后可以在 screen 中,取得对应的值:
$ avatar_tag = d.who_args.get("avatar") or "default"
使用 get_registered_image 获取图像
接下来是获取图像文件,有一个很有用的函数:renpy.get_registered_image . 你可以方便的使用自定义的前缀比如 avatar (当然也可以使用 side), 然后使用角色的 avatar tag 去获取头像,这样管理起来比较方便。
renpy.get_registered_image("avatar alice")
顺便一提,根据 Ren’Py 的源代码
,传入的 name 可以是字符串或者 tuple. 所以 renpy.get_registered_image("avatar alice") 和 renpy.get_registered_image(("avatar", "alice)) 都可以工作。
还有一件事
禁用默认的 screen 样式
对于 text d.what id d.what_id 之类的界面,Ren’Py 会通过 id 添加一些默认样式,但是这个 id 又不能不带。比起手动逐个覆盖自带的样式,一个方案是,设置 prefer_screen_to_id
为 True, 然后自行指定 style.
弹性布局

如果也想要像这样,在下方展示菜单,但是选项数量与高度不确定;上半部分展示聊天记录,并且可以滚动。可以使用 vbox 但是调转方向 ,把高度不确定的菜单写在前面,负责滚动的 viewport 写在后面,并设置 yfill 为 True.
为什么只有六条对话
define config.nvl_list_length = None
# game/screens.rpy
## This controls the maximum number of NVL-mode entries that can be displayed at
## once.
define config.nvl_list_length = gui.nvl_list_length
# game/gui.rpy
## The maximum number of NVL-mode entries Ren'Py will display. When more entries
## than this are to be show, the oldest entry will be removed.
define gui.nvl_list_length = 6
支持多种 NVL 模式
NathanGuilhot/Renpy-simple-messaging-system-for-mobile-game 的方案很不错,增加一个全局变量,指定要用哪个 nvl, 然后在 screen nvl 中进行判断。