Files
xiaochoupai/duihua.md
richarjiang 5590bbc897 perf: duihua
2026-09-21 14:46:05 +08:00

396 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 规划小丑牌 Web 游戏
> 如图所示,是 steam 中非常火爆的小丑牌游戏,我需要你仔细理解图片中的画风,然后为我开发一款基于 web 的小丑牌游戏, 重点是逻辑的搜索、理解和实现,UI 尽可能优美和有游戏的画风,最好使用 canvas 实现,如果你有能力的话,可以使用 cocos 来进行实现这个项目, 仔细理解我的需求,规划出来你的实现方案
>
> User context
>
> Images:
> - `/var/folders/19/fswt80ld441d8p2vm2qbh07m0000gn/T/codex-clipboard-a9050d3b-7783-453c-bea7-5439e4901400.jpg`
<details><summary>6 previous messages</summary>
> 我会先检查工作区规范,再查证小丑牌的核心规则与计分顺序,结合图片拆解画风,给你一份分阶段的实现方案。本轮先完成规划,不直接开始游戏开发。
>
> <details><summary>Explored a search, ran a command</summary>
>
> - Ran `pwd && rg --files -g 'AGENTS.md' -g 'CLAUDE.md' -g 'package.json' -g '!node_modules' -g '!Library' .; cat /Users/richard/.codex/RTK.md`
>
> <details><summary>Explored a file, a search</summary>
>
> - Searched for `xiaochoupai|小丑牌|Balatro` in `MEMORY.md`
> - Read `~/.agents/skills/frontend-design/SKILL.md`
>
> </details>
>
> </details>
>
> 目前工作区没有现成的项目规范或代码。我会先建立目录约定和方案文档,并使用 frontend-design 技能梳理视觉方向。技术上初步倾向 TypeScript + PixiJS:规则引擎可以独立验证,也适合实现图中的牌面倾斜、逐张计分和 CRT 质感。
>
> <details><summary>Ran 2 commands, searched the web</summary>
>
> Searched the web for `Balatro official game 150 jokers 8 antes poker roguelike ...`
>
> Searched the web for `site.pixijs.com 8 guides rendering canvas webgl webgpu ...`
>
> - Ran `rtk proxy ls -la`
>
> Searched the web for `https://www.playbalatro.com/faq`
>
> Searched the web for `https://balatrowiki.org/w/Poker_hands`
>
> - Ran `rtk git status --short`
>
> </details>
>
> 规则上的关键已经明确:牌型判定、哪些牌实际计分、效果触发顺序必须分开实现;“加倍率”和“乘倍率”交换位置,会改变最终得分。图片里的 10 张手牌、6 个小丑槽位也只能视为当局状态,不能直接写成默认值。
>
> 方案会先完成一局可通关、可失败、可续玩的完整流程,再扩充卡牌。部分规则页面无法访问,我会把尚未核实的数值单独标出来。
>
> <details><summary>Created 2 files, ran a command, searched the web</summary>
>
> Searched the web for `site.balatrogame.fandom.com/wiki/Poker_Hands "High Card" "Flush Five" "Two Pair" ...`
>
> - Wrote `./AGENTS.md` (+29 -0)
>
> - Wrote `./docs/implementation-plan.md` (+130 -0)
>
> - Ran `rtk git diff --check`
>
> </details>
</details>
我的建议是:**使用 TypeScript + PixiJS,以 Canvas 承载游戏画面;先实现可靠的规则引擎,再完成复古牌桌和完整对局。**
Cocos 可以实现,但目前目标是浏览器游戏,PixiJS 更直接。真正的难点是小丑效果组合、计分顺序和商店构筑,而不是选哪个引擎。
我已建立 [项目规范](./AGENTS.md) 和 [完整实现方案](./docs/implementation-plan.md),目前没有开始编写游戏代码。
**一、图片中的画风,应该如何还原**
这张图的特点不只是“像素风”,而是复古电子屏幕里的实体牌桌:
| 图片特征 | 实现方式 |
|---|---|
| 墨绿色桌面,大面积留白 | 缓慢流动的同色背景纹理,让注意力落在牌上 |
| 暖白纸牌、粗描边、硬阴影 | 统一牌面材质与像素插画,保留纸牌厚度 |
| 卡牌重叠、轻微歪斜 | 扇形排列、悬停抬升、选中上移、拖动重排 |
| 蓝色筹码、红色倍率、金黄奖励 | 颜色直接表达游戏含义 |
| 扫描线与旧显示器质感 | 轻量 CRT 后处理,可关闭,保证文字清晰 |
| 大数字和明显的操作反馈 | 逐张弹跳、倍率脉冲、分数滚动、递进音效 |
布局沿用图中的阅读顺序:**左侧状态、上方小丑、中间结算、下方手牌、右侧消耗品和牌堆。**
美术会制作成套牌面、小丑插画和牌背,不能仅用文字方框或 emoji 代替。截图中的模糊感不需要照搬,尤其中文说明必须清楚。
**二、核心玩法,需要做到什么程度**
官方规则确认的主循环是:通过出牌得分击败盲注,每个 Ante 包含小盲、大盲和 Boss,传统通关终点是 Ante 8 的特殊 Boss。[官方 FAQ](https://www.playbalatro.com/faq)
实际实现应形成完整循环:
**选择盲注 → 抽牌 → 出牌/弃牌 → 计分 → 过关奖励 → 商店构筑 → 下一关 → 胜利或失败。**
其中最重要的是三个区别:
- **打出的牌,不一定全部计分。** 牌型判定与计分牌集合必须分别计算。
- **“包含对子”和“牌型是对子”不同。** 小丑条件不能简单比较牌型名称。
- **效果顺序会改变结果。** 同一阶段先加倍率再乘倍率,与反过来不同;拖动小丑顺序必须真正影响结算。[社区触发顺序指南](https://balatrogame.fandom.com/wiki/Guide:_Activation_Sequence)
图片中的 10 张手牌、6 个小丑槽位只是当局状态,不能直接当作默认配置。
**三、技术结构:让规则可验证,让动画可信**
推荐技术栈为 **TypeScript + Vite + PixiJS 8**。这里使用的是 Canvas 画布中的 WebGL 渲染,适合卡牌变换和屏幕特效。[PixiJS 官方文档](https://pixijs.com/8.x/guides/components/application)
分成三层:
| 层级 | 职责 |
|---|---|
| 规则层 | 牌型、计分、效果、盲注、经济、随机数 |
| 对局层 | 操作校验、流程切换、商店交易、存档 |
| 表现层 | 卡牌绘制、拖拽、动画、提示、音效 |
**计分引擎先算出结果和每一步触发记录,画面再播放这些记录。** 这样加速动画、切换窗口或恢复存档,都不会改变得分或重复发奖。
另外,随机数要支持种子和状态保存,抽牌、商店、概率效果分别管理,方便复现问题。
Cocos 也支持 Web 发布,但当前没有现成场景或小游戏平台交付需求,引入编辑器和资源构建流程的收益有限。如果之后转向微信或抖音小游戏,可以复用独立规则模块,再重做表现层。[Cocos 官方文档](https://docs.cocos.com/creator/3.8/manual/en/editor/publish/publish-web.html)
**四、第一版建议范围**
第一版应当是一款能完整游玩的游戏,建议范围为:
- 1 个基础牌组、1 个难度、完整 8 Ante。
- 常规牌型及改牌后出现的特殊牌型,支持牌型升级。
- **24 张小丑**,覆盖筹码、加倍率、乘倍率、成长、经济和重触发。
- 6 种常规 Boss 机制、1 种终局机制。
- 行星牌、8 种塔罗、部分卡牌强化。
- 商店购买、出售、刷新、基础补充包和有限跳盲奖励。
- 新开局、失败重开、胜利结算、本地续局。
- 中文界面,桌面优先,兼容移动设备横屏。
这批内容要能形成不同的玩法,例如对子成长、花色触发、留手钢铁和经济转化。完整原作卡池、多难度、无尽模式和复杂复制效果留到后续。
**五、实施顺序与验收**
| 阶段 | 交付内容 | 验收重点 |
|---|---|---|
| 1. 规则冻结 | 规则表、卡池清单、手算案例 | 每个效果都有明确条件与触发时机 |
| 2. 逻辑引擎 | 牌型、计分、抽弃牌、商店、状态机 | 固定种子可复现,边界情况正确 |
| 3. 可玩切片 | 1 个 Ante、代表性小丑、商店、正式牌桌 | 完整循环可玩,能看懂得分来源 |
| 4. 完整首版 | 8 Ante、首批卡池、Boss、存档 | 胜利、失败、续局流程都跑通 |
| 5. 体验打磨 | 美术、音效、CRT、触控与性能 | 画面统一、操作准确、结算有节奏 |
测试重点放在容易破坏游戏的地方:倍率顺序、重触发范围、失效牌、重复购买、结算重复发奖、存档恢复和随机一致性。
本轮已查证主循环和关键触发顺序;部分社区规则页面无法完整访问,**基础数值、经济公式和特殊交互仍需在第一阶段逐项核实**,不会把未确认的细节直接写进代码。完整方案已将这些待办单独列出。
> 实现这个需求
<details><summary>25 previous messages</summary>
> 我会按方案开始实现:先建立可测试的规则引擎和完整对局流程,再接入 Canvas 牌桌、商店、卡牌动效与存档,最后运行构建和关键规则验证。
>
> <details><summary>Ran a command</summary>
>
> - Ran `rtk proxy sh -c 'cat AGENTS.md; cat docs/implementation-plan.md; ls -la; node -v; npm -v'`
>
> </details>
>
> 我会继续使用 frontend-design 的视觉规范,把界面做成复古印刷纸牌与墨绿牌桌的组合。首版采用独立绘制的卡面,并明确记录与原作不同的卡牌和 Boss 规则,保证每个可见按钮都有实际用途。
>
> <details><summary>Created 14 files, edited a file, ran 4 commands, searched the web</summary>
>
> - Ran `rtk proxy sh -c 'cat /Users/richard/.codex/RTK.md; cat /Users/richard/.agents/skills/frontend-design/SKILL.md; rg -n "xiaochoupai|小丑牌" /Users/richard/.codex/memories/MEMORY.md'`
>
> Searched the web for `site.balatrogame.fandom.com/wiki/Poker_Hands "Flush Five" "160" "Mult" ...`
>
> - Ran `rtk proxy npm view pixi.js version && rtk proxy npm view vite version`
>
> - Wrote `./.gitignore` (+5 -0)
> - Wrote `./AGENTS.md` (+1 -1)
> - Wrote `./docs/assets.md` (+6 -0)
> - Wrote `./docs/rules.md` (+44 -0)
> - Wrote `./index.html` (+2 -0)
> - Wrote `./package.json` (+6 -0)
> - Wrote `./tsconfig.json` (+1 -0)
>
> - Ran `rtk proxy npm install --no-audit --no-fund`
>
> - Ran `rtk proxy mkdir -p src/core src/content src/app src/render src/platform tests`
>
> - Wrote `./src/content/catalog.ts` (+54 -0)
> - Wrote `./src/core/poker.ts` (+30 -0)
> - Wrote `./src/core/random.ts` (+4 -0)
> - Wrote `./src/core/scoring.ts` (+58 -0)
> - Wrote `./src/core/types.ts` (+21 -0)
>
> - Wrote `./src/core/run.ts` (+94 -0)
> - Wrote `./src/platform/audio.ts` (+5 -0)
> - Wrote `./src/platform/storage.ts` (+24 -0)
>
> </details>
>
> 规则层已具备牌型识别、分阶段计分、24 张小丑、商店交易和可复现随机数。接下来会把这些结果接到牌桌上,特别处理“小丑顺序影响倍率”和“动画过程中刷新不重复结算”。依赖安装遇到当前 npm 镜像解析失败,我会切换官方源继续。
>
> <details><summary>Created 2 files, ran a command</summary>
>
> - Ran `rtk proxy npm install --registry=https://registry.npmjs.org --cache=/private/tmp/velvet-npm-cache --no-audit --no-fund`
> - Wrote `./src/render/art.ts` (+105 -0)
> - Wrote `./src/render/board.ts` (+87 -0)
>
> </details>
>
> 现在已完成独立卡面绘制和 Canvas 交互层:扑克、人头牌、小丑和消耗品都有实际纹理,支持手牌与小丑拖动排序。接下来补齐牌桌上的关卡选择、商店、结算提示和操作反馈,再用固定用例核对计分结果。
>
> <details><summary>Created 5 files, edited a file, ran 7 commands</summary>
>
> - Wrote `./src/app/main.ts` (+128 -0)
> - Wrote `./src/app/style.css` (+2 -0)
> - Ran `rtk proxy npm run build`
> - Wrote `./src/app/style.css` (+0 -1)
> - Wrote `./tests/core.test.ts` (+60 -0)
> - Ran `rtk proxy npm run build && rtk proxy npm test`
> - Ran `rtk proxy npm run dev -- --port 5173`
> - Ran `/bin/zsh -lc 'rtk proxy npm run dev -- --host 127.0.0.1 --port 5173'`
> - Ran `rtk proxy sh -c 'ls /Applications; ls /Users/richard/Library/Caches/ms-playwright 2>/dev/null'`
> - Wrote `./tests/browser.mjs` (+59 -0)
> - Wrote `./vite.config.ts` (+2 -0)
> - Ran `rtk proxy npm run build && rtk proxy npm test`
> - Ran `rtk proxy node tests/browser.mjs`
>
> </details>
>
> 构建已通过,76 个规则与状态测试也全部通过,涵盖倍率顺序、重触发、失效牌、交易原子性和存档恢复。现在正在真实浏览器里验证拖牌、出牌、商店购买和刷新续局,同时检查不同窗口尺寸下的画面。
>
> <details><summary>Edited 3 files, ran 4 commands</summary>
>
> - Ran `rtk proxy ls -lh artifacts`
> - Wrote `./tests/browser.mjs` (+3 -2)
> - Ran `rtk proxy node tests/browser.mjs`
> - Wrote `./index.html` (+1 -1)
> - Wrote `./src/app/main.ts` (+5 -1)
> - Wrote `./tests/browser.mjs` (+1 -1)
> - Ran `rtk proxy node tests/browser.mjs`
> - Ran `rtk proxy ls -lh artifacts`
>
> </details>
>
> Viewed an image
>
> Viewed an image
>
> <details><summary>Ran a command</summary>
>
> - Ran `rtk proxy ls -lh artifacts`
>
> </details>
>
> 浏览器验证已经跑通选牌、拖动、弃牌、计分和刷新续局。截图检查发现左侧状态栏在设计尺寸下偏高,我正在收紧布局;另外正在排查小丑排序后紧接着点击消耗品的交互,确保快速操作也可靠。
>
> <details><summary>Edited a file, ran 3 commands</summary>
>
> - Ran `rtk proxy python3 - <<'PY'
> p='src/app/style.css'
> s=open(p).read()
> s += '''
> /* Compact the sidebar so every control stays inside the table at the design size. */
> .blind-target{padding:14px 13px 10px}.blind-target strong{font-size:29px;margin:3px 0}.blind-note{padding:8px 0 10px;font-size:9px;min-height:34px}.score-panel{padding:14px 3px 11px}.score-panel>strong{font-size:35px;margin:8px 0 10px}.hand-panel{padding:14px 0 9px}.hand-title{font-size:20px;margin-bottom:10px}.hand-panel p{margin-top:8px}.equation>div{padding:7px 9px}.equation strong{font-size:29px}.counters>div{padding:7px 13px}.counters strong{font-size:26px}.wallet{padding:8px 14px;margin-top:10px}.wallet strong{font-size:32px}.rounds{margin-top:12px}.rounds strong{font-size:25px}.run-info{margin-top:12px;padding-top:11px}
> '''
> open(p,'w').write(s)
> PY`
> - Wrote `./tests/browser.mjs` (+4 -1)
> - Ran `rtk proxy node tests/browser.mjs`
> - Ran `rtk proxy ls -lh artifacts`
>
> </details>
>
> Viewed 2 images
>
> <details><summary>Created a file, edited 6 files, ran 2 commands</summary>
>
> - Wrote `./src/core/run.ts` (+2 -2)
> - Wrote `./src/platform/storage.ts` (+7 -4)
> - Wrote `./src/render/board.ts` (+5 -5)
> - Ran `rtk proxy npm install --save-dev --save-exact prettier@3.5.3 --registry=https://registry.npmjs.org --cache=/private/tmp/velvet-npm-cache --no-audit --no-fund`
> - Wrote `./.prettierrc.json` (+1 -0)
> - Wrote `./docs/rules.md` (+1 -1)
> - Wrote `./src/content/catalog.ts` (+1 -0)
> - Wrote `./src/core/run.ts` (+1 -1)
> - Wrote `./tests/core.test.ts` (+1 -1)
> - Ran `rtk proxy npm exec prettier -- --write src tests/core.test.ts tests/browser.mjs package.json tsconfig.json vite.config.ts index.html .prettierrc.json`
>
> </details>
>
> 关键浏览器流程已通过,包括小丑重排、消耗品使用、过关奖励、商店刷新、开包和跳盲,且没有页面脚本错误。界面溢出也已修复。接下来会补做正常规则下的固定种子对局检查,并整理启动说明、验收截图和已知限制。
>
> <details><summary>Created 2 files, edited 8 files, ran 6 commands</summary>
>
> - Wrote `./tests/balance.test.ts` (+58 -0)
> - Ran `rtk proxy npm exec vitest -- run tests/balance.test.ts`
> - Ran `rtk proxy sed -n '1,170p' src/core/run.ts; rtk proxy sed -n '1,90p' src/app/main.ts; rtk proxy cat src/platform/audio.ts; rtk proxy cat package.json`
> - Wrote `./docs/rules.md` (+1 -0)
> - Wrote `./package.json` (+3 -0)
> - Wrote `./src/app/main.ts` (+3 -3)
> - Wrote `./src/app/style.css` (+1 -1)
> - Wrote `./src/core/run.ts` (+8 -0)
> - Wrote `./src/platform/audio.ts` (+3 -2)
> - Wrote `./src/platform/storage.ts` (+6 -0)
> - Ran `rtk proxy python3 - <<'PY'
> p='src/app/main.ts'
> s=open(p).read().replace("localStorage.setItem('velvet-speed', String(speed))", "writeSetting('velvet-speed', String(speed))").replace("localStorage.setItem('velvet-crt', crt ? 'on' : 'off')", "writeSetting('velvet-crt', crt ? 'on' : 'off')").replace("p ? p.name : run.last?.name || '等待好牌'", "esc(p ? p.name : run.last?.name || '等待好牌')")
> open(p,'w').write(s)
> PY`
> - Wrote `./README.md` (+64 -0)
> - Wrote `./tests/core.test.ts` (+14 -0)
> - Ran `rtk proxy python3 - <<'PY'
> p='tests/browser.mjs'
> s=open(p).read().replace("executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',", "executablePath: process.env.CHROME_PATH || (process.platform === 'darwin' ? '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' : undefined),")
> open(p,'w').write(s)
> p='docs/implementation-plan.md';s=open(p).read().replace('状态:待用户确认;未开始游戏实现。','状态:用户已授权,首版已实现。实际规则及范围以 rules.md 为准,验收情况见 verification.md。').replace('对应牌型的行星、8 种塔罗','对应牌型的行星、9 种塔罗(新增女皇投放多倍强化)');open(p,'w').write(s)
> PY`
> - Ran `rtk proxy npm run format && rtk proxy npm run build && rtk proxy npm test`
> - Ran `rtk proxy node tests/browser.mjs`
>
> </details>
>
> Viewed an image
>
> <details><summary>Edited 2 files, ran a command</summary>
>
> - Wrote `./src/app/main.ts` (+1 -0)
> - Wrote `./src/core/run.ts` (+4 -0)
> - Ran `rtk git status --short`
>
> </details>
>
> 固定种子检查已完成:在不修改金钱、牌面或等级的正常规则下,16 局贪心策略对局中有 11 局通关、5 局失败,说明完整流程能正常胜败;这还不代表所有流派已经平衡。最后的浏览器复查暴露了界面更新与 Canvas 首帧之间的时序问题,我会修好后再交付。
>
> <details><summary>Edited 2 files, ran 9 commands</summary>
>
> - Ran `rtk proxy rg -n 'draw\(|private handCard|showPlayed' src/render/board.ts; rtk proxy sed -n '210,275p' src/render/board.ts; rtk proxy sed -n '1,120p' tests/browser.mjs`
>
> - Wrote `./src/render/board.ts` (+0 -0)
>
> - Ran `rtk proxy python3 - <<'PY'
> p='src/render/board.ts'
> s=open(p).read().replace(' }\n }\n private handCard(', ' }\n // Commit world transforms before exposing the newly rebuilt interactive scene.\n this.app.render();\n }\n private handCard(')
> open(p,'w').write(s)
> PY`
>
> - Ran `rtk proxy npm run format && rtk proxy npm run build && rtk proxy npm test`
>
> Tool call
>
> Tool: open_in_codex
> Status: completed
>
> - Ran `rtk proxy node tests/browser.mjs`
>
> - Ran `rtk proxy rg -n 'localStorage|hand-title|app.render' src/app/main.ts src/render/board.ts src/platform`
>
> - Wrote `./tests/browser.mjs` (+4 -0)
>
> - Ran `rtk proxy node tests/browser.mjs`
>
> - Ran `rtk proxy ls -lt artifacts`
>
> - Wrote `./src/render/board.ts` (+9 -1)
> - Wrote `./tests/browser.mjs` (+21 -1)
>
> - Ran `rtk proxy npm run format && rtk proxy npm run build && rtk proxy npm test`
>
> - Ran `rtk proxy node tests/browser.mjs`
>
> </details>
>
> 最终验收已通过:81 个测试、完整浏览器流程,以及模拟触屏的点击、长按和拖动都正常。游戏预览已启动,我正在保存最终验收记录;当前版本可完整游玩 8 个底注,并支持商店构筑、胜败结算和自动续局。
>
> <details><summary>Created a file, ran 2 commands</summary>
>
> - Wrote `./docs/verification.md` (+58 -0)
> - Ran `rtk proxy python3 - <<'PY'
> from pathlib import Path
> for name in ['startup-error.png','before-consumable.png','consumable-error.png','drag-error.png']:
> p=Path('artifacts')/name
> if p.exists(): p.unlink()
> PY`
> - Ran `rtk proxy npm run format:check && rtk git diff --check && rtk git status --short`
>
> </details>
</details>
已实现可玩的首版:**[打开天鹅绒小丑](http://127.0.0.1:5173/)**。
- Canvas / PixiJS 牌桌、原创卡面、拖拽排序、计分动效与音效。
- 24 张小丑、12 类牌型、9 种塔罗、完整 8 底注挑战。
- 商店、开包、牌型升级、Boss、胜败结算和自动存档。
- 构建与 **81 个测试通过**,浏览器及模拟触屏流程通过。
目前采用独立卡池与部分自定义规则;真实手机、Safari 和各流派平衡仍需进一步验收。
[启动说明](./README.md) · [验收记录](./docs/verification.md)
![游戏牌桌](./artifacts/playing.png)