使用 Claude Fable 5 一次性打造 Raccoon Heist 游戏
摘要
Simon Willison 演示了如何通过 Claude Code for web 使用 Claude Fable 5,根据一条 2022 年的 GPT-3/DALL-E 推文,构建一个可玩的 3D Raccoon Heist 游戏,并利用 GitHub Pages 进行实时预览。
暂无内容
查看缓存全文
缓存时间: 2026/08/05 21:44
# 用 Claude Fable 5 一把梭出《浣熊大劫案》游戏
来源:https://simonwillison.net/2026/Aug/5/raccoon-heist/
2026年8月5日
早在2024年,我发过一条推文(https://twitter.com/simonw/status/1555626060384911360)晒出用 GPT-3 生成的一个游戏概念截图,以及用 DALL-E 创作的“概念艺术”。今天,正好是那条推文四周年纪念日,我决定看看 Claude Fable 5(运行在Claude Code for web(https://code.claude.com/docs/en/claude-code-on-the-web)里)能不能仅凭那条推文的内容,把整个游戏做出来。结果它干得还真不错!
你可以在这里玩这个游戏(https://simonw.github.io/raccoon-heist/)。这是GitHub 仓库(https://github.com/simonw/raccoon-heist/),还有一段简短视频演示:
你的浏览器不支持 HTML5 视频。
#### 我是怎么做的
这是2022年8月5日那条推文(https://twitter.com/simonw/status/1555626060384911360):
Simon Willison @simonw - 新爱好:用 GPT-3 和 DALL-E 组合,60 秒快速原型一个电子游戏。这是「Raccoon Heist」。两张图——第一张是 GPT-3 playground 的截图,提示词如下。右边是一张明显由 DALL-E 生成的图片,展示了一个近乎等距视角的 3D 电脑游戏,两只浣熊正沿街道悄悄路过一栋未来感建筑,看起来想偷点什么东西。
当时我的 GPT-3 提示词是:
> `为一款以浣熊团队实施劫案为主题的电脑游戏撰写一份详细的产品描述。`
那还是“文本补全”的时代,你需要让 GPT-3 补全剩下的文本。它补全的内容是:
> 在《Raccoon Heist》中,你和你的浣熊盗贼团队的任务是完成一系列惊险刺激的劫案。从抢劫银行到窃取无价艺术品,无论工作大小,你的毛茸茸团队都能胜任。你需要运用智慧和技巧躲避警察,带着赃物全身而退。凭借激动人心的玩法和一群迷人的角色,《Raccoon Heist》是任何寻求轻松诙谐冒险游戏的人的完美之选。
我给 DALL-E 的提示词很短:
> `一款浣熊团队实施劫案的电子游戏截图`
今天的实验是:我能不能把这些截图丢给 Fable 5,附上一条提示词叫它写个游戏,然后完全放手不管,最后得到一个能玩的游戏?
#### 设置 Claude Code for web 以使用 GitHub Pages
Claude Code for web 一个让人头疼的地方是,当它还在工作时,你很难实时预览它正在做的东西。
我一直在用 GitHub Pages 来解决这个限制,效果非常好。
我的流程如下:
1. 在https://github.com/new 创建一个新仓库——可以是公开或私有,这个技巧两者都适用。
2. 在 Claude iPhone 或桌面应用中,或浏览器访问 https://claude.ai/code 启动一个 Claude Code for web 会话。
3. 告诉 Claude 要做什么,并鼓励它尽快提交一个 `index.html` 页面。这会产生一个类似 `claude/3d-raccoon-heist-game-50n293` 的分支名称。
4. 进入仓库的 Settings -> Pages 区域(我的情况是 `github.com/simonw/raccoon-heist/settings/pages`),选择“Deploy from a branch”,选择分支名,然后点 Save。
就这么简单!每次 push 后大约 30 秒内,最新内容就会出现在 `yourname.github.io/your-repo/`。
如果你用私有仓库这样做,任何能猜到仓库名的人都能看到发布的内容。我个人不太担心这个问题。
#### Fable 5 的提示词
以下是我给 Fable 5 的提示词(写在手机备忘录里——整个项目都是在手机上完成的)。我附上了原始推文中的两张图片。
> `帮我构建这个 3D 游戏,运行在浏览器中。`
> `这个仓库配置为服务静态文件,所以确保有一个 index.html 加载所有其他内容。`
> `确保它在移动端表现良好(触控操作,在小屏幕上也能正常运行)。`
> `你有一个 OpenAI API 密钥,可以调用他们的图像生成模型 API,用来为你的 3D 模型生成纹理。文档在这里:https://developers.openai.com/api/docs/guides/image-generation - 使用 gpt-image-2`
> `独立工作——不要让我做任何进一步的设计决策。确保游戏有趣、有点惊喜、有良好的浣熊劫案氛围,并且视觉上令人愉悦。`
> `尽可能频繁地提交并推送,这样我就能预览你的成果——先从一个展示标题画面的 index.html 开始,然后逐步构建。`
> `工作时在 notes.md 文件中追加记录,并将该文件的更改包含在每次提交中。`
我没有指定任何技术选型。我(正确地)猜测它可能会基于之前的实验使用Three.js(https://threejs.org/)。
给 Claude 一个 OpenAI 密钥,用来弥补其能力上的空白,效果出奇地好——在本例中,我们需要某种方式生成用作纹理的图像。Fable 很擅长给图像生成器写提示词!
我说“独立工作——不要让我做任何进一步的设计决策”,是因为我想看看它能否在没有我任何进一步输入的情况下,产出一个完整、可玩的游戏。
我还说了“尽可能频繁地提交并推送,这样我就能预览你的成果”。当你在 Claude iPhone 应用中使用 Claude Code 时,给它一个 GitHub 仓库,它会在某个分支里工作。告诉它“尽可能频繁地推送”,就意味着提交会立刻开始落到那个分支上。
我喜欢要求 `notes.md` 作为一点额外风味——这是完成的文件(https://github.com/simonw/raccoon-heist/blob/main/notes.md),以及它加入那条狗时写的记录:
> 新的升级:从第三夜开始,院子里会有一只巡逻的护卫犬——一只低多边形棕色猎犬,戴着红色尖刺项圈,尾巴摇来摇去。它在随机地点之间游荡,如果浣熊进入 12 个单位以内,它会嗅到你的气味并追踪你(视线无关紧要——全靠鼻子,头顶会显示一只👃并吠叫)。如果你拉开 17 个单位的距离,它就会放弃。被抓到的消息现在按来源区分:守卫 / 车灯 / 猎犬。已验证 游荡 → 追踪 → 被抓 的流程,并配有自动化测试。
#### 回顾对话记录
你可以访问这个Claude Code 共享会话(https://claude.ai/code/session_01NUBoCfnhGETcCDyEUPS8jp),我还用了我的claude-code-transcripts(https://github.com/simonw/claude-code-transcripts)工具导出了我自己的 HTML 版本,你可以在找到它(https://simonw.github.io/raccoon-heist/transcript/page-001.html)。
Fable 从一个 index 页面开始,将 Three.js 的副本(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T14-55-13-304Z)收入本地,然后撰写了自己的gen_textures.py 脚本(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T14-55-49-064Z)(副本在此(https://github.com/simonw/raccoon-heist/blob/main/gen_textures.py))。
它生成了纹理并抽查(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T14-59-07-900Z)以确保看起来没问题。它为垃圾桶生成的metal.jpg 文件(https://github.com/simonw/raccoon-heist/blob/main/textures/metal.jpg)看起来像这样,不过我觉得它在游戏里似乎没有被完全正确地贴上去:
一个深蓝灰色铆接金属面板的游戏纹理图集,左上方显示一个带有把手的圆形舱门,中间是带棱纹的波纹板,左下方是一块普通的圆形板,顶部和底部是扁平条带。没有可见文字。
接着它构建了游戏的第一版基础框架,然后决定用 Playwright 在“预装 Chromium”中进行冒烟测试(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-04-51-625Z)。这意味着它可以给自己的作品截图并亲眼检查(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-05-53-823Z)。它分别以桌面和移动页面宽度做了这件事,随后注意到在移动端宽度下浣熊是隐形的(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-09-33-406Z),于是修复了这个问题(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-14-39-180Z):
> 浣熊、垃圾箱藏身处和两只同伙浣熊现在在移动端上完全可见。提交此关键修复。
它决定生成一个标题画面,使用这个 gen_title.py(https://github.com/simonw/raccoon-heist/blob/main/gen_title.py)脚本完成了(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-15-02-574Z)。这是它使用的 `gpt-image-2` 提示词:
> `游戏主视觉,低多边形 3D 渲染风格,昏暗夜间场景:一只可爱的低多边形浣熊戴着黑色小飞贼面罩,踮着后脚偷偷摸摸地叼着一枚发光的金币,旁边是一个被推倒的金属垃圾桶,背景是郊区房屋,窗户透出温暖的灯光,深蓝色夜晚,满月,萤火虫,电影感轮廓光,迷人的劫案冒险氛围。没有文字,没有单词,没有 logo。`
以及生成的图像(Claude 觉得它“美极了”(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-16-42-176Z))——不过我注意到,在桌面端显示时它会被裁剪到只剩上面三分之一,根本看不到浣熊!
多边形风格的浣熊叼着一枚金币,旁边是一个被推倒的垃圾桶,背景里有房屋和月亮。
然后是我最喜欢的改动:它加入了那条狗(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-23-00-850Z):
``
export function makeDog() {
const g = new THREE.Group();
const BROWN = 0x8a6440, DARK = 0x5e4128;
const body = new THREE.Mesh(new THREE.SphereGeometry(0.42, 10, 8), M(BROWN));
body.scale.set(0.9, 0.8, 1.5);
body.position.y = 0.55;
body.castShadow = true;
g.add(body);
const head = new THREE.Mesh(new THREE.SphereGeometry(0.3, 10, 8), M(BROWN));
head.position.set(0, 0.85, 0.62);
g.add(head);
const snout = new THREE.Mesh(new THREE.SphereGeometry(0.16, 8, 6), M(DARK));
snout.scale.set(0.9, 0.7, 1.3);
snout.position.set(0, 0.76, 0.9);
g.add(snout);
const nose = new THREE.Mesh(new THREE.SphereGeometry(0.06, 6, 6), M(BLACK));
nose.position.set(0, 0.78, 1.08);
g.add(nose);
for (const s of [-1, 1]) {
const ear = new THREE.Mesh(new THREE.SphereGeometry(0.12, 6, 6), M(DARK));
ear.scale.set(0.7, 1.3, 0.5);
ear.position.set(0.2 * s, 1.08, 0.55);
g.add(ear);
const eye = new THREE.Mesh(new THREE.SphereGeometry(0.05, 6, 6), M(0x1a1a1a, { emissive: 0x331111 }));
eye.position.set(0.13 * s, 0.92, 0.86);
g.add(eye);
}
const tail = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.09, 0.5, 6), M(DARK));
tail.position.set(0, 0.8, -0.62);
tail.rotation.x = 0.8;
g.add(tail);
// spiked collar
const collar = new THREE.Mesh(new THREE.TorusGeometry(0.22, 0.05, 6, 12), M(0xc0392b));
collar.position.set(0, 0.78, 0.5);
collar.rotation.x = Math.PI / 2.4;
g.add(collar);
const legGeo = new THREE.CylinderGeometry(0.07, 0.09, 0.34, 6);
const legs = [];
for (const [x, z] of [[-0.22, 0.35], [0.22, 0.35], [-0.22, -0.35], [0.22, -0.35]]) {
const leg = new THREE.Mesh(legGeo, M(DARK));
leg.position.set(x, 0.17, z);
g.add(leg);
legs.push(leg);
}
let phase = Math.random() * 10;
return {
group: g,
animate(dt, speed) {
phase += dt * (3 + speed * 10);
const amp = Math.min(0.6, 0.1 + speed * 0.6);
legs[0].rotation.x = Math.sin(phase) * amp;
legs[3].rotation.x = Math.sin(phase) * amp;
legs[1].rotation.x = -Math.sin(phase) * amp;
legs[2].rotation.x = -Math.sin(phase) * amp;
tail.rotation.z = Math.sin(phase * 1.5) * 0.4;
body.position.y = 0.55 + Math.abs(Math.sin(phase)) * 0.04 * (0.3 + speed);
},
};
}
``
然后它用 Playwright 对它做了一轮测试(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-24-09-230Z),还另外截图(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-24-33-559Z)确认效果。
``
// walk near the dog
await page.evaluate(() => { const d = window.__rh.dog; window.__rh.teleport(d.x + 6, d.z); });
await page.waitForTimeout(2000);
info = await page.evaluate(() => JSON.stringify({ dog: window.__rh.dog, state: window.__rh.state, player: window.__rh.debug().player }));
console.log('after approach:', info);
await page.waitForTimeout(3000);
info = await page.evaluate(() => JSON.stringify({ dog: window.__rh.dog, state: window.__rh.state }));
console.log('after chase:', info);
await page.screenshot({ path: __dirname + '/shot-dog.png' });
``
游戏截图。第三夜,浣熊在画面中央与狗重叠。一条消息写着“被抓住了!守卫把你赶走了!”屏幕边缘泛着红色。
它又做了一些调整,然后宣布自己完成(https://simonw.github.io/raccoon-heist/transcript/page-001.html#msg-2026-08-05T15-29-13-245Z):
> **Raccoon Heist 已构建、测试并推送**——分支 `claude/3d-raccoon-heist-game-50n293` 上有 7 次提交,均通过自动化 Playwright 试玩验证,覆盖桌面、竖屏手机和横屏手机视口。**游戏内容:**你是一只戴着面罩的浣熊,从你的团队藏身的垃圾箱悄悄溜出来,进入月光下的死胡同。收集金币、宝石、戒指、甜甜圈和鱼(它们会明显堆叠在你背上并让你减速),然后在黎明前蹒跚回家并把它们存入银行。每夜都会提高目标和危险程度:第一晚有一个扫视手电筒的守卫,第二晚有两个,第三晚新增一只完全无视视线的嗅迹猎犬。一辆警车用车灯扫过街道,房主会随机从窗户探头,海鸥会不时俯冲轰炸你尚未领取的战利品,披萨片会触发 6 秒速度 FRENZY,还有一台罕见的金色电视,如果你能把它搬回家,价值 120 分。胜利等级:TRASH PANDA ⭐ → CAT BURGLAR ⭐⭐ → MASTER OF DISGUISE ⭐⭐⭐,你的最佳成绩会保存在 localStorage 中。**构建方式:**引入本地 Three.js(无 CDN)、程序化低多边形角色,以及程序化 WebAudio 配乐(充满狡黠氛围的走低音爵士乐外加全部音效——零音频文件)。全部七张地面/墙壁纹理和标题画面主视觉均由 gpt-image-2 生成并作为静态资源提交,因此部署后的游戏不会产生任何 API 调用。移动端有动态触摸摇杆(触摸任意位置出现)外加 DASH 按钮;桌面端使用 WASD/方向键和空格。**测试发现了两个值得一提的真实 bug:**画布在任何真实手机上都会以 2 倍尺寸渲染(一次 `cssText` 赋值覆盖了 Three.js 的内联尺寸——桌面 DPR-1 测试完全掩盖了这个问题),以及胜利画面上的星级评分 div 继承了标题画面的全屏 `.stars` CSS,默默吞掉了“next night”按钮上的每一次点击。这两个问题都已修复并进行了回归测试,同时覆盖拾取、存入、追逐/被抓、黎明、夜晚推进以及失败/重试流程。`notes.md` 里有完整的构建日志。游戏已上线分支——只需服务仓库根目录并打开 `index.html` 即可。
#### 这游戏好玩吗?
它是一个令人印象深刻的起点,但它不是一款*好*游戏。
你操控浣熊在院子里走动收集物品——甜甜圈、鱼、金币、珠宝——同时要躲避拿着手电筒的守卫,以及后面关卡中的狗。你有有限的负重,一旦装满就需要去垃圾箱那里卸货。如果你捡起一块披萨片,会获得临时加速。
完全没有团队机制——垃圾箱旁边有另外两只静止不动的浣熊,但它们纯粹是装饰。
随着关卡推进,难度会稍微提升——第三关引入的狗是最有趣的新机制——但还是非常非常容易通关。而且也挺无聊的——每夜有固定的时长,而(文章截断)
相似文章
Moonlight & Mayhem (Raccoon Heist by Codex + GPT-5.6 Sol Ultra)
Simon Willison 通过 Codex Desktop 测试 GPT-5.6 Sol Ultra,要求其根据一个四年前的提示重新制作“Raccoon Heist”游戏,结果比 Claude Fable 5 的版本好得多,但存在眼球过大的 bug。
结束了。Claude Fable 5 恐怖游戏直播一次通关
Claude(Anthropic 的 AI 模型)在直播演示中一次通关了恐怖游戏。
@rork: 介绍 Rork Games × Claude Fable 5 — Rork 现在可以一键生成 3D 和 2D 游戏,让你与朋友在线联机,甚至《堡垒之夜》…
由 Claude Fable 5 驱动的 Rork Games 现已能够生成完整的 3D 和 2D 游戏,支持与朋友在线联机,并且可以从文本和照片生成游戏资源。
@PrajwalTomar_: Claude Fable 5 刚刚发布,所有人都在争相自主运行它。Claude Code的创建者已经展示了…
Claude Fable 5 已发布,支持通过子代理、钩子和持久内存实现自主操作,基于一年前 Claude Code 展示的基础之上。
Claude 5 Opus 与 3D 月光场景
一位开发者分享了 Claude 5 Opus 如何从零生成一个详细的 3D 月光场景,编写了超过 944KB 的 JavaScript,并计划将其改造成一款射击游戏。