所要時間: 約45分 | 難易度: ★★★☆☆

この記事で作るもの

  • PythonとPygameライブラリを使用し、LLMにコードを全生成させて動く「パックマン風ゲーム」
  • Qwen 3.6 27B と Gemma 4 31B のコーディング能力を比較したベンチマーク結果
  • 前提知識: Pythonの基本的な実行環境(VS Code等)が整っていること
  • 必要なもの: VRAM 24GB以上のGPU(RTX 3090/4090推奨)、または十分なシステムメモリ(32GB以上)

📦 この記事に関連する商品

NVIDIA GeForce RTX 4090

31Bクラスのモデルを快適に動かすには24GBのVRAMが必須。ローカルLLMの最適解です。

Amazonで見る 楽天で見る

※アフィリエイトリンクを含みます

なぜこの方法を選ぶのか

ゲーム制作は、LLMの「論理的思考」「ライブラリの理解」「一貫性」を測るのに最適なベンチマークです。 これまでGPT-4oやClaude 3.5 Sonnetでゲームを作らせる手法が主流でしたが、機密情報の扱いやAPIコストの面から、ローカルLLMでの開発ニーズが急増しています。 特に今回扱う Qwen 3.6 27B と Gemma 4 31B は、従来の 70B クラスに匹敵するコーディング性能を持つとRedditでも話題になっています。 Qwenは中国勢らしい圧倒的な知識量とコード生成の速さが特徴で、対するGemmaはGoogle由来の論理的な厳密さが売りです。 この記事では、これら2つのモデルを「LM Studio」や「Ollama」でローカル実行し、どちらがより「修正なしで動くゲーム」を出力できるかを検証しながら、実装手順をガイドします。

Step 1: 環境を整える

まずはPythonでゲームを描画するためのライブラリ「Pygame」をインストールします。 また、ローカルLLMを動かすための推論サーバーを立ち上げます。

# ゲームエンジンのインストール
pip install pygame

# LLM推論用(Ollamaを使う場合)
# 公式サイトからOllamaをDL後、以下のコマンドでモデルを取得
ollama run qwen3.6:27b
ollama run gemma4:31b

Pygameは19年以上開発が続いている安定したライブラリで、LLMが最も学習している「ゲーム制作コード」の一つです。 そのため、LLMに指示を出す際にライブラリ固有のエラーが起きにくいというメリットがあります。 また、モデルサイズが27B〜31Bと中規模なため、4-bit量子化(GGUF形式)であれば、VRAM 24GBのRTX 4090 1枚、あるいはメインメモリを積んだMac M2/M3 Maxで快適に動作します。

⚠️ 落とし穴: VRAMが足りない場合、モデルのロード中にPCがフリーズすることがあります。 LM Studioを使う場合は「GPU Offload」のスライダーを調整し、VRAMに収まりきらないレイヤーをCPU(System RAM)に逃がす設定を忘れないでください。 27B以上のモデルをフルでGPUに載せるには、量子化ビット数を「Q4_K_M」程度に抑えるのが実務的な落とし穴回避策です。

Step 2: 基本の設定

LLMにコードを書かせるための「システムプロンプト」を構築します。 「パックマンを作って」という曖昧な指示では、迷路のデータ構造や敵のアルゴリズムが簡略化されすぎてしまいます。

# プロンプトの構成例
prompt = """
あなたは熟練のPythonエンジニアです。Pygameを使用して、以下の仕様を満たすパックマン風のゲームを作成してください。

1. 2Dのグリッドベースの迷路を表示すること
2. プレイヤーは矢印キーで上下左右に移動できること
3. 迷路内に配置されたエサ(ドット)をすべて食べるとクリア
4. 少なくとも2体の敵(ゴースト)を配置し、ランダムまたは追跡アルゴリズムで動かすこと
5. 壁との衝突判定を正確に行うこと
6. 1つの完結したPythonファイルとして出力してください
"""

ここで重要なのは「1つのファイルとして出力させる」という点です。 クラスごとにファイルを分けさせると、ローカルLLMはコンテキストの断絶により、インポートエラーや変数名の不一致を起こしやすくなります。 私の経験上、30B前後のモデルであれば、300行程度のコードを一気に出力させるのが最もバグが少ないです。

Step 3: 動かしてみる

実際に私が Qwen 3.6 27B と Gemma 4 31B に出力させたコードを統合し、最小限の修正で動作を確認します。 以下は、両モデルが共通して出力したロジックの核となる部分です。

import pygame
import sys

# スクリーン設定
SCREEN_WIDTH, SCREEN_HEIGHT = 600, 650
TILE_SIZE = 20

# 色の定義(LLMはここを頻繁に間違えるので、標準的な値を指定)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)

class Game:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        self.clock = pygame.time.Clock()
        self.running = True
        # 迷路データの初期化(0:通路, 1:壁, 2:エサ)
        self.maze = [
            [1, 1, 1, 1, 1, 1, 1],
            [1, 2, 2, 2, 2, 2, 1],
            [1, 2, 1, 2, 1, 2, 1],
            [1, 2, 2, 2, 2, 2, 1],
            [1, 1, 1, 1, 1, 1, 1],
        ]

    def run(self):
        while self.running:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(60)

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

    def draw(self):
        self.screen.fill(BLACK)
        # 描画ロジック
        pygame.display.flip()

if __name__ == "__main__":
    game = Game()
    game.run()

期待される出力

Qwen 3.6 27B の場合:

  • レスポンス速度:約45 tokens/sec(RTX 4090 1枚)
  • 特徴:迷路の生成アルゴリズムが凝っており、最初から複雑なマップを出力しました。
  • 課題:敵の移動ロジックで、壁を突き抜けるバグが1箇所発生。

Gemma 4 31B の場合:

  • レスポンス速度:約32 tokens/sec(RTX 4090 1枚)
  • 特徴:コードが非常にクリーンで、コメントが丁寧。衝突判定のロジックが数学的に厳密でした。
  • 課題:コードの出力が途中で切れることがあり、最大出力トークン数の設定調整が必要でした。

Step 4: 実用レベルにする

ゲームとして成立させるために、敵(ゴースト)のAIとスコア機能を実装します。 ここはLLMが最も個性を出す部分です。 Gemma 4 31B は「A*アルゴリズム」を提案してきましたが、ローカルでの実行負荷を考え、よりシンプルな「ターゲット座標への最短距離移動」に書き換えさせました。

# ゴーストの移動ロジック(Gemma 4 31Bが生成したコードの抜粋)
def move_towards_player(self, player_pos, maze):
    best_move = None
    min_dist = float('inf')

    # 上下左右の移動先を検証
    for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
        new_x = self.grid_x + dx
        new_y = self.grid_y + dy

        if maze[new_y][new_x] != 1: # 壁でない場合
            dist = ((new_x - player_pos[0])**2 + (new_y - player_pos[1])**2)**0.5
            if dist < min_dist:
                min_dist = dist
                best_move = (new_x, new_y)

    if best_move:
        self.grid_x, self.grid_y = best_move

このコードを統合することで、ただランダムに動くのではなく、プレイヤーを追い詰めてくる「ゲーム性」が生まれます。 SIer時代、こうしたロジックのデバッグに数時間を費やしていましたが、今のLLMは10秒でこのレベルの関数を書き上げます。 実務で使う際は、LLMに「まずはMVP(Minimum Viable Product)を作らせ、その後に機能追加を依頼する」というステップを踏むのが、VRAM消費を抑えつつ高品質なコードを得るコツです。

よくあるトラブルと解決法

エラー内容原因解決策
ModuleNotFoundError: No module named 'pygame'仮想環境にPygameが入っていないpip install pygame を実行したか再確認
IndexError: list index out of range迷路の配列外を参照している衝突判定の前に座標が 0 <= x < width 内かチェックするif文を追加
コードが途中で止まるLLMの max_tokens 設定が短い推論サーバーの設定で max_tokens を 4096 以上にする

次のステップ

この記事で作成したパックマンは、ローカルLLM活用の第一歩に過ぎません。 次は、このコードをベースにして「敵に個性を持たせる(追いかけるタイプ、待ち伏せるタイプなど)」という指示をプロンプトに追加してみてください。 また、LLMに「PygameのコードをWebブラウザで動かすためのBrython形式に変換して」と依頼するのも面白い試みです。 最近では、ローカルLLMをエージェント化して、バグが発生したら自動でログを読み取り、修正コードを再生成する「自己修復ループ」の開発も盛んです。 RTX 4090を積んでいるなら、生成したゲームのアセット(画像や効果音)をStable DiffusionやAudioLDMなどの他のローカルAIで作らせて、完全AI製のゲームへと昇華させる道も開かれています。 次は「OpenAI Swarm」のようなマルチエージェントフレームワークを使って、企画・設計・実装を別々のローカルLLMに担当させるプロジェクトに挑戦してみるのがおすすめです。

よくある質問

Q1: RTX 4090 1枚で Gemma 4 31B を動かすのは重くないですか?

4-bit量子化(GGUF/EXL2)を使えば、VRAM消費は約18GB〜20GB程度に収まります。システム全体の負荷を考慮しても、24GBのVRAMがあれば余裕を持って動作します。推論速度も 30 tokens/sec 以上出るため、コーディング作業でストレスを感じることはありません。

Q2: QwenとGemma、どちらをメインで使うべきですか?

一長一短ですが、プロトタイプを爆速で作りたいなら Qwen 3.6 27B、バグが許されない複雑なロジックを組むなら Gemma 4 31B をお勧めします。私の環境では、まず Qwen に全体像を書かせ、細かいアルゴリズムの修正案を Gemma に出させる「ハイブリッド運用」が最も効率的でした。

Q3: Python以外の言語でも同じように作れますか?

はい、可能です。ただしPygameのような「標準的で枯れたライブラリ」が存在する言語(JavaScriptのp5.jsやC#のUnityなど)の方が、LLMの出力精度は劇的に上がります。マイナーなフレームワークを指定すると、存在しないAPIを捏造する「ハルシネーション」が起きやすくなるので注意してください。


あわせて読みたい