这是《游戏设计》三卷本的第一卷。它回答一个问题:一份玩法设计文档,能不能本身就是原型,而且它的性质可以被证明?
站内的游戏内容基本落在两端:一端是机制怎么实现(
game/专题与《游戏引擎实现原理》各卷),一端是产品怎么立项、怎么变现(game/industry/与《小游戏开发实战》卷一)。中间那一段——机制跑起来会涌现出什么(Dynamics)、玩家因此体验到什么(Aesthetics)——没有人占。 而这一段恰恰是可计算、可跑、可证明的一段。这一卷补的就是这一段的地基。做法只有一句话:一份玩法规格,四处消费。
config/play_spec.json是唯一真源(动词 / 规则 / 状态 / 资源 / 目标 / 反馈 / 难度参数 / 随机性结构),它同时驱动四处——S 层 Python 机制仿真、P 层 TypeScript 确定性内核、W 层浏览器可玩原型、B 层参数扰动与相变扫描。四处读的是同一个文件,产出的是逐字相同的摘要。改一个规则参数,四处同步改变且仍然互相一致。贯穿全书的是虚构的卡牌构筑 Roguelike 《灰烬牌库》(工程名
ashdeck)与同名工具链:config/放规格,sim/是 Python 仿真,core/是 TypeScript 确定性内核,web/把内核内联进单文件 HTML 供无头浏览器真玩。
这套书与站内既有内容的分工
站内已经有大量相邻内容,写清分工比重复写一遍更有价值。下面七处边界是本卷最容易混淆的,务必分清:
- 《小游戏开发实战》卷一《市场品类与产品设计》 是产品口径:品类选择、用户动机、立项预算、变现前置。本卷是机制口径:把玩法写成可执行规格并证明其性质。它那一卷有 7 个点最像本卷,逐个划清:① 核心循环拆解 用 S 层算循环时长占比,本卷第 3 章算的是守恒与不变量;② 循环时长与反馈 讲时长与反馈的经验关系,本卷第 7 章给回路增益的可算模型;③ 最小可玩原型 是原型的产品口径,本卷第 5 章是规格内联 + 无头真玩的工程做法;④ 难度-心流曲线 是 S 层心流模型 + B 层难度敏感性,本卷第 6 章是相变 / 序参量,并把心流写成带宽(区间而非单点);⑤ 可玩性指标测试 是 S 层模拟采样 + 置信区间、指标偏占比类,本卷(与卷二)给的是策略熵 / 支配缺失度 / 涌现度等机制量;⑥ 设计文档装配 是产品立项文档的装配与评审,本卷第 16 章是可执行规格的四处消费联调;⑦ 交付物验收与交接 是交付物验收,本卷卷三做的是六品类变体的机制闸门回归。
game/indie/的四篇长文是散文式 + Unitycsharp片段、不可跑:核心循环与手感设计 (约 690 行)讲手感参数体系,本卷把机制形式化为规格字段、把「手感」变成可断言的输入-反馈机制;关卡设计与环境叙事 (约 940 行)讲空间引导与难度曲线,本卷把跳跃机制可算化;平衡与经济 (约 1430 行)是概念罗列,本卷给可判定的支配策略检测与方差结构分析;叙事设计 属叙事方向,本卷不覆盖叙事。game/专题其它篇讲的是概念与实现片段:经济平衡 是经济概念 + 示意代码,本卷讲整数化与逐位一致;输入与打击感 是输入 / 帧缓冲 / 打击感实现,本卷把战斗当机制(伤害、时序、资源);平衡治理流程 是流程治理,本卷给涌现度量;新手引导清单 是清单,本卷给技巧习得曲线;留存设计清单 是清单,本卷第 8 章把奖励节奏写成可算的谱;关卡生产管线 是管线,本卷做平台跳跃机制的可算化。- 《产品架构与经济系统》 做的是 SLG 的系统地图与功能架构,与具体品类绑定;本卷做的是跨品类的可执行规格,与品类无关。凡「这个系统该拆成哪些模块」翻那一套,凡「这份规格在四种宿主里跑得对不对」看本卷。
- 《数值平衡与商业化运营》 管 SLG 的赛季膨胀 / 数值 / 商业化;本卷第 13 章只取机制层演化(增量兼容、赛季与 DLC 的机制设计、退场),不做商业化数值。
- 《引擎实现与体验打磨》 与 《风格与品类美术实战》 分别是引擎实现与风格距离矩阵的家;本卷第 15 章做的是同一规格三处消费的偏差与容差,卷三第 14 章做的是机制距离矩阵(口径对照,不重造风格矩阵)。
- 站内三个栏目页各有各的家:
/posts/game/engine/是引擎内核(渲染),本卷core/只做逻辑内核;/posts/game/design/是 SLG 的模块拆分,本卷第 10 章是状态空间语义;/posts/game/client/phaser/是引擎实现(塔防索敌),本卷卷三做的是机制口径。本套的后继两卷——《游戏设计》卷二《策略、涌现与体验度量》与卷三《原型、可玩性与品类》——在本卷的四处消费之上接住「涌现与体验」与「跨品类」,其分卷目录见《玩法机制与可执行规格》卷末第 16 章 16.3 节的交付说明。
一句话:本卷做的是「一份玩法规格怎么写、怎么跑、怎么证明它自洽」,不是「怎么把游戏做出来」,也不是「怎么把它卖出去」。
明确不在本卷范围内
为了让边界清楚,下面这些这一卷不讲:
- 机制的具体实现与引擎 API(渲染、输入、帧缓冲、资源加载)——见
game/专题与《游戏引擎实现原理》各卷。 - 产品立项、品类选择、变现与买量——见《小游戏开发实战》卷一《市场品类与产品设计》。
- 叙事、关卡与美术的创作——见
game/indie/的叙事长文与《游戏美术与技术美术》三卷。 - 真实玩家测试数据、真实测试服、真实榜单:本机没有,一律标 X,正文逐处显式标注「需真实业务环境,命令行不可复现」。
- 任何第三方素材:贯穿案例为虚构游戏,所有 PNG / SVG 由程序化生成。
可运行性六档口径
本卷每一节的代码块头部注释里都写着它属于哪一档。所有代码块都在本机实跑过,正文数字等于实跑输出;但「整卷项目复现」(把全部配置与共享模块一次性组装跑通)由第 16 章交付,本页不单独声称。
| 档 | 数据源 | 算什么(真跑) | 产出 | 断言 |
|---|---|---|---|---|
| S | config/play_spec.json | 策略空间枚举 + Shannon 熵 / 支配策略检测 / 可解性与死锁检测 / 资源守恒 / 随机性结构分析 / 难度-能力曲线 / 奖励节奏谱 / 相变扫描 | JSON + CSV + 纯 xml.etree SVG | 脚本 exit 0;SVG 可 ET.parse;守恒误差(整数)= 0 |
| P | 同一 spec | 机制不变量(守恒 / 不可达 / 单调 / 无死锁)+ 确定性回放 | core/src/ashdeck/*.ts + core/test/gd_mech_*.test.ts | node --test '<glob>',fail == 0 |
| W | 同一 spec 内联进单文件 HTML | 浏览器里真的玩:注入整段策略序列、断言状态与胜负、采样可玩性指标 | web/dist/mech<NN>.html + out/shots/*.png | Playwright 无头:断言全绿 + 两遍确定性 + canvas ≥ 1px |
| D | 规格文本 | 字段表、不变量清单、验收清单、评审表、品类参数表 | JSON / YAML / Markdown 表 | schema / lint;必须与 S/P/W 同节搭配 |
| X | 真实业务 | 真实玩家测试数据、真实测试服、真实榜单 | 无 | 正文逐处显式标注「需真实业务环境,命令行不可复现」 |
| B | 可扰动参数 | 可玩性指标对参数的敏感度、相变点、稳健性 | JSON | 软告警不硬失败;数字来自本机实跑 |
「好玩」在本卷被操作化成几个可算的代理指标(策略空间熵、支配策略缺失度、涌现度、相变临界宽度、可解率),只用于相对比较,禁绝对化——它们证明的是「这套规格自洽、可控、可分辨」,不是「这游戏好玩」。
贯穿案例《灰烬牌库》机制总览
全书只用一份规格 config/play_spec.json 驱动。它是一局卡牌构筑 Roguelike 战斗:玩家每回合有 3 点能量,从 5 张手牌里打出若干张(扣能量、加格挡、结算伤害),结束回合后敌人攻击(先扣格挡再扣血)、补满手牌、能量重置,直到敌人死亡(胜)、玩家死亡或超过回合上限(负)。
参数(params)
| 参数 | 值 | 作用 |
|---|---|---|
playerHp | 60 | 玩家初始生命 |
enemyHp | 50 | 敌人初始生命(主目标) |
enemyAttack | 6 | 回合结束时敌人的攻击力 |
energyMax | 3 | 每回合能量上限 |
handSize | 5 | 手牌上限 |
turnLimit | 20 | 回合上限,超时判负 |
rewardGold | 12 | 胜利奖励金币(第 8 章) |
punishHp | 4 | 惩罚扣血(第 8 章) |
卡池(cards,deck_size = Σ count = 12)
| id | cost | damage | block | count | rarity |
|---|---|---|---|---|---|
strike | 1 | 6 | 0 | 5 | common |
heavy | 2 | 14 | 0 | 3 | uncommon |
jab | 0 | 3 | 0 | 2 | common |
guard | 1 | 0 | 5 | 2 | common |
目标(goals)与不变量(invariants)
- 主目标
enemyHp<=0;次目标playerHp>0;约束turn<=turnLimit。 - 四条不变量:
cardCount==deckSize(牌数守恒)、damageConserved(伤害守恒)、energyInRange(0 ≤ energy ≤ energyMax)、blockNonNegative(格挡非负)。 - 随机源是自实现可播种 PRNG(Lehmer MINSTD:
state = state * 48271 % 2147483647),种子20261014;禁Math.random()/ Pythonrandom。
用规格自带的基线策略跑一局,S 层与 P 层产出逐字相同的摘要(下面这行是 sim/ashlib.py 与本卷 P 层内核的实跑输出):
{"block":0,"cardCount":12,"damageConserved":true,"dealt":50,"enemyHp":0,"energy":1,"hand":["strike","jab","heavy"],"over":true,"played":9,"playerHp":48,"turn":4,"won":true}
读法:4 回合取胜,打出 9 张、累计造成 50 点伤害(恰好清空敌人 50 血),余能量 1,玩家剩 48 血。这行摘要就是「四处消费同一份规格」的可验证点。
底座:四处消费的公共入口
四处消费共享同一套底座:S 层公共库 sim/ashlib.py,P 层内核 core/src/ashdeck/{types,rng,cards,combat,digest}.ts,W 层打包器 web/pack.mjs 与验证器 web/verify_mech.mjs。底座只读,各章只在它之上写自己那一节的脚本与断言。下面这段是本卷的随机源,全文 26 行,与工作区 core/src/ashdeck/rng.ts 逐字节一致——它是三条跨语言纪律里第二条(自实现可播种 PRNG)的落点:
// file: core/src/ashdeck/rng.ts
// tier: P
// verify: node --test 'core/test/gd_mech_base.test.ts'
//
// 自实现可播种 PRNG(Lehmer MINSTD),与 sim/ashlib.py 的 rng_next 同算法。
// 跨语言逐位一致的唯一保证就是这里:整数运算,绝不用 Math.random()。
export const RNG_MOD = 2147483647;
export const RNG_MUL = 48271;
export function rngNext(state: number): number {
return (state * RNG_MUL) % RNG_MOD;
}
export function shuffleDeck<T>(deck: T[], seed: number): T[] {
const out = deck.slice();
let state = seed % RNG_MOD || 1;
for (let i = out.length - 1; i > 0; i -= 1) {
state = rngNext(state);
const j = state % (i + 1);
const t = out[i];
out[i] = out[j];
out[j] = t;
}
return out;
}
三条跨语言纪律(违反其一,跨语言对照必然崩):① 预算与阈值一律整数(回合数、能量点、伤害、概率千分比、熵 ×1000)→ 整数地板除 → 逐位一致;② 随机一律自实现可播种 PRNG(同算法同种子),禁语言自带随机数;③ config/ 禁浮点,幂运算 TS 侧用 BigInt,感知类派生量按声明容差断言,正文不写「逐位相等」(整数类才可以写)。
全书目录(16 章 48 节)
第一部分 · 机制与规格(第 1–4 章)
第 1 章 机制解剖(D+S)
- 1.1 机制的最小构成:动词、规则、状态 :把动词 / 规则 / 状态三者拆成规格字段(D+S)
- 1.2 资源与目标 :资源收支与目标条件的形式化(D+S)
- 1.3 反馈:机制与玩家的接口 :把反馈写成可断言的输入-输出(D+S)
第 2 章 机制的可执行规格(D+P)
- 2.1
play_spec.json的字段 :一份规格的字段全表(D) - 2.2 模式校验与语义校验 :schema 与语义两层的校验器(D+P)
- 2.3 规格的版本与迁移
:
spec_version与向后迁移(D+P)
第 3 章 S 层:机制仿真(S+B)
- 3.1 从规格到轨迹 :把一局展开成状态轨迹(S)
- 3.2 资源守恒与不变量检验 :守恒误差恒为 0 的检验(S)
- 3.3 仿真输出的可读化
:纯
xml.etree出图与 CSV(S+B)
第 4 章 P 层:确定性内核(P)
- 4.1 规格驱动的状态机 :与 S 层逐条对应的状态机(P)
- 4.2 不变量断言:守恒、不可达、单调 :三类不变量的断言(P)
- 4.3 无死锁与可解性 :死锁与可解性的判定(P)
第二部分 · 跑起来(第 5–8 章)
第 5 章 W 层:可玩原型(W)
- 5.1 规格内联进单文件 HTML :把规格与内核内联成一个页面(W)
- 5.2 Playwright 真玩:注入策略、断言状态 :无头浏览器里真玩并断言(W)
- 5.3 原型与内核的同源性 :同一内核,两个宿主(W)
第 6 章 B 层:参数扰动与相变扫描(B+S)
- 6.1 参数敏感度 :指标对参数的敏感度(B+S)
- 6.2 相变扫描:游戏被解开的点 :找「被解开的点」(B+S)
- 6.3 稳健性与告警 :软告警不硬失败(B)
第 7 章 反馈循环(S+B)
- 7.1 正反馈与负反馈 :两类回路的机制形态(S)
- 7.2 反馈延迟与回路增益 :回路增益的可算模型(S+B)
- 7.3 循环的稳定性 :循环稳不稳的判据(S+B)
第 8 章 奖励节奏与惩罚设计(S+B)
- 8.1 奖励节奏谱 :把奖励节奏写成可算的谱(S)
- 8.2 惩罚机制与挫败预算 :挫败的整数预算(S+B)
- 8.3 节奏与惩罚的度量 :两个度量的口径(S+B)
第三部分 · 可计算性(第 9–13 章)
第 9 章 随机性与方差(S+P)
- 9.1 随机性的结构:均匀、加权、洗牌袋 :三种随机结构的差别(S)
- 9.2 方差与体验 :方差如何塑造体验(S+P)
- 9.3 可播种随机与确定性回放 :同种子同回放(S+P)
第 10 章 状态空间与不变量(S+P)
- 10.1 状态的可达性 :哪些状态可达(S)
- 10.2 不变量清单 :不变量的完整清单(P)
- 10.3 死锁与可解性检测 :死锁与可解的自动检测(S+P)
第 11 章 机制数值的整数化与跨语言一致(P+S)
- 11.1 整数化与跨语言一致 :整数化换来的逐位一致(P+S)
- 11.2 增长与衰减的闭式与递推 :闭式与递推的等价(P+S)
- 11.3 数值的可复现 :可复现的边界(P+S)
第 12 章 机制的组合与相互作用(S+B)
- 12.1 机制之间的耦合 :耦合的度量(S)
- 12.2 协同与反协同 :协同 / 反协同的判定(S+B)
- 12.3 组合爆炸的控制 :剪枝与采样上界(S+B)
第 13 章 机制的扩展、演化与退场(D+S)
- 13.1 机制增量与兼容 :加机制不破坏旧机制(D+S)
- 13.2 赛季与 DLC 的机制设计 :赛季与 DLC 的机制层设计(D+S)
- 13.3 机制的退场 :机制如何体面退场(D+S)
第四部分 · 接口与装配(第 14–16 章)
第 14 章 机制到体验的接口(S+B)
- 14.1 机制到体验的映射 :从机制量到体验量(S)
- 14.2 可观测的体验指标 :哪些指标可观测(S+B)
- 14.3 从机制到体验的断言 :把体验写成断言(S+B)
第 15 章 三处消费的对照与偏差(S+P)
- 15.1 跨语言摘要与 digest :digest 的构造与比对(S+P)
- 15.2 同源不同宿主 :同一内核在三处宿主(S+P)
- 15.3 偏差与容差 :偏差从哪来、容差怎么定(S+P)
第 16 章 装配:一份规格,四处消费(S+P+W+B)
16.1 规格装配检查表 :交付前的装配检查表(D)
16.2 四处消费的联调 :四处一起跑(S+P+W+B)
16.3 交付卷二 :把规格交给卷二(S+P)
怎么读
三条路径,按你的目的挑一条:
- 先看主张:读本页的引语与《灰烬牌库》机制总览,再跳到第 2 章 2.1
play_spec.json的字段 看规格长什么样,最后看第 15 章 15.1 跨语言摘要与 digest 看「逐字一致」怎么被验证。 - 直接动手:从第 2 章 2.2 模式校验与语义校验 开始写规格,依次跑 S 层(第 3 章 )、P 层(第 4 章 )、W 层(第 5 章 ),最后用第 16 章 16.1 规格装配检查表 收口。
- 只看结论:直接看第 16 章 16.2 四处消费的联调 与附录 A ——那里有字段全表、公式表、不变量清单与全部数据集索引。
可运行性总表(各章档位分布)
| 章 | 主题 | 档位 |
|---|---|---|
| 1 | 机制解剖 | D + S |
| 2 | 机制的可执行规格 | D + P |
| 3 | S 层:机制仿真 | S + B |
| 4 | P 层:确定性内核 | P |
| 5 | W 层:可玩原型 | W |
| 6 | B 层:参数扰动与相变扫描 | B + S |
| 7 | 反馈循环 | S + B |
| 8 | 奖励节奏与惩罚设计 | S + B |
| 9 | 随机性与方差 | S + P |
| 10 | 状态空间与不变量 | S + P |
| 11 | 机制数值的整数化与跨语言一致 | P + S |
| 12 | 机制的组合与相互作用 | S + B |
| 13 | 机制的扩展、演化与退场 | D + S |
| 14 | 机制到体验的接口 | S + B |
| 15 | 三处消费的对照与偏差 | S + P |
| 16 | 装配:一份规格,四处消费 | S + P + W + B |
整卷口径:每一节至少有一个 S / P / W 档的可跑代码块;S 层脚本逐个跑(/opt/homebrew/bin/python3 sim/gd_mech_*.py),P 层写全 glob(node --test 'core/test/gd_mech_*.test.ts'),W 层用 web/verify_mech<NN>.mjs 无头断言;B 层软告警不硬失败。完整字段表、公式表与数据集索引见附录 A
。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。