0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ハードボイルド探偵ADVを作ろうとしたらサイバーパンクになった話——AIと共作したノベルゲームの技術構成

0
Posted at

始まり

やりたかったのは、ハードボイルドな探偵ものだった。

薄暗い事務所、ミントを噛み砕く探偵、控えめなノックの音。新宿の夜を舞台に、古き良き探偵小説の空気感をゲームにしたかった。それだけのつもりだった。

ところが、AIと一緒にストーリーを組み立てていくうちに、話がどんどんおかしな方向に転がり始めた。

「地下道に毎週置かれる青いバラ」の謎を追っていたはずが、いつの間にか「ゴーストプロトコル」だの「ウロボロス」だの物騒なコードネームが飛び交い、警察庁の元局長が暗殺を「業務委託」で決裁していたり、黒幕がデジタル空間で「神」を気取っていたりする。

完全にサイバーパンクだった。

最初は「いや、そっちに行く?」と思ったけれど、AIが提案してくるプロットが妙に筋が通っていて、気がつけば乗っかっていた。ハードボイルドとサイバーパンクが混ざり合って、自分では絶対に思いつかないカオスな世界観が出来上がった。

ゲームの構成

出来上がったのは、3ルート・28シナリオファイル・8種類のミニゲームを持つノベルゲームだ。

シナリオの規模

static readonly string[] allFiles = {
    "Chapter1", "Chapter2",
    "Chapter2_Saeki", "Chapter2_Rin",
    "Flashback1",
    "Chapter3", "Chapter3_Saeki", "Chapter3_Rin", "Chapter3_Merge",
    "Flashback2",
    "Chapter4", "Chapter5",
    "END_Main_Good", "END_Main_Bad",
    "RinStory_Ch1", "RinStory_Ch2", "RinStory_Ch3", "RinStory_Ch4", "RinStory_Ch5",
    "END_Rin_Good", "END_Rin_Bad",
    "KasumiStory_Ch1", "KasumiStory_Ch2", "KasumiStory_Ch3",
    "KasumiStory_Ch4", "KasumiStory_Ch5", "KasumiStory_Ch6",
    "END_Kasumi_Good", "END_Kasumi_Bad"
};
  • メインルート: 全5章+グッド/バッドエンド
  • 凛ルート: 全5章+グッド/バッドエンド(19歳のハッカー)今後追加予定
  • 霞ルート: 全6章+グッド/バッドエンド(バーテンダー)今後追加予定
  • フラッシュバック: 2本(故人・遠藤の過去)今後追加予定

全てのシナリオはJSONで管理されていて、選択肢による分岐とファイル間の連鎖で物語が進む。

技術的な構成

JSON駆動のダイアログシステム

シナリオデータは1行1行がJSON構造体として定義されている。

[Serializable]
public class DialogueLine
{
    public string charName;    // 話者名
    public string text;        // セリフ
    public string pose;        // キャラクター表情
    public string bg;          // 背景画像
    public string bgm;         // BGM切替
    public string se;          // 効果音
    public string choice1;     // 選択肢1
    public string choice2;     // 選択肢2
    public string next1;       // 選択肢1のジャンプ先
    public string next2;       // 選択肢2のジャンプ先
    public string miniGame;    // ミニゲーム発動
    public string nextFile;    // 次のシナリオファイルへ連鎖
}

1つのJSONフィールドで「セリフ表示」「背景変更」「BGM切替」「選択肢分岐」「ミニゲーム起動」「次章への連鎖」を全て制御できる。プログラマーが個別にイベントを組む必要がなく、シナリオライター(=AI)がJSONを書くだけでゲームが動く

8種類のミニゲーム

ADVパートの途中でシナリオに応じたミニゲームが発動する。全てAction<bool>コールバックで成否をADVエンジンに返す統一設計。

ミニゲーム 内容 シーン
HackingGame 16進コードの記憶・再現(サイモン風) 凛のハッキングシーン
CipherLinkGame 暗号フラグメントのペアリング 霞と遠藤の暗号鍵復元
QTEBattleGame タイミングバー+キーシーケンス 格闘シーン
StealthGame 8×6グリッドの潜入パズル ビル侵入シーン
AlleyChaseGame 路地裏の追跡 追跡シーン
DigitalInquisitionGame デジタル尋問 情報引き出し
WisdomRingGame 知恵の輪 謎解きシーン
HangOnGame 耐久 危機脱出シーン
// HackingGame: 16進コードの色で記憶する
static readonly string[] hexPool = {
    "7A", "BD", "1C", "E9", "FF", "42", "D1", "93", "A3", "C8", "55", "F4"
};
// StealthGame: 8×6グリッドで敵の視界を避ける
const int COLS = 8, ROWS = 6;

struct Enemy
{
    public int x, y, dir, min, max;
    public bool horiz;  // 水平パトロールか垂直か
}

ミニゲームに失敗してもストーリーは進む(難易度が変わる場合がある)。ADVのテンポを崩さないように、各ミニゲームはチュートリアル→プレイ→結果の3ステップで完結する設計にした。

多言語対応

LanguageManagerで全テキストをキーベースで管理。ミニゲームのチュートリアルも含めて多言語化している。

// ミニゲーム内のUIテキストも全てキーで参照
MakeLabel(tutGo.transform, LanguageManager.T("breach_title"), 40, ...);
MakeLabel(tutGo.transform, LanguageManager.T("tut_hacking"), 24, ...);

キャラクターの話

でも、このゲームで一番気に入っているのは世界観よりもキャラクターだ。

主人公の冴木蓮は33歳の探偵。ミントを噛む癖があって、過去に何かを失っている男。彼を「おじさん」と呼ぶ19歳の凛は、生意気だけど腕の立つハッカーで、この二人の掛け合いが妙に楽しい。バーで働く霞や、物語の発端となる故人・遠藤——AIと一緒に作ったはずなのに、どのキャラクターもちゃんと「生きている」感じがする。

正直、最初に自分が思い描いていたゲームとはまったく違うものが出来上がった。でも、これはこれで好きだ。むしろ自分一人では絶対に辿り着けなかった場所にいる、という感覚がある。

灰色の残響——タイトルも、AIとの共作にふさわしい名前だと思っている。

ダウンロード

灰色のリフレイン:近未来探偵ノベル×謎解きパズル - Google Play

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?