ふくふくHukuhuku Inc.
EP.09LLM Gamedev 11分公開: 2026-05-26

Ren'Py × LLM ── ノベルゲームのシナリオ・分岐・キャラ会話を生成 AI で

ノベルゲームエンジン Ren'Py と LLM の組合せ。シナリオ生成、分岐設計、キャラごとの口調維持、立ち絵 / 背景 / BGM の生成 AI 連携。Python 拡張で実行時 LLM も。

#Ren'Py#ノベルゲーム#シナリオ生成#Python#立ち絵
執筆 / 監修
松尾 亮合同会社ふくふく 代表社員

データ基盤・データパイプライン構築 / BI / 生成 AI 活用支援を専門とするエンジニア (28 年)。 本記事は AI 利用ポリシーに基づき、生成 AI の補助で執筆 → 人間が監修・編集して公開しています。

プロフィール詳細
シェア

EP.09 は × ── ノベルゲームエンジン を使って、 生成シナリオ + 生成立ち絵 + Suno 生成 BGM でフルセットを作る話。テキスト中心のジャンルゆえに 連動度が ★4-5 と高い領域です。 / のシナリオライティング能力を最大化します。

1. Ren'Py の最小サンプル

game/script.rpy ── Ren'Py の典型スクリプト
Python
# キャラ定義define h = Character("ヘリアス", color="#a08060")define p = Character("プレイヤー")
# 画像定義image bg tavern = "images/bg_tavern.jpg"image helias normal = "images/helias_normal.png"image helias smile = "images/helias_smile.png"
# シナリオlabel start:    scene bg tavern    play music "audio/bgm_tavern.ogg"
    show helias normal at left
    h "おお、新顔か。座れ。"    h "ここは『銀の鴉亭』 ──酒も飯もある。情報もな。"
    menu:        "依頼を聞きたい":            jump quest_branch        "酒を飲む":            jump drink_branch        "店を出る":            jump leave_branch
label quest_branch:    show helias smile    h "ほう、冒険者か。最近は北の塔が騒がしくてな……"    # 以下続く    return

2. シナリオを LLM に生成させる

プロット → 節生成プロンプト
Text
世界観: 中世ファンタジー、王国ヴェラント、魔物が増えているキャラ:  - ヘリアス: 58歳元冒険者の老マスター、寡黙だが情報通  - 主人公: 駆け出しの冒険者、性別任意、声を当てない (沈黙の主人公)
このシーンを Ren'Py スクリプトで書いて:場所: 銀の鴉亭、夜、客は少なめイベント: 主人公がヘリアスに北の塔の調査依頼を受けるキャラ感情の弧: ヘリアスは最初警戒 → 主人公の真摯さを認める → 注意を促す分岐: 「報酬を交渉する」 vs 「すぐ引き受ける」 → ヘリアスの態度が変わる長さ: 30-40 行、台詞主体、地の文最小限

3. LLM 生成出力を .rpy に整形するスクリプト

tools/gen_scene.py
Python
from anthropic import Anthropicimport reimport os
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
def generate_scene(prompt: str, scene_name: str) -> str:    response = client.messages.create(        model="claude-opus-4-7",        max_tokens=2000,        system="あなたはノベルゲームのシナリオライター。Ren'Py スクリプトを書く。",        messages=[{"role": "user", "content": prompt}],    )    raw = response.content[0].text
    # トリプルバッククォートで囲まれたコードブロックを取り出す    match = re.search(r"```(?:renpy|python)?\n(.+?)```", raw, re.DOTALL)    rpy_code = match.group(1) if match else raw
    # ファイルに書出し    out_path = f"game/scenes/{scene_name}.rpy"    os.makedirs(os.path.dirname(out_path), exist_ok=True)    with open(out_path, "w") as f:        f.write(f"# Auto-generated: {scene_name}\n\n")        f.write(rpy_code)    print(f"Saved {out_path}")    return out_path
# 使い方generate_scene(    prompt=open("prompts/scene_tavern.txt").read(),    scene_name="tavern_intro")

4. 立ち絵生成 (キャラ一貫性が課題)

  • IP-Adapter / FaceID: 参照画像から顔特徴を引き継ぐ
  • LoRA 学習: 5-20 枚の参照画像で 1 キャラ専用 LoRA を作る (Kohya-trainer 等)
  • ControlNet (Reference / OpenPose): 同じポーズ・構図で複数表情
  • rembg で背景除去: `pip install rembg && rembg i input.png output.png`
  • Outpainting で縦長化: SDXL の正方形出力を 800x1200 に拡張

5. 実行時 LLM 会話 (Ren'Py から API 呼び出し)

game/llm_npc.rpy ── Ren'Py の中で Python を使う
Python
init python:    import json    import urllib.request
    ANTHROPIC_API_KEY = "your-key"
    def npc_reply(npc_name, system_prompt, conversation):        """Claude API を呼んで NPC 返答を取得"""        data = {            "model": "claude-haiku-4-5-20251001",  # コスト重視            "max_tokens": 200,            "system": system_prompt,            "messages": conversation,        }        req = urllib.request.Request(            "https://api.anthropic.com/v1/messages",            data=json.dumps(data).encode(),            headers={                "x-api-key": ANTHROPIC_API_KEY,                "anthropic-version": "2023-06-01",                "content-type": "application/json",            }        )        try:            with urllib.request.urlopen(req, timeout=10) as r:                result = json.load(r)                return result["content"][0]["text"]        except Exception:            return "(無言で頷いた)"  # フォールバック
label dynamic_chat:    $ helias_history = []    $ system_prompt = "あなたは老マスター ヘリアス…(略)…"
    show helias normal at left
    label chat_loop:        $ player_input = renpy.input("ヘリアスに話しかける:", length=200)        if player_input.strip() == "":            jump end_chat
        $ helias_history.append({"role": "user", "content": player_input})        $ reply = npc_reply("ヘリアス", system_prompt, helias_history)        $ helias_history.append({"role": "assistant", "content": reply})
        h "[reply]"        jump chat_loop
    label end_chat:        h "また来るがいい。"        return

6. アセット一括生成パイプライン

アセット生成ツールRen'Py での扱い
キャラ立ち絵SDXL + LoRA + rembgimages/<キャラ>_<表情>.png
背景SDXL / Midjourney (16:9)images/bg_*.jpg
BGMSuno / Stable Audio + ループ加工audio/bgm_*.ogg
SFXElevenLabs Sound Effectsaudio/sfx_*.mp3
音声ElevenLabs / Voicevoxaudio/voice/<キャラ>_<台詞ID>.ogg
UISDXL + ControlNet (Edge)gui/*.png

7. ビルド・配布

Ren'Py プロジェクトのビルド
Bash
# Ren'Py SDK をダウンロード後、CLI も使えるrenpy launch myproject distribute --packages pc,mac,linux,web
# 出力先 (デフォルト)ls myproject-dists/# → myproject-1.0-pc.zip (Win)# → myproject-1.0-mac.zip (Mac)# → myproject-1.0-linux.tar.bz2# → myproject-1.0-web.zip (HTML5)
# itch.io 配信 (butler 経由)butler push myproject-1.0-pc.zip myuser/mygame:windows

8. ノベルゲームならではの設計 tips

  • 主人公の発話を最小化: プレイヤーの自由想像を残す (「沈黙の主人公」 が定石)
  • 選択肢は 2-3 個: 多すぎると選択疲れ、極端な分岐は別ルートに収束させる
  • 既読スキップ対応: Ren'Py 標準でスキップ機能、テキスト変更時の seen tracking
  • 音声のオートプレイ・スピード調整: アクセシビリティ重要
  • セーブスロット 10 個以上: ノベルゲー流派の慣習

9. 著作権・年齢制限・公開戦略

  • AI 生成立ち絵の公開: 「AI 生成」 開示を Steam / itch.io で明記
  • R18 含むなら: DLsite / FANZA / itch.io 成人向け (規約遵守)、Steam は所定の手順
  • 翻訳: Ren'Py 標準の翻訳機能 (.tl) + LLM で多言語化が現実的
  • ファンディスク文化: Patreon / Fantia でファン向け配信、無料体験版 + 有料本編

10. 次の話

EP.10 は プロシージャル生成 + LLM ── マップ・ダンジョン・クエストの動的生成。古典的なプロシージャルアルゴリズム (Wave Function Collapse / Cellular Automata) と LLM 連携の融合パターン。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp