进阶GUI与自定义
本页属于 GenPy Ren'Py 学习路线。教程内容面向 Ren'Py 8.x,并在页面末尾连接到 GenPy 的对应工作流。
学习目标
- 了解“进阶GUI与自定义”在 Ren'Py 项目中的用途。
- 能在一个最小项目里验证本章相关语法或工作流。
- 知道发布前需要检查的常见风险,并能在 GenPy 中继续维护。
核心语法
Displayablerenpy.register_statementcustom text tagscallbacksCDD
可运行示例
text
init python:
def buy(item):
store.money -= item["price"]
store.inventory.append(item["name"])
screen shop():
vbox:
for it in shop_items:
textbutton "[it[name]] - [it[price]]金" action Function(buy, it)教程正文
当内置能力不够用时,Ren'Py 允许你用 Python 扩展:自定义可显示物、自定义语句、自定义文本标签、 各类回调。这是做复杂玩法(小游戏、特效、独特 UI)的关键。
1. 屏幕与 Python 协作
- 屏幕语言里可调用任意 Python 函数(
action Function(fn)、SetVariable等)。 - 复杂数据准备放在 Python 函数里,屏幕只负责展示,保证刷新性能。
text
init python:
def buy(item):
store.money -= item["price"]
store.inventory.append(item["name"])
screen shop():
vbox:
for it in shop_items:
textbutton "[it[name]] - [it[price]]金" action Function(buy, it)2. 自定义可显示物(Creator-Defined Displayable, CDD)
继承 renpy.Displayable,自己实现 render()(绘制)与可选的 event()(交互)。 适合做粒子、迷你游戏、自绘控件。
text
init python:
class Spinner(renpy.Displayable):
def __init__(self, child, **kwargs):
super(Spinner, self).__init__(**kwargs)
self.child = renpy.displayable(child)
self.angle = 0
def render(self, width, height, st, at):
# st: 自显示以来的时间;用它驱动动画
self.angle = (st * 90) % 360
child_render = renpy.render(self.child, width, height, st, at)
rv = renpy.Render(width, height)
# ... 旋转绘制 child_render ...
renpy.redraw(self, 0) # 请求下一帧,形成动画
return rv
image spinning_logo = Spinner("logo.png")要点:
render(w, h, st, at)返回一个renpy.Render;st是“显示时长”,用于动画。renpy.redraw(self, delay)让引擎在 delay 秒后重绘(驱动动画)。- 需要响应点击/拖拽时实现
event(ev, x, y, st)。
3. 自定义语句(Creator-Defined Statement, CDS)
用 renpy.register_statement 注册新脚本语句,让脚本更易读(如 nvl_clear、smartshow)。
text
python early:
def parse_flash(lexer):
color = lexer.string()
lexer.expect_eol()
return {"color": color}
def execute_flash(o):
renpy.show("_flash", what=Solid(o["color"]))
renpy.with_statement(Dissolve(0.1))
renpy.hide("_flash")
renpy.register_statement(
"flash",
parse=parse_flash,
execute=execute_flash,
)之后脚本里可写:
text
label start:
flash "#fff" # 自定义语句:闪白8.5:
register_statement的init_priority现可传一个返回优先级的函数。
4. 自定义文本标签(Custom Text Tags)
注册 {xxx} 文本标签实现特效或语义化(见第 10 章):
text
init python:
def emphasis_tag(tag, argument, contents):
rv = [(renpy.TEXT_TAG, "b")]
rv.extend(contents)
rv.append((renpy.TEXT_TAG, "/b"))
return rv
config.custom_text_tags["em"] = emphasis_tag使用:e "这是{em}重点{/em}。"
也可用 config.self_closing_custom_text_tags 注册自闭合标签(如 {ruby} 注音)。
5. 角色回调(Character Callback)
在角色说话的各阶段插入逻辑(播配音、特效、记录历史):
text
init python:
def e_callback(event, interact=True, **kwargs):
if event == "begin":
renpy.play("audio/voice_blip.ogg")
elif event == "show":
pass
elif event == "end":
pass
define e = Character("艾琳", callback=e_callback)event 取值:begin、show、show_done、slow_done、end 等。
6. 其它常用回调/钩子
| 钩子 | 时机 |
|---|---|
config.start_callbacks | 游戏开始 |
config.after_load_callbacks | 读档后 |
config.before_load_callbacks(8.5 新增 before_load label) | 读档前(可换显示/音效) |
config.context_callbacks(8.5 新增) | 进入新上下文时(可多个) |
config.interact_callbacks | 每次交互 |
config.python_callbacks | 每条 Python 语句后 |
7. _ren.py 文件(在纯 Python 里写 Ren'Py)
xxx_ren.py 文件让你用标准 Python 语法编写、被 Ren'Py 当作脚本加载,便于用 IDE 类型检查:
python
"""renpy
init python:
"""
def my_helper(x):
return x * 2常见坑
- CDD 的
render要返回renpy.Render,动画靠renpy.redraw持续请求重绘。 - CDS 的
parse在python early:注册,保证早于脚本解析。 - 自定义文本标签返回的是“文本片段列表”,格式要对。
- 回调里别做重 IO/阻塞操作,会卡帧。
官方参考
- 屏幕与 Python:https://www.renpy.org/doc/html/screen_python.html
- 自定义可显示物:https://www.renpy.org/doc/html/cdd.html
- 自定义语句:https://www.renpy.org/doc/html/cds.html
- 自定义文本标签:https://www.renpy.org/doc/html/custom_text_tags.html
- 角色回调:https://www.renpy.org/doc/html/character_callbacks.html
在 GenPy 里怎么做
- 在 GenPy 的代码模式中维护相关 .rpy 文件,先保持语法清晰,再逐步加入本章功能。
- 用故事图谱、变量、校验或演出编辑器把“能运行”提升到“可维护”。
- 导出前结合 Ren'Py Lint 和 GenPy 校验结果,确认脚本、素材和发布路径一致。
推荐继续阅读:
