NarraLeaf

声音

用 Sound 播放音效、背景音乐与语音片段,并用 Control.doAsync 让播放与剧情并行推进

使用 Sound 播放音效、背景音乐和语音。静态构造方法会为声音设置正确类型

import { Sound } from "narraleaf-react";

const door = Sound.sound({
    src: "/audio/door.ogg",
    volume: 0.8,
});

const theme = Sound.bgm({
    src: "/audio/theme.ogg",
    volume: 0.5,
    loop: true,
});

音效

play() 返回一个动作。默认情况下,剧情会等到音频播放结束

scene.action([
    door.play(),
    alice.say("有人来了。"),
]);

如果剧情需要在声音播放时继续执行,可把声音放到异步控制栈

import { Control } from "narraleaf-react";

scene.action([
    Control.doAsync([door.play()]),
    alice.say("门在你身后关上了。"),
]);

旧版的 sync 配置已经移除。非阻塞音频请使用 Control.doAsync()Control.allAsync()

背景音乐

可以在场景配置中指定 BGM,也可以在剧情中更换。淡入淡出时间的单位是毫秒

const room = new Scene("房间", {
    backgroundMusic: theme,
    backgroundMusicFade: 800,
});

room.action([
    room.setBackgroundMusic(Sound.bgm("/audio/night.ogg"), 800),
]);

传入 null 可以停止当前 BGM

room.setBackgroundMusic(null, 500);

前奏与循环区间

seek 是音频的入点,endTime 是出点。配合 loop,这一对就构成了循环区间,而 loopStart 指定每一遍回到哪里—— 带前奏的背景音乐正是这样先完整播一遍开头,然后只重复主体

const theme = Sound.bgm({
    src: "/audio/theme.ogg",
    loop: true,
    seek: 0,       // 第一遍从头开始
    loopStart: 12, // 之后每一遍都回到这里,跳过前奏
    endTime: 90,
});

循环是采样级精确的——接缝处没有空隙,长时间播放也不会漂移。参见 ISoundUserConfig

要移动正在播放的音频的播放头,把 seek() 当作动作使用:

room.action([
    theme.seek(12), // 跳过前奏
]);

音量与总线

每段音频都在某条音频总线上播放,由它的 type 决定。游戏无需声明就拥有 bgmsoundvoice, 也可以再声明更多——比如为每个角色一条总线——从而提供固定三条总线表达不出的玩家控制 参见音频总线

播放控制

Sound 动作可以调整播放状态和参数

scene.action([
    door.setVolume(0.3, 300),
    door.setRate(1.2),
    door.pause(200),
    door.resume(200),
    door.mute(),
    door.unmute(),
    door.stop(300),
]);

在 React UI 中需要立即播放声音时,使用 liveGame.playSound(),不用创建剧情动作

const liveGame = useLiveGame();

<button onClick={() => liveGame.playSound("/audio/click.ogg")}>播放</button>

本页目录