NarraLeaf

从 Ren'Py 迁移

Ren'Py 的标签、跳转与屏幕,对应到 NarraLeaf 的 Scene、Character 与 Menu 等概念

NarraLeaf 使用 TypeScript 对象,不使用独立的脚本语言。常用概念可以这样对应:

Ren'PyNarraLeaf React
labelScene
jumpscene.jumpTo(otherScene)
scene bg roomScene 的 backgroundscene.setBackground()
show eileen happyimage.show() 后调用 image.char(["happy"])
hide eileenimage.hide()
e "你好"character.say("你好")
menuMenu.prompt().choose()
default / 持久变量Persistent
Screen LanguagePlayer 内的 React 组件
with dissolvenew Dissolve({ duration })

名称相近,但职责不同。NarraLeaf 的 Character 只负责对话身份和头像规则,舞台立绘由 Image 控制。Scene 更接近 Ren'Py 的 label,不是 Ren'Py 的 scene 语句

一个小型迁移示例

Ren'Py:

define a = Character("爱丽丝")

label start:
    scene bg room
    show alice happy at center
    with dissolve
    a "早上好。"

    menu:
        "打开窗户":
            $ opened_window = True
            jump window
        "继续睡觉":
            jump sleep

NarraLeaf React:

import {
    Character,
    Dissolve,
    Image,
    Menu,
    Scene,
    Story,
} from "narraleaf-react";

const story = new Story("清晨");
const state = story.createPersistent("state", { openedWindow: false });
const alice = new Character("爱丽丝");
const aliceSprite = new Image({
    src: {
        groups: [["happy", "sleepy"]],
        defaults: ["happy"],
        resolve: (expression) => `/characters/alice-${expression}.webp`,
    } as const,
});

const windowScene = new Scene("窗边");
const sleepScene = new Scene("继续睡觉");
const start = new Scene("开场", {
    background: "/backgrounds/room.webp",
}).action((scene) => [
    aliceSprite.show(),
    aliceSprite.char(["happy"], new Dissolve({ duration: 400 })),
    alice.say("早上好。"),
    Menu.prompt("要做什么?")
        .choose("打开窗户", [
            state.set("openedWindow", true),
            scene.jumpTo(windowScene),
        ])
        .choose("继续睡觉", [
            scene.jumpTo(sleepScene),
        ]),
]);

story.entry(start);

UI 与 Screen

NarraLeaf 没有 Screen Language。设置、存档槽位、历史、画廊和菜单都由 React 组件实现。路由页面放在 Player 内;对话框、选项、NVL 和通知组件通过 Game 配置替换

建议先读基础,再参考页面叠层自定义对话框存档系统

迁移前需要考虑的差异

  • 默认不提供回滚 UI,但底层可以调用 liveGame.undo()redo(),并用 canUndo() / canRedo() 控制按钮的可用状态。和 Ren'Py 的 rollback 一样,回退不会丢弃前方的内容:再往前读走的是同样的行,只有当故事走向别处时未来才会被丢弃
  • NarraLeaf 提供可序列化的存档数据,存储方式和槽位 UI 由项目实现
  • 素材使用 URL 或构建工具导入,受网页预加载和浏览器音频规则影响
  • Transform 和 Transition 是 TypeScript 对象,不使用 ATL
  • 界面布局和无障碍由 React 组件负责

本页目录