AIキャラクターが実況するタイピングバトルゲーム
はじめに
うるわし会で発表する用にオンラインの対戦型のタイピングゲームを作ってみました。
ハックツなどに参加して思ったのが、私はシステム作りだけで満足してしまい、演出などの面やゲーム体験を向上させる能力が無いなぁと思ったので演出をいい感じにしようと思って制作しました。
唯そんな完成度高くないのとオンライン機能はまだ作れていないので未完成です。
一旦うるわし会に出しておくとする👆
技術構成
| 技術 | 用途 |
|---|---|
| React 19 + TypeScript | UI・ゲームロジック |
| Vite 7 | ビルドツール・開発サーバー |
| Web Audio API | 効果音の生成(音声ファイル不使用) |
| Socket.IO | オンライン対戦のリアルタイム通信 |
AI実況システム
| 技術 | 用途 |
|---|---|
| aituber-kit | AIキャラクターの表示・制御基盤 |
| Google Gemini 2.0 Flash | セリフ・感情タグの生成 |
| VOICEVOX | テキストから音声を合成 |
インフラ
| 技術 | 用途 |
|---|---|
| Render | Socket.IO サーバーのホスティング |
| GitHub Actions | CI/CD |
どんなゲームなのか
タイピングゲームと銘打っていますが実際は魔法を打ち合うゲームです
魔法を打って相手のHPを削り切れば勝ちで魔法を打つ際には決まった呪文名をタイプしてEnterを押すと魔法を打つことができます
呪文を撃つ際にMPを消費するのですが、MPを回復するための方法がタイピングです。
攻撃でタイピングしねーのかよ!と思われてる方もいると思います。
しません。
エセタイピングゲームです
ですが、
誰が何と言おうと
制作者の私が言うので
タイピングゲームです()
ゲーム画面

左側がメインで動く画面でこのコマンドプロンプト風の画面でタイプをして敵を攻撃します。
右側がAITuber Kitのリポジトリをフォークして作ったおにゃのこです。
結構手が掛かりました。反抗期ですね。
AITuber Kit とは?
Next.js 上で動作する React ベースのフレームワークです。
ゲームイベント発生時に aituber-kit へ状況テキストを送信し、LLM が文章化してキャラクターが読み上げます。キャラクターは iframe でゲーム画面の右側に埋め込んでいます。
推し技術:ゲームイベントのAI実況
ゲームで何かが起きるたびに、AIキャラクターがリアルタイムで実況・反応します。
Magic Post(ゲーム)
↓ ゲームイベント発生(被弾・命中・カウンターなど)
↓ HTTP POST
aituber-kit(AIキャラクター基盤)
↓ Gemini API でセリフ生成
↓ VOICEVOX API で音声合成
キャラクターが喋る+表情が変わる
aituber-kitのいい点:LLM・TTS・キャラクター表示がひとまとめ
キャラクターに喋らせるだけならテキストを生成して音声の出力だけで済みます。しかし aituber-kit は LLM によるセリフ生成・TTS による音声合成・Live2D キャラクターの表示と表情制御 をひとつのフレームワークにまとめています。
さらに HTTP API(/api/v1/chat/)を公開しているため、外部アプリから1回のリクエストを投げるだけで「AIがセリフを考えて喋る+表情が変わる」という一連の動作が完結します。自分で LLM API・TTS API・キャラクター制御をそれぞれ実装する必要がなく、ゲーム側でそこまで意識する点はなくて楽ができます。
// ゲーム側はテキストを投げるだけ
await fetch("/aituber-api/chat/", {
method: "POST",
body: JSON.stringify({ text: "被弾!残りHP: 30", clientId: "magic-post", mode: "ai_generate" }),
});
VOICEVOXのいい点:無料キャラクターボイス
VOICEVOX はローカルで動く無料の音声合成エンジンです。クラウド TTS と違い、リクエスト1回ごとの課金が発生しないです。
ずんだもんやきりたんといったkawaii声を選べるからみんな使った方がiiyo.
aituber-kit の設定で話者 ID を変えるだけで声が切り替わるのも手軽でした。
Gemini関連:感情タグ付きセリフを生成するように指定
aituber-kit ではキャラクターの表情変化を 感情タグ([happy]、[sad] など)でテキストに埋め込む形で制御します。
[happy]攻撃命中!敵を追い詰めろ!
[sad]被弾してしまった...ピンチだ。
Gemini はシステムプロンプトで書式を指示するだけで、ゲーム状況から感情を判断して適切なタグ付きセリフを生成してくれます。「HP が低いので悲しい表情で」といったルールを自分でコーディングしなくても、LLM がコンテキストを読んで自然に判断してくれる点が強かったです。
systemPrompt: `感情の種類は neutral, happy, angry, sad, relaxed, surprised の6つです。
回答は必ず以下の書式で返してください。
[{感情}]{セリフ}`,
ただし感情の大枠はゲーム側でも制御したいため、HP 比率から感情のヒントをログに出しながら開発しました。
const getEmotion = (p: PlayerState, c: PlayerState): string => {
const playerRatio = p.hp / p.maxHp;
const cpuRatio = c.hp / c.maxHp;
if (playerRatio < 0.15) return "angry";
if (playerRatio < 0.30) return "sad";
if (cpuRatio < 0.40) return "happy";
return "neutral";
};
感想
AITuber機能多くてフルで活用するの無理だなって思った
反省
開発に夢中になって発表用のgeminiAPIの無料分を使い切ってしまったので反省
実はあんま開発やってなかったから毎日草を生やせるように頑張りたいですね

驚きの白さ