import {
audio,
wait,
defineVQTimeline,
say,
still,
standeeFacingDirection,
standeeShake,
standeeVerticalOffset,
type VQCustomTimelineEvent,
type VQStandeeFacingDirectionEvent,
type VQStandeeShakeEvent,
type VQStandeeVerticalOffsetEvent,
type VQSpeechEvent,
type VQTimelineEvent,
type VQTimelineInputEvent,
} from "../../lib/VQRemotionLib/timeline";
import type {CharacterId, VoicevoxVoice} from "./characters";
export {characters, initialVisibleCharacters} from "./characters";
export type {CharacterDefinition, CharacterId, VoicevoxVoice} from "./characters";
export const compositionTitle = "ずんだもんの持論";
export type ShowOptions = Readonly<{
caption?: string;
durationSeconds?: number;
}>;
export type SpeechEvent = VQSpeechEvent<CharacterId, VoicevoxVoice>;
export type ShowEvent = VQCustomTimelineEvent<
"show",
{
character: CharacterId;
caption?: string;
durationSeconds?: number;
}
>;
export type TimelineEvent = VQTimelineEvent<
CharacterId,
VoicevoxVoice,
| ShowEvent
| VQStandeeFacingDirectionEvent<CharacterId>
| VQStandeeShakeEvent<CharacterId>
| VQStandeeVerticalOffsetEvent<CharacterId>
>;
export type TimelineInputEvent = VQTimelineInputEvent<
CharacterId,
VoicevoxVoice,
| ShowEvent
| VQStandeeFacingDirectionEvent<CharacterId>
| VQStandeeShakeEvent<CharacterId>
| VQStandeeVerticalOffsetEvent<CharacterId>
>;
// 用途: キャラクターを画面に登場させ、任意の説明字幕を表示する。
// 使用方法: timeline 内で show("sayo", {caption: "小夜が登場!"}) のように呼び出す。
// オプションや引数詳細: durationSeconds を省略すると timing.ts の既定秒数で表示する。
export const show = (
character: CharacterId,
options: ShowOptions = {}
): ShowEvent => ({
type: "show",
character,
...options,
});
export const timeline = defineVQTimeline([
still("zundamon-jiron-background-001", "image/still/nc238325_living_day.jpg", {
fit: "cover",
}),
audio("zundamon-jiron-bgm-001", "audio/common_bgm/saturn-3-music-rockabye-baby-music-box-lullaby-loopable-527146.mp3", {
playback: "loop",
volume: 0.2,
}),
say("zundamon-jiron-zunda-001", "zundamon", "ふー、着替えて落ち着いたのだ。"),
say("zundamon-jiron-zunda-002", "zundamon", "やっぱり寮ではこのスタイルが一番なのだ。"),
standeeVerticalOffset("zundamon-jiron-zunda-y-001", "zundamon", -150),
audio("zundamon-jiron-sound-effect-002", "audio/common_soundeffect/Door 6_5 Open.wav",
{
playback: "once",
durationSeconds: 1.5,
}
),
show("sayo", { }),
say("zundamon-jiron-sayo-001", "sayo", "あ、ずんだもんだ。"),
standeeFacingDirection("zundamon-jiron-zunda-facing-001", "zundamon", "right"),
say("zundamon-jiron-sayo-002", "sayo", "あったかくなってきたにしても、おむつ一枚はちょっとラフな格好すぎない?"),
say("zundamon-jiron-zunda-003", "zundamon", "そんなことないのだ!これが夏のベストスタイルなのだ!"),
say("zundamon-jiron-zunda-004", "zundamon", "小夜もこのスタイルにしてみればいいのだ。たぶん似合うし、快適なのだ!"),
say("zundamon-jiron-sayo-003", "sayo", "えー、私はいいや。なんか清潔じゃない感じがするし…。"),
say("zundamon-jiron-zunda-005", "zundamon", "それは偏見なのだ!"),
say("zundamon-jiron-zunda-006", "zundamon", "考えてみるのだ。紙おむつは常に新品をあてることになるから、むしろ清潔なのだ!"),
say("zundamon-jiron-zunda-007", "zundamon", "毎日おろしたての下着を身につけるようなものなのだ。洗濯して使い続ける下着よりも清潔なのは明らかなのだ。"),
say("zundamon-jiron-sayo-004", "sayo", "うーん、そう言われると確かにそうかも…。"),
say("zundamon-jiron-zunda-008", "zundamon", "なのだ?だからみんなもこのスタイルを試してみるといいのだ!"),
say("zundamon-jiron-sayo-005", "sayo", "確かに言ってることはまちがってないんだけど、\n清潔なのは「穿いた直後」の話だよね?"),
say("zundamon-jiron-zunda-009", "zundamon", "うっ…!"),
audio("zundamon-jiron-sound-effect-001", "audio/common_soundeffect/nc174220_osikko7.mp3",
{
playback: "once",
durationSeconds: 10.0,
}
),
standeeShake("zundamon-jiron-zunda-shake-001", "zundamon", {
durationSeconds: 2.0,
amplitudeX: 9,
amplitudeY: 6,
frequencyHz: 16,
}),
wait(2.0),
say("zundamon-jiron-zunda-010", "zundamon", "……丁度いま、清潔じゃなくなったのだ。"),
say("zundamon-jiron-sayo-006", "sayo", "そうだね…。"),
say("zundamon-jiron-sayo-007", "sayo", "(……でも、漏らさないで使う限りはずんだもんが言うとおりなのかな?)"),
say("zundamon-jiron-zunda-011", "zundamon", "こまめに替えれば大丈夫なのだ!\nなので、小夜もおむつスタイルを試してみるといいのだ!"),
say("zundamon-jiron-sayo-008", "sayo", "考えておくね。\nずんだもんは早くおむつ替えてね。"),
say("zundamon-jiron-zunda-012", "zundamon", "そうするのだ!"),
wait(4.0),
] satisfies readonly TimelineInputEvent[]);