ミニゲーム
Pixi’VNにミニゲームを統合するためのガイド。ベストプラクティス、ライフサイクル管理、PixiJSとReactを使用した実装例を含みます。
AI
上のボタンを使用して、AIで独自のミニゲームを作成できます。
通常のテキストと比較したインタラクティブなストーリーの魅力は、一息ついてストーリーに関連するミニゲームで遊べることです。
ビジュアルノベルのミニゲームは、通常物語の途中で起動されます。物語のUIとミニゲームのUIを切り替えるには、ミニゲームをルート(例: "/minigame/snake")にリンクし、ストーリーからそこへナビゲートすることを推奨します。詳細についてはこちらをご覧ください。
以下にいくつかのヒントを紹介します:
- PixiJSを直接使用します —
pixi.jsパッケージ自体、またはそれを再エクスポートする@drincs/pixi-vn/pixi.jsサブモジュールのいずれかを —Graphics、Sprite、Textなどのコンポーネントとともに、PixiJS Layersと組み合わせて、メインのビジュアルノベルインターフェースから独立して管理される、ミニゲーム専用のレイヤーを作成します。 - ミニゲームの操作のためのキーボード入力を処理するには、Hotkeysを使用します。設定方法についてはHotkeysを参照してください。
- UI(ボタン、スコア表示、ゲームオーバーメッセージなど)の構築にはPixiJSを使用しないことを常に推奨します。代わりにReactやVueなどのフレームワークを使用してください。
- ミニゲームの現在の状態を保存・復元することは、開発者の責任です。
- ミニゲームはそれ自体が1つのルートであるため、プロジェクトでは通常、同じ
/minigameパス(例:/minigame/snake、/minigame/quiz)の下に複数のミニゲームが存在することになります。TanStack Routerのファイルベースルーティングを使用して、各ミニゲームでロジックを重複させる代わりに、それらの間でロジックを共有してください(下記参照)。 - ミニゲームを開始することは、ストーリーからそのルートへナビゲートするだけのことです。パラメータ(難易度、レベルIDなど)が必要な場合は、同じルートを通じてそれを渡してください(下記参照)。
テンプレート
useMinigameは、開始、更新、リソースのクリーンアップを含め、ミニゲームのライフサイクルを管理するのに役立つカスタムフックです。すべてのテンプレートに含まれています。
例:
import { Layer } from "@drincs/pixi-vn";
import { Graphics, Ticker } from "@drincs/pixi-vn/pixi.js";
import { createFileRoute } from "@tanstack/react-router";
import { useCallback, useMemo, useState } from "react";
import { useHotkey } from "@tanstack/react-hotkeys";
import useMinigame from "@/lib/hooks/minigame-hooks";
export const Route = createFileRoute("/minigame/example")({
component: MiniGame,
});
function MiniGame() {
const [displayScore, setDisplayScore] = useState(0);
const [gameOver, setGameOver] = useState(false);
const ticker = useMemo(() => {
const ticker = new Ticker();
const endGame = () => {
ticker.stop();
setGameOver(true);
};
ticker.add(({ deltaMS }) => {
// Update game logic here
});
return ticker;
}, []);
useHotkey(
"ArrowUp",
() => {
// Handle key down events for game controls
},
{ enabled: !gameOver },
);
const game = useCallback(
(layer: Layer) => {
ticker.start();
},
[ticker], // They must not be changed during the game otherwise the game will restart
);
const options = useMemo(
() => ({
onExit() {
ticker.stop();
ticker.destroy();
},
}),
[ticker], // They must not be changed during the game otherwise the game will restart
);
const { loading } = useMinigame(game, options);
return (
<>
<div
style={{
position: "absolute",
top: 10,
left: 10,
color: "white",
fontSize: "24px",
background: "rgba(0,0,0,0.5)",
padding: "5px 10px",
borderRadius: "5px",
}}
>
Score: {displayScore}
</div>
{gameOver && (
<div
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
color: "red",
fontSize: "48px",
background: "rgba(0,0,0,0.7)",
padding: "20px 40px",
borderRadius: "10px",
}}
>
GAME OVER
</div>
)}
</>
);
}例
Pixi’VNチームは、このライブラリをさらに充実させるための新しい提案や貢献を歓迎します。以下のチャットで、ミニゲームの実装を自由に共有したり提案したりしてください!