Googleのエージェント開発キット(ADK)で作る「RPGキャラ制作エージェント」


最近、AI界隈で注目を集めている「エージェント」という仕組みを使い、RPGのキャラクターを自動生成する「RPGキャラ制作エージェント」プログラムを作成してみました。

「まずキャラクター設定をじっくり練り上げ、その設定に基づいて一貫性のある画像を生成する」という流れを自動化したエージェントです。

今回はpyhonを使います。必要なパッケージをインストールします。


pip install google-adk google-genai

adk createコマンドでエージェントのプロジェクトを作成します。今回プロジェクト名はrpg_agentとします。


adk create rpg_agent

作成されたエージェントのプロジェクト構成は次のようになります。


rpg_agent/
    agent.py      # エージェントのメインコード
    .env          # APIキーまたはプロジェクトIDs
    __init__.py

.envファイルにAPIキーを追加します。


echo 'GOOGLE_API_KEY="あなたの取得したAPI Key"' > .env

agent.pyにエージェントのメインコードを記述します。

agent.py


import logging
from google import genai
from google.genai import types
from google.adk.agents import Agent
from google.adk.tools import ToolContext
from google.adk.tools.load_artifacts_tool import load_artifacts_tool
from google.genai.types import Part

# ログの設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 使用するモデルの定義
MODEL_ID = "gemini-2.5-flash-lite"
IMAGE_MODEL_ID = "gemini-2.5-flash-image"
# --- 1. Tools Definition ---

async def generate_full_illustration(tool_context: ToolContext, description: str) -> str:
    """RPGキャラクターの高品質な全身立ち絵を生成します。"""
    logger.info(f"⚡ Generating Full Illustration: {description[:30]}...")
    client = genai.Client()
    
    # 立ち絵用のプロンプト:整合性を保つため詳細な外見記述を含める
    prompt = (
        f"Full body portrait of an RPG character: {description}. "
        "Professional digital art, high fantasy, detailed costume design, "
        "vibrant colors, clean white background, masterpiece quality."
    )
    
    response = client.models.generate_images(
        model=IMAGE_MODEL_ID,
        prompt=prompt,
        config=types.GenerateImagesConfig(
            number_of_images=1, 
            output_mime_type='image/png',
            aspect_ratio="3:4" # 立ち絵に適した縦長比率
        )
    )
    
    image_bytes = response.generated_images[0].image.image_bytes
    filename = "full_illustration.png"
    await tool_context.save_artifact(filename=filename, artifact=Part.from_bytes(data=image_bytes, mime_type="image/png"))
    return f"Saved '{filename}'."

async def generate_pixel_sprite(tool_context: ToolContext, description: str) -> str:
    """
    アニメーション用のスプライトシートを生成します。
    各フレームのキャラクターサイズと頭身を厳密に統一します。
    """
    logger.info(f"⚡ Generating Unified Pixel Sprite Sheet: {description[:30]}...")
    client = genai.Client()
    
    # サイズと比率を固定するための強力な制約プロンプト
    prompt = (
        f"16-bit pixel art sprite sheet, RPG character: {description}. "
        "Strictly consistent character scale and height across all frames. " # サイズと高さを厳密に統一
        "Arranged in a perfectly aligned 3x4 grid pattern. " # 完璧に整列した3x4グリッド
        "Showing 12 identical-sized frames: walking animation for front, side, and back views. " # 12枚の同一サイズフレーム
        "Orthographic projection, uniform body proportions, " # 正投影図、均一な体型比率
        "isolated on a plain white background, clean pixel edges, retro game aesthetic."
    )
    
    response = client.models.generate_images(
        model=IMAGE_MODEL_ID,
        prompt=prompt,
        config=types.GenerateImagesConfig(
            number_of_images=1, 
            output_mime_type='image/png',
            aspect_ratio="1:1"
        )
    )
    
    image_bytes = response.generated_images[0].image.image_bytes
    filename = "pixel_sprite_sheet.png"
    await tool_context.save_artifact(filename=filename, artifact=Part.from_bytes(data=image_bytes, mime_type="image/png"))
    return f"Saved '{filename}' with consistent scaling."
    
# --- 2. Agent Definition (オーケストレーター) ---

root_agent = Agent(
    name="rpg_asset_designer",
    model=MODEL_ID,
    instruction=f"""
      あなたは伝説的なRPG制作に携わるシニアキャラクターデザイナーです。

      【デザインの重要ルール】
      ユーザーから与えられたキーワードからインスピレーションを膨らませ、魅力的なキャラクターを創造してください。
      **最優先事項として、立ち絵(イラスト)とスプライト(ドット絵)のキャラクターデザインが同一人物に見えるよう、外見的特徴(髪型、服装の色、武器、装飾品など)を具体的に定義してから生成プロセスに移ってください。**

      【実行プロセス】
      1. **キャラクター考案**: 名前、性格、そして詳細な「外見デザインガイド」を作成する。
      2. **共通プロンプトの作成**: イラストとドット絵の両方で使用する、一貫した外見説明文(Description)を生成する。
      3. **画像生成**: 
         - `generate_full_illustration`: 上記Descriptionを使用し、豪華な全身立ち絵を作成。
         - `generate_pixel_sprite`: 同じDescriptionを使用し、アニメーション用の複数フレームが含まれるスプライトシートを作成。
      4. **納品**: `load_artifacts_tool` で画像を読み込み、キャラクター設定と共に表示する。
      
      【最終回答の表示ルール】
      ### 🛡️ キャラクター設定: [名前]
      - **クラス/役割**: [職業など]
      - **性格**: [性格の要約]
      - **外見的特徴**: [生成に使用した共通のデザインポイント]

      ### 🎨 全身イラスト
      ![Full Illustration](full_illustration.png)
      
      ### 👾 アニメーション用スプライトシート
      ![Pixel Sprite](pixel_sprite_sheet.png)
    """,
    tools=[generate_full_illustration, generate_pixel_sprite, load_artifacts_tool],
)

次のコマンドでWebインターフェースを開始します。


adk web --port 8000

ブラウザ(http://localhost:8000)を開きます。開いた画面の左上でrpg_agentを選択します。

右のチャット画面で作成したいキャラクタについて説明を入力してください。


🛠️ この「エージェント」の仕組み

このエージェントは、バックグラウンドで以下の3つのステップを瞬時に実行しています。

  1. キャラクターの「設定」を構築する
    「炎の騎士」というお題に対し、名前・性格・装備の詳細といった「言葉の設計図」をまず書き上げます。
  2. 「豪華な立ち絵」の生成
    作成した設計図をもとに、ゲームのパッケージに使われるようなハイクオリティな全身イラストを描画します。
  3. 「ゲーム用ドット絵」の生成
    同じ設計図を参照し、ゲーム画面で動かすための「ドット絵(スプライト)」を生成。立ち絵とのデザインのズレを最小限に抑えます。

🎨 出力イメージ

例えば「炎の騎士」と一言入力するだけで、次のような結果が返ってきます。

承知いたしました。「炎の騎士」をテーマに、RPGキャラクターをデザインします。

まず、キャラクターの具体的な外見デザインを定義します。イラストとドット絵で一貫性を持たせるため、以下の共通設定を設けます。

  • 名前:焔(ホムラ)
  • クラス/役割:炎の騎士(フレイムナイト)
  • 性格:燃えるような情熱と、内に秘めた静かなる決意を持つ。仲間を守るためなら、どんな困難にも立ち向かう勇敢さを持つ。
  • 外見デザインガイド
    • :燃え盛る炎のような赤みがかったオレンジ色のショートヘア。顔にかかる前髪は少し長め。
    • :鋭い意志を感じさせる燃えるような赤色。
    • 服装
      • 上半身:黒を基調とし、肩や胸部に赤と金の装飾が施された重厚なプレートアーマー。アーマーの一部(特に肩当てや胸当て)から、常に小さな炎が揺らめいているように見えるエフェクト。
      • 下半身:黒の革パンツと、赤のラインが入ったブーツ。
      • マント:炎のような赤とオレンジのグラデーションがかかった、軽やかなマント。風になびくと炎のように見える。
    • 武器:大剣。刀身は黒く、柄の部分に赤い宝石が埋め込まれている。振るうと炎を纏う。
    • 装飾品:首元に炎を模したペンダント。
    • 全体的な雰囲気:炎の力を宿し、力強くもどこか儚げな印象。

この設定に基づき、共通のプロンプトを作成し、イラストとスプライトを生成します。少々お待ちください。


炎の騎士 焔 イラスト

炎の騎士 焔 ドット絵

まとめ

今回は、キャラクター設定から立ち絵、スプライト画像までをワンストップで生成するシンプルなエージェントを作成しました。

ADKの強みは拡張性です。さらに機能を加えたい場合、「背景」や「モンスター」の生成担当、さらには「セリフ」や「シナリオ」を執筆する担当など、複数の専門エージェントを連携させることも容易に可能です。

今後、より複雑なAIエージェントシステムを構築する際、ADKは開発効率を高めてくれるツールになりそうです。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください