NarraLeaf

对话框头像教程

用角色头像与 Avatar 组件,在 ADV 模式对白旁显示小尺寸立绘

ADV 文本旁的小头像由 Avatar 渲染。配置分两步:

  1. Character 上配置用哪张图(也可用舞台 Image 做表情立绘)
  2. 在自己的 Dialog摆上 <Avatar />

完整规则(解析顺序、解析器函数、类型)见 DialoguseAvatar

1. 配置角色级头像

一张固定图片,角色说话时都会显示,包括没有立绘在场上的旁白

import { Character } from "narraleaf-react";

const alice = new Character("Alice", {
    avatar: "/characters/alice/avatar.png",
});

alice.say("玩家会在文字旁边看到我的小头像。");

链式写法:

const bob = new Character("Bob").setAvatar("/characters/bob/avatar.png");

头像需要有名字的角色。旁白new Character(null))不显示头像

2. 在对话框里放上 Avatar

Avatar 会根据当前这一句解析出头像;没有可显示的图片时不渲染,不会留出空白占位

通常和 NametagTexts 并排,布局和内置默认对话框一致:

import {
    Avatar,
    Dialog,
    Nametag,
    Texts,
} from "narraleaf-react";

export function GameDialog() {
    return (
        <Dialog className="bg-black/75 rounded-xl px-5 py-4 text-white">
            <div
                className="flex items-start gap-4"
                style={{ width: "100%", minHeight: 96 }}
            >
                <Avatar
                    className="shrink-0 rounded-lg border border-white/20"
                    style={{ width: 88, height: 88 }}
                />
                <div className="min-w-0 flex-1 flex flex-col gap-1">
                    <Nametag className="text-base font-semibold" />
                    <Texts className="text-sm leading-relaxed" />
                </div>
            </div>
        </Dialog>
    );
}

不写 style 时默认 96×96,可用 classNamestyle 覆盖

可选:用 useAvatar 自适应布局

要让文字栏在没有头像时占满整行,读取 useAvatarvisible

import {
    Avatar,
    Dialog,
    Nametag,
    Texts,
    useAvatar,
} from "narraleaf-react";

export function GameDialog() {
    const { visible } = useAvatar();

    return (
        <Dialog className="bg-black/75 rounded-xl px-5 py-4">
            <div
                className="grid gap-4 items-start text-white"
                style={{
                    gridTemplateColumns: visible ? "96px minmax(0,1fr)" : "minmax(0,1fr)",
                }}
            >
                {visible && <Avatar />}
                <div>
                    <Nametag />
                    <Texts />
                </div>
            </div>
        </Dialog>
    );
}

3. 注册自定义对话框

创建 Game 时指定组件,再把同一个实例传给 GameProviders

import { Game, GameProviders, Player } from "narraleaf-react";
import { GameDialog } from "./GameDialog";

const game = new Game({ dialog: GameDialog });

export function GameView() {
    return (
        <GameProviders game={game}>
            <Player story={story} onReady={({ liveGame }) => liveGame.newGame()} />
        </GameProviders>
    );
}

4. 单行与立绘规则

某一行不要头像

alice.say("这一句不显示头像。", { avatar: false });

可选:场上的立绘换一张对话框头像

当舞台 Image 可见时,可以为它单独指定对话框头像(见角色页的 addPortrait):

const body = new Image({
    name: "alice-body",
    src: "/characters/alice/body-normal.png",
});

const alice = new Character("Alice", {
    avatar: "/characters/alice/avatar-default.png", // body 藏起来时用
    portraits: [{ image: body, avatar: "/characters/alice/avatar-smile.png" }],
});

scene.action([
    alice.say("画外 → 默认头像"),
    body.show(/* ... */),
    alice.say("上台 → 微笑头像"),
]);

小结

目的做法
给有名角色出头像图Character 构造函数里的 avatar.setAvatar(...)
屏幕上画出来<Dialog> 里放入 <Avatar />
使用自己的对话框game.configure({ dialog: 你的组件 })
单行特例{ avatar: false }{ avatar: "/其它.png" } 或解析器(详见 Dialog

多个可见立绘与标签解析器见 Dialog

本页目录