opengame-agentic-game-creation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OpenGame: Agentic Web Game Creation

OpenGame:智能体驱动的网页游戏创作

Skill by ara.so — Daily 2026 Skills collection.
OpenGame is an open-source TypeScript framework that generates fully playable web games end-to-end from a single natural language prompt. It combines Game Skill (Template Skill + Debug Skill), an optional specialized GameCoder-27B LLM, and OpenGame-Bench for automated evaluation across Build Health, Visual Usability, and Intent Alignment.

ara.so 开发的 Skill — 属于 Daily 2026 Skills 系列。
OpenGame 是一个开源的 TypeScript 框架,可通过单个自然语言提示词端到端生成可直接游玩的网页游戏。它结合了Game Skill(模板技能 + 调试技能)、可选的专用GameCoder-27B大语言模型(LLM),以及用于在构建健康度、视觉可用性和意图匹配度三个维度进行自动化评估的OpenGame-Bench

What OpenGame Does

OpenGame 功能介绍

  • Takes a high-level game design prompt and produces a runnable browser game (HTML/JS/CSS)
  • Template Skill: Maintains a growing library of project skeletons to scaffold stable architectures
  • Debug Skill: Keeps a living protocol of verified fixes to repair cross-file integration errors systematically
  • OpenGame-Bench: Evaluates generated games via headless browser execution + VLM judging across 150 diverse prompts
  • Supports any OpenAI-compatible LLM backend (GPT-4o, Claude, GameCoder-27B, etc.)

  • 接收高层级的游戏设计提示词,生成可在浏览器中运行的游戏(HTML/JS/CSS)
  • 模板技能:维护一个不断扩充的项目骨架库,用于搭建稳定的架构
  • 调试技能:保留一份实时更新的已验证修复协议,系统性修复跨文件集成错误
  • OpenGame-Bench:通过无头浏览器执行 + 视觉语言模型(VLM)评判,针对150种不同提示词评估生成的游戏
  • 支持任何兼容OpenAI的LLM后端(GPT-4o、Claude、GameCoder-27B等)

Prerequisites

前置要求

  • Node.js >= 20.0.0
  • An OpenAI-compatible API key (or self-hosted GameCoder-27B endpoint)

  • Node.js >= 20.0.0
  • 兼容OpenAI的API密钥(或自托管的GameCoder-27B端点)

Installation

安装步骤

bash
undefined
bash
undefined

Clone the repository

Clone the repository

Install dependencies

Install dependencies

npm install
npm install

Copy and configure environment variables

Copy and configure environment variables

cp .env.example .env
undefined
cp .env.example .env
undefined

.env
Configuration

.env
配置

bash
undefined
bash
undefined

Required: LLM API credentials

Required: LLM API credentials

OPENAI_API_KEY=$OPENAI_API_KEY OPENAI_BASE_URL=https://api.openai.com/v1 # or your custom endpoint MODEL_NAME=gpt-4o # or gamecoder-27b, claude-3-5-sonnet, etc.
OPENAI_API_KEY=$OPENAI_API_KEY OPENAI_BASE_URL=https://api.openai.com/v1 # or your custom endpoint MODEL_NAME=gpt-4o # or gamecoder-27b, claude-3-5-sonnet, etc.

Optional: OpenGame-Bench VLM judging

Optional: OpenGame-Bench VLM judging

VLM_API_KEY=$VLM_API_KEY VLM_BASE_URL=https://api.openai.com/v1 VLM_MODEL_NAME=gpt-4o
VLM_API_KEY=$VLM_API_KEY VLM_BASE_URL=https://api.openai.com/v1 VLM_MODEL_NAME=gpt-4o

Optional: Output directory for generated games

Optional: Output directory for generated games

OUTPUT_DIR=./output
OUTPUT_DIR=./output

Optional: Max debug iterations

Optional: Max debug iterations

MAX_DEBUG_ITERATIONS=5

---
MAX_DEBUG_ITERATIONS=5

---

Key CLI Commands

核心CLI命令

bash
undefined
bash
undefined

Generate a game from a prompt

Generate a game from a prompt

npm run generate -- --prompt "Build a top-down shooter where a spaceship avoids asteroids"
npm run generate -- --prompt "Build a top-down shooter where a spaceship avoids asteroids"

Generate with a specific model

Generate with a specific model

npm run generate --
--prompt "Create a tower defense game with 3 enemy types"
--model gpt-4o
--output ./my-games
npm run generate --
--prompt "Create a tower defense game with 3 enemy types"
--model gpt-4o
--output ./my-games

Run OpenGame-Bench evaluation on a set of prompts

Run OpenGame-Bench evaluation on a set of prompts

npm run bench -- --prompts ./bench/prompts.json --output ./bench-results
npm run bench -- --prompts ./bench/prompts.json --output ./bench-results

Evaluate a single already-generated game directory

Evaluate a single already-generated game directory

npm run evaluate -- --game-dir ./output/my-game
npm run evaluate -- --game-dir ./output/my-game

Run the local dev server for a generated game

Run the local dev server for a generated game

npm run serve -- --game-dir ./output/my-game
npm run serve -- --game-dir ./output/my-game

List available template skeletons

List available template skeletons

npm run templates -- --list
npm run templates -- --list

Add a new template skeleton from an existing game directory

Add a new template skeleton from an existing game directory

npm run templates -- --add ./output/my-game --name platformer-base

---
npm run templates -- --add ./output/my-game --name platformer-base

---

Programmatic API

编程式API

Basic Game Generation

基础游戏生成

typescript
import { OpenGameAgent } from './src/agent';
import { GameSkill } from './src/skills/gameSkill';
import { TemplateSkill } from './src/skills/templateSkill';
import { DebugSkill } from './src/skills/debugSkill';

async function generateGame(prompt: string) {
  // Initialize skills
  const templateSkill = new TemplateSkill({
    libraryPath: './templates',
  });

  const debugSkill = new DebugSkill({
    protocolPath: './debug-protocol.json',
    maxIterations: 5,
  });

  const gameSkill = new GameSkill({ templateSkill, debugSkill });

  // Create and run the agent
  const agent = new OpenGameAgent({
    apiKey: process.env.OPENAI_API_KEY!,
    baseURL: process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1',
    model: process.env.MODEL_NAME ?? 'gpt-4o',
    gameSkill,
    outputDir: './output',
  });

  const result = await agent.generate({ prompt });

  console.log('Game generated at:', result.outputPath);
  console.log('Build status:', result.buildHealth);
  return result;
}

generateGame(
  'Make a Pac-Man style maze game with 3 levels, power-ups, and ghost AI'
).catch(console.error);
typescript
import { OpenGameAgent } from './src/agent';
import { GameSkill } from './src/skills/gameSkill';
import { TemplateSkill } from './src/skills/templateSkill';
import { DebugSkill } from './src/skills/debugSkill';

async function generateGame(prompt: string) {
  // Initialize skills
  const templateSkill = new TemplateSkill({
    libraryPath: './templates',
  });

  const debugSkill = new DebugSkill({
    protocolPath: './debug-protocol.json',
    maxIterations: 5,
  });

  const gameSkill = new GameSkill({ templateSkill, debugSkill });

  // Create and run the agent
  const agent = new OpenGameAgent({
    apiKey: process.env.OPENAI_API_KEY!,
    baseURL: process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1',
    model: process.env.MODEL_NAME ?? 'gpt-4o',
    gameSkill,
    outputDir: './output',
  });

  const result = await agent.generate({ prompt });

  console.log('Game generated at:', result.outputPath);
  console.log('Build status:', result.buildHealth);
  return result;
}

generateGame(
  'Make a Pac-Man style maze game with 3 levels, power-ups, and ghost AI'
).catch(console.error);

Using Template Skill Directly

直接使用模板技能

typescript
import { TemplateSkill } from './src/skills/templateSkill';

const templateSkill = new TemplateSkill({ libraryPath: './templates' });

// Find the best matching template for a game type
const template = await templateSkill.match({
  prompt: 'side-scrolling platformer with double jump',
  gameType: 'platformer',
});

console.log('Matched template:', template.name);
console.log('Skeleton files:', template.files);

// Scaffold a new project from a template
const scaffolded = await templateSkill.scaffold({
  template,
  outputDir: './output/my-platformer',
  context: { gameName: 'MyPlatformer', playerSpeed: 300 },
});

// Save a successful game as a new template for future use
await templateSkill.save({
  sourceDir: './output/successful-game',
  name: 'tower-defense-base',
  tags: ['tower-defense', 'wave-based', 'grid'],
});
typescript
import { TemplateSkill } from './src/skills/templateSkill';

const templateSkill = new TemplateSkill({ libraryPath: './templates' });

// Find the best matching template for a game type
const template = await templateSkill.match({
  prompt: 'side-scrolling platformer with double jump',
  gameType: 'platformer',
});

console.log('Matched template:', template.name);
console.log('Skeleton files:', template.files);

// Scaffold a new project from a template
const scaffolded = await templateSkill.scaffold({
  template,
  outputDir: './output/my-platformer',
  context: { gameName: 'MyPlatformer', playerSpeed: 300 },
});

// Save a successful game as a new template for future use
await templateSkill.save({
  sourceDir: './output/successful-game',
  name: 'tower-defense-base',
  tags: ['tower-defense', 'wave-based', 'grid'],
});

Using Debug Skill for Iterative Repair

使用调试技能进行迭代修复

typescript
import { DebugSkill } from './src/skills/debugSkill';
import { BuildRunner } from './src/build/runner';

const debugSkill = new DebugSkill({
  protocolPath: './debug-protocol.json',
  maxIterations: 5,
});

const buildRunner = new BuildRunner({ gameDir: './output/my-game' });

// Run the debug loop
const debugResult = await debugSkill.repair({
  gameDir: './output/my-game',
  buildRunner,
  onIteration: (iter, error, fix) => {
    console.log(`Iteration ${iter}: fixing "${error.message}" with "${fix.description}"`);
  },
});

if (debugResult.success) {
  console.log('Game repaired after', debugResult.iterations, 'iterations');
  // Protocol is automatically updated with the new verified fix
} else {
  console.log('Could not repair after max iterations:', debugResult.lastError);
}
typescript
import { DebugSkill } from './src/skills/debugSkill';
import { BuildRunner } from './src/build/runner';

const debugSkill = new DebugSkill({
  protocolPath: './debug-protocol.json',
  maxIterations: 5,
});

const buildRunner = new BuildRunner({ gameDir: './output/my-game' });

// Run the debug loop
const debugResult = await debugSkill.repair({
  gameDir: './output/my-game',
  buildRunner,
  onIteration: (iter, error, fix) => {
    console.log(`Iteration ${iter}: fixing "${error.message}" with "${fix.description}"`);
  },
});

if (debugResult.success) {
  console.log('Game repaired after', debugResult.iterations, 'iterations');
  // Protocol is automatically updated with the new verified fix
} else {
  console.log('Could not repair after max iterations:', debugResult.lastError);
}

OpenGame-Bench Evaluation

OpenGame-Bench 评估

typescript
import { OpenGameBench } from './src/bench/evaluator';

const bench = new OpenGameBench({
  vlmApiKey: process.env.VLM_API_KEY!,
  vlmBaseURL: process.env.VLM_BASE_URL ?? 'https://api.openai.com/v1',
  vlmModel: process.env.VLM_MODEL_NAME ?? 'gpt-4o',
  headlessBrowser: true,
});

// Evaluate a single game
const scores = await bench.evaluate({
  gameDir: './output/my-game',
  originalPrompt: 'Make a Pac-Man style maze game with 3 levels',
});

console.log('Build Health:     ', scores.buildHealth);      // 0–100
console.log('Visual Usability: ', scores.visualUsability);  // 0–100
console.log('Intent Alignment: ', scores.intentAlignment);  // 0–100
console.log('Overall:          ', scores.overall);

// Batch evaluation across multiple prompts
import promptsData from './bench/prompts.json';

const batchResults = await bench.evaluateBatch({
  prompts: promptsData,
  agent,                    // OpenGameAgent instance
  outputDir: './bench-results',
  concurrency: 4,
});

console.log('Mean Build Health:     ', batchResults.mean.buildHealth);
console.log('Mean Intent Alignment: ', batchResults.mean.intentAlignment);

typescript
import { OpenGameBench } from './src/bench/evaluator';

const bench = new OpenGameBench({
  vlmApiKey: process.env.VLM_API_KEY!,
  vlmBaseURL: process.env.VLM_BASE_URL ?? 'https://api.openai.com/v1',
  vlmModel: process.env.VLM_MODEL_NAME ?? 'gpt-4o',
  headlessBrowser: true,
});

// Evaluate a single game
const scores = await bench.evaluate({
  gameDir: './output/my-game',
  originalPrompt: 'Make a Pac-Man style maze game with 3 levels',
});

console.log('Build Health:     ', scores.buildHealth);      // 0–100
console.log('Visual Usability: ', scores.visualUsability);  // 0–100
console.log('Intent Alignment: ', scores.intentAlignment);  // 0–100
console.log('Overall:          ', scores.overall);

// Batch evaluation across multiple prompts
import promptsData from './bench/prompts.json';

const batchResults = await bench.evaluateBatch({
  prompts: promptsData,
  agent,                    // OpenGameAgent instance
  outputDir: './bench-results',
  concurrency: 4,
});

console.log('Mean Build Health:     ', batchResults.mean.buildHealth);
console.log('Mean Intent Alignment: ', batchResults.mean.intentAlignment);

Project Structure

项目结构

OpenGame/
├── src/
│   ├── agent/              # Core OpenGameAgent orchestration
│   ├── skills/
│   │   ├── gameSkill.ts    # Combines Template + Debug skills
│   │   ├── templateSkill.ts# Template library management & matching
│   │   └── debugSkill.ts   # Debug protocol & iterative repair
│   ├── build/
│   │   └── runner.ts       # Headless build execution & error capture
│   ├── bench/
│   │   └── evaluator.ts    # OpenGame-Bench scoring pipeline
│   └── llm/
│       └── client.ts       # OpenAI-compatible LLM client
├── templates/              # Template skeleton library (grows over time)
├── bench/
│   └── prompts.json        # 150 benchmark game prompts
├── output/                 # Generated games land here
├── debug-protocol.json     # Living verified-fix protocol
├── .env.example
└── package.json

OpenGame/
├── src/
│   ├── agent/              # Core OpenGameAgent orchestration
│   ├── skills/
│   │   ├── gameSkill.ts    # Combines Template + Debug skills
│   │   ├── templateSkill.ts# Template library management & matching
│   │   └── debugSkill.ts   # Debug protocol & iterative repair
│   ├── build/
│   │   └── runner.ts       # Headless build execution & error capture
│   ├── bench/
│   │   └── evaluator.ts    # OpenGame-Bench scoring pipeline
│   └── llm/
│       └── client.ts       # OpenAI-compatible LLM client
├── templates/              # Template skeleton library (grows over time)
├── bench/
│   └── prompts.json        # 150 benchmark game prompts
├── output/                 # Generated games land here
├── debug-protocol.json     # Living verified-fix protocol
├── .env.example
└── package.json

Common Patterns

常见模式

Full Pipeline: Prompt → Playable Game

完整流程:提示词 → 可游玩游戏

typescript
import { OpenGameAgent } from './src/agent';
import { GameSkill } from './src/skills/gameSkill';
import { TemplateSkill } from './src/skills/templateSkill';
import { DebugSkill } from './src/skills/debugSkill';
import { OpenGameBench } from './src/bench/evaluator';

async function fullPipeline(prompt: string) {
  const agent = new OpenGameAgent({
    apiKey: process.env.OPENAI_API_KEY!,
    baseURL: process.env.OPENAI_BASE_URL!,
    model: process.env.MODEL_NAME ?? 'gpt-4o',
    gameSkill: new GameSkill({
      templateSkill: new TemplateSkill({ libraryPath: './templates' }),
      debugSkill: new DebugSkill({
        protocolPath: './debug-protocol.json',
        maxIterations: 5,
      }),
    }),
    outputDir: './output',
  });

  // Step 1: Generate
  const result = await agent.generate({ prompt });
  console.log('Generated:', result.outputPath);

  // Step 2: Evaluate
  const bench = new OpenGameBench({
    vlmApiKey: process.env.VLM_API_KEY!,
    vlmModel: 'gpt-4o',
    headlessBrowser: true,
  });

  const scores = await bench.evaluate({
    gameDir: result.outputPath,
    originalPrompt: prompt,
  });

  console.log('Scores:', scores);

  // Step 3: If good quality, promote to template library
  if (scores.overall >= 80) {
    const templateSkill = new TemplateSkill({ libraryPath: './templates' });
    await templateSkill.save({
      sourceDir: result.outputPath,
      name: `auto-${Date.now()}`,
      tags: ['auto-promoted'],
    });
    console.log('Promoted to template library!');
  }

  return { result, scores };
}
typescript
import { OpenGameAgent } from './src/agent';
import { GameSkill } from './src/skills/gameSkill';
import { TemplateSkill } from './src/skills/templateSkill';
import { DebugSkill } from './src/skills/debugSkill';
import { OpenGameBench } from './src/bench/evaluator';

async function fullPipeline(prompt: string) {
  const agent = new OpenGameAgent({
    apiKey: process.env.OPENAI_API_KEY!,
    baseURL: process.env.OPENAI_BASE_URL!,
    model: process.env.MODEL_NAME ?? 'gpt-4o',
    gameSkill: new GameSkill({
      templateSkill: new TemplateSkill({ libraryPath: './templates' }),
      debugSkill: new DebugSkill({
        protocolPath: './debug-protocol.json',
        maxIterations: 5,
      }),
    }),
    outputDir: './output',
  });

  // Step 1: Generate
  const result = await agent.generate({ prompt });
  console.log('Generated:', result.outputPath);

  // Step 2: Evaluate
  const bench = new OpenGameBench({
    vlmApiKey: process.env.VLM_API_KEY!,
    vlmModel: 'gpt-4o',
    headlessBrowser: true,
  });

  const scores = await bench.evaluate({
    gameDir: result.outputPath,
    originalPrompt: prompt,
  });

  console.log('Scores:', scores);

  // Step 3: If good quality, promote to template library
  if (scores.overall >= 80) {
    const templateSkill = new TemplateSkill({ libraryPath: './templates' });
    await templateSkill.save({
      sourceDir: result.outputPath,
      name: `auto-${Date.now()}`,
      tags: ['auto-promoted'],
    });
    console.log('Promoted to template library!');
  }

  return { result, scores };
}

Custom LLM Endpoint (e.g., GameCoder-27B self-hosted)

自定义LLM端点(例如自托管的GameCoder-27B)

typescript
const agent = new OpenGameAgent({
  apiKey: process.env.GAMECODER_API_KEY!,
  baseURL: process.env.GAMECODER_BASE_URL!, // e.g. http://localhost:8000/v1
  model: 'gamecoder-27b',
  gameSkill,
  outputDir: './output',
});
typescript
const agent = new OpenGameAgent({
  apiKey: process.env.GAMECODER_API_KEY!,
  baseURL: process.env.GAMECODER_BASE_URL!, // e.g. http://localhost:8000/v1
  model: 'gamecoder-27b',
  gameSkill,
  outputDir: './output',
});

Loading Prompts from File and Batch Generating

从文件加载提示词并批量生成

typescript
import fs from 'fs/promises';

async function batchGenerate(promptsFile: string) {
  const prompts: string[] = JSON.parse(await fs.readFile(promptsFile, 'utf8'));

  for (const [i, prompt] of prompts.entries()) {
    console.log(`Generating ${i + 1}/${prompts.length}: ${prompt.slice(0, 60)}...`);
    try {
      const result = await agent.generate({ prompt });
      console.log('  ✅ Output:', result.outputPath);
    } catch (err) {
      console.error('  ❌ Failed:', err);
    }
  }
}

batchGenerate('./bench/prompts.json');

typescript
import fs from 'fs/promises';

async function batchGenerate(promptsFile: string) {
  const prompts: string[] = JSON.parse(await fs.readFile(promptsFile, 'utf8'));

  for (const [i, prompt] of prompts.entries()) {
    console.log(`Generating ${i + 1}/${prompts.length}: ${prompt.slice(0, 60)}...`);
    try {
      const result = await agent.generate({ prompt });
      console.log('  ✅ Output:', result.outputPath);
    } catch (err) {
      console.error('  ❌ Failed:', err);
    }
  }
}

batchGenerate('./bench/prompts.json');

Troubleshooting

故障排除

Build fails immediately with no output

构建立即失败且无输出

  • Ensure
    NODE_VERSION >= 20.0.0
    :
    node --version
  • Verify your API key and base URL are set correctly in
    .env
  • Check that
    OUTPUT_DIR
    exists and is writable
  • 确保
    NODE_VERSION >= 20.0.0
    :执行
    node --version
    检查
  • 验证
    .env
    文件中API密钥和基础URL设置正确
  • 检查
    OUTPUT_DIR
    目录是否存在且可写入

LLM returns incomplete or truncated code

LLM返回不完整或截断的代码

  • Increase the model's max token limit in your API settings or agent config
  • Switch to a larger/more capable model:
    MODEL_NAME=gpt-4o
    or
    gamecoder-27b
  • The Debug Skill will attempt iterative repair; raise
    MAX_DEBUG_ITERATIONS
    if needed
  • 在API设置或agent配置中增加模型的最大令牌限制
  • 切换到更强大的模型:
    MODEL_NAME=gpt-4o
    gamecoder-27b
  • 调试技能会尝试迭代修复;必要时提高
    MAX_DEBUG_ITERATIONS
    的值

Debug loop exhausted without success

调试循环耗尽仍未成功

  • Inspect
    debug-protocol.json
    — it may need a manual verified fix entry for a novel error pattern
  • Check
    ./output/<game>/build.log
    for the raw build errors
  • Reduce game complexity in the prompt and regenerate
  • 检查
    debug-protocol.json
    — 可能需要为新的错误模式手动添加已验证的修复条目
  • 查看
    ./output/<game>/build.log
    获取原始构建错误信息
  • 简化提示词中的游戏复杂度并重新生成

OpenGame-Bench headless browser errors

OpenGame-Bench无头浏览器错误

  • Ensure Chromium/Chrome is installed:
    npx playwright install chromium
  • For CI environments, set
    DISPLAY=:99
    or use a virtual framebuffer
  • 确保已安装Chromium/Chrome:执行
    npx playwright install chromium
  • 对于CI环境,设置
    DISPLAY=:99
    或使用虚拟帧缓冲区

Template matching returns wrong skeleton

模板匹配返回错误的骨架

  • Add a better-matched template:
    npm run templates -- --add ./output/good-example --name my-game-type
  • Templates are matched by semantic similarity to the prompt; more diverse templates improve accuracy
  • 添加更匹配的模板:执行
    npm run templates -- --add ./output/good-example --name my-game-type
  • 模板通过与提示词的语义相似度匹配;更多样化的模板可提高匹配准确性

Rate limits or API quota errors

速率限制或API配额错误

  • Add retry logic or use
    concurrency: 1
    in batch evaluation
  • For self-hosted GameCoder-27B, verify the vLLM/TGI server is healthy:
    curl $GAMECODER_BASE_URL/health

  • 添加重试逻辑,或在批量评估中设置
    concurrency: 1
  • 对于自托管的GameCoder-27B,验证vLLM/TGI服务器是否正常:执行
    curl $GAMECODER_BASE_URL/health

Benchmark: OpenGame-Bench

基准测试:OpenGame-Bench

OpenGame-Bench evaluates 150 diverse game prompts across three axes:
MetricDescription
Build HealthDoes the game compile and run without errors in a headless browser?
Visual UsabilityAre UI elements visible, legible, and interactable? (VLM-judged)
Intent AlignmentDoes the generated game match the original prompt's design intent? (VLM-judged)
bash
undefined
OpenGame-Bench针对150种不同的游戏提示词从三个维度进行评估:
指标描述
构建健康度游戏能否在无头浏览器中编译并无错误运行?
视觉可用性UI元素是否可见、清晰且可交互?(由VLM评判)
意图匹配度生成的游戏是否与原始提示词的设计意图相符?(由VLM评判)
bash
undefined

Run full benchmark (150 prompts)

Run full benchmark (150 prompts)

npm run bench --
--prompts ./bench/prompts.json
--output ./bench-results
--concurrency 4
npm run bench --
--prompts ./bench/prompts.json
--output ./bench-results
--concurrency 4

Results are saved to ./bench-results/summary.json

Results are saved to ./bench-results/summary.json


---

---

Resources

资源