コンテンツにスキップ

Vega

Vega は haneoka.org のストーリープレーヤーを支えるビジュアルノベルエンジンです。ストーリー(台詞、キャラクター、背景、カメラ、サウンド、選択肢、チャットのコマンドの並び)を読み、何が話され、誰がステージにいて、何が再生されるかという状態に変えます。見えるものと聞こえるものはすべてプラグインが担うため、同じエンジンで、3D のステージと Live2D キャラクターを備えたフル構成も、スマートフォン向けの軽い 2D ステージも、WebGL をまったく使わない素の DOM 表示も動かせます。

部分公式プラグインない場合
レンダラーThree.js、Pixi背景、スチル、立ち絵を表示する DOM のシーン。
ストーリー UIPortable UI自分で用意する dialogue UI スロット。
シェル標準シェル: タイトル、セーブ、設定、バックログ、ギャラリー、フローチャートストーリーがすぐに始まる。
テーマHaneoka、Portable、WebGALスタイルのない UI。
キャラクターCubism(Live2D)、Spine、合成モデル静止画のみ。
テキストリッチテキストと Markdown、BBCode、HTML、LaTeX、Typstプレーンテキスト。
その他エンディング画面、WebGAL 互換、Haneoka ホスト

Vega Full Preset を使うと、妥当な一式を 1 回の呼び出しで組み立てられます。

Terminal window
pnpm add @haneoka/vega @haneoka/vega-preset-full three@0.184
import { VegaEngine } from "@haneoka/vega/engine";
import createVegaFullPreset from "@haneoka/vega-preset-full";
const engine = new VegaEngine({ officialPlugins: createVegaFullPreset() });
const player = await engine.createPlayer({
mount: document.querySelector("#story")!,
story: await (await fetch("/stories/episode-1.json")).json(),
});
await player.player.play();

createPlayer は必要ならエンジンを起動し、要素の下にプレーヤーを置き、ストーリーが使うリソースをすべて読み込んでハンドルを返します。player.player から play()、pause()、resume()、requestNext()、choose(key)、seekTo(index) を呼び、リアクティブな state(現在の行、バックログ、ストーリーが終わったか)を読めます。ハンドルはエンジンより先に破棄してください。エンジンを破棄するとそのプレーヤーも破棄されます。

何もインストールせずに haneoka.org のストーリーを埋め込むには、代わりに Vega の埋め込みを使います。

ストーリーは commands 配列を持つ JSON です。各コマンドは数値の command コードとそのフィールドを持ちます。

{
"commands": [
{ "command": 25, "background": { "url": "/bg/rooftop.png" }, "duration": 0.5 },
{ "command": 0, "targetName": "anon", "characterModel": { "runtime": { "imageUrl": "/figure/anon.png" } } },
{ "command": 2, "targetName": "anon", "text": "Let's go!" }
]
}

ここで 25 は Stage(背景の設定)、0 はキャラクターの登場、2 は台詞 1 行です。

コマンドの種類はゲームと同じです。台詞と話者、モーションと表情を伴うキャラクターの登場・退場、背景とスチル、カメラのパン・チルト・ズーム・揺れ、被写界深度、BGM、効果音とボイス、フェード、フラッシュ、トランジション、チャット画面のシーン、字幕付きムービー、選択肢、ジャンプ、コマンドグループがあります。コードは @haneoka/vega-protocol(VEGA_ADV_OPCODE)にあります。実際に手で書くことはほとんどなく、Altair がフォームで編集し、その取り込み機能が WebGAL、Bestdori、文章から生成します。

テキストはゲームのマークアップ(ルビ、色、サイズ)に対応し、形式プラグインを入れれば Markdown なども使えます。テキストのフィールドには複数の言語を入れられ、プレーヤーは読み手の言語を表示します。

リソースはストーリー内の URL です。HTTP(S)、data:、blob: の URL はそのまま読み込みます。アーカイブ、アプリ独自のプロトコル、CDN の対応付けには、スキームと load 関数を持つリソースプラグインを加えます。許可された範囲から出ようとする URL(..、空、または安全でないパス)は読み込み前に拒否されます。

ストーリーを始める前に、Vega は必要なリソースをすべて列挙して読み込みます。各 Live2D モデルが実際に使うモーションも含むため、再生の途中でダウンロード待ちが起きません。

const engine = new VegaEngine({
officialPlugins: [threeRenderer, portableUi],
plugins: [myAnalyticsPlugin],
});

officialPlugins は配布物の一部として信頼され、plugins はサードパーティー扱いでサードパーティーの権限を受けます。プラグインはレンダラー、UI スロット、テーマ、キャラクターのプロバイダー、コマンド、リソース、ストレージ、入力を提供し、プラグインを外すかエンジンを破棄すると登録はすべて取り消されます。初期化に失敗したプラグインは完全に巻き戻されます。

プロジェクトは必要なプラグインを記録し、マーケットプレイスのカタログが公式プラグインとその権限、依存関係を一覧します。

標準シェルは、Vega のストレージポートを通してセーブ、設定、バックログを提供します。既定ではブラウザーに保存します。ホストプラグインを使えば別の場所に保存でき、Haneoka ホストプラグインはストレージと入力を、アプリ側で実装する小さなブリッジ経由で扱います。

プロジェクトをサイト、PWA、デスクトップアプリ、モバイルプロジェクトにするには Deneb を使います。

Vega リポジトリの README がエンジン API を、各プラグインの README がそのオプションのすべてを説明しています。