这是《游戏设计》三卷本的第二卷。它接住卷一留下的那条基线——一份可执行、可证明、跨宿主一致的玩法规格——然后问下一个问题:这份规格跑起来之后,会发生什么?玩家又会体验到什么?
卷一(《玩法机制与可执行规格》)做的是 M 层(Mechanics):机制怎么写成规格、规格怎么被 S / P / W / B 四处消费、四处怎么逐字一致。这一卷做的是 MDA 的另外两层:机制跑起来涌现出什么(Dynamics)、玩家因此体验到什么(Aesthetics)。站内这两层基本无人占,而它们恰恰是可计算、可跑、可比较的。
做法只有一句话:把「好玩」拆成能算的量。策略空间的 Shannon 熵、支配策略缺失度、涌现度、相变临界宽度、心流带宽、情绪张力曲线、可解率——每一个都是整数或千分比,都能从同一份
config/play_spec.json真跑出来。它们是代理指标(proxy),只用于相对比较,不用于证明「好玩」。 这一点全书反复声明。贯穿案例仍是虚构的卡牌构筑 Roguelike 《灰烬牌库》(工程名
ashdeck),底座与卷一完全相同:config/放规格,sim/是 Python 仿真,core/是 TypeScript 确定性内核,web/把内核内联进单文件 HTML 供无头浏览器真玩。
这套书与站内既有内容的分工
站内已经有大量相邻内容,写清分工比重复写一遍更有价值。下面五处边界是本卷最容易混淆的,务必分清:
- 《小游戏开发实战》卷一《市场品类与产品设计》 是产品口径:品类选择、用户动机、立项预算、变现前置。本卷是动态与体验口径:机制跑起来涌现什么、玩家体验到什么,全部操作化为可计算指标。它那一卷有三个点最像本卷,逐个划清:① 核心循环拆解 用 S 层算循环时长占比,本卷第 1 章算的是策略空间(动作序列的枚举规模与 Shannon 熵);② 难度-心流曲线 给的是 S 层心流单点模型 + B 层难度敏感性,本卷第 6 章与第 10 章给的是相变 / 序参量与心流带宽(区间而非单点);③ 可玩性指标测试 的指标偏占比类(S 层模拟采样 + 置信区间),本卷第 12–13 章给的是策略熵 / 支配缺失度 / 涌现度 / 相变宽度等机制量。
game/indie/的四篇长文是散文式 + Unitycsharp片段、不可跑:核心循环与手感设计 (约 690 行)讲手感参数体系,本卷第 11 章把它换成技巧习得曲线(建模 / 习得曲线与难度曲线 / 天花板与瓶颈);平衡与经济 (约 1430 行)是概念罗列,本卷第 2 章给可判定的支配策略检测;关卡设计与环境叙事 (约 940 行)讲空间引导与难度曲线,本卷第 9 章把张力与释放写成可算的情绪曲线;叙事设计 属叙事方向,本卷不覆盖叙事。game/专题其它篇讲的是概念与流程:经济平衡 是经济平衡概念 + 示意代码,本卷第 5 章给策略平衡度量;平衡治理流程 是流程治理(委员会、评审、榜单),本卷第 4 章给涌现度量;新手引导清单 是清单,本卷第 11 章给习得曲线。凡「该走什么流程」看那些篇,凡「这个量等于多少」看本卷。- 《数值平衡与商业化运营》 管 SLG 的赛季膨胀 / 数值 / 商业化;本卷第 3 章只取博弈最优(极小极大、混合策略、最优解的计算代价),不做商业化数值。《风格与品类美术实战》 做的是风格距离矩阵,本卷(与卷三)做的是机制距离矩阵(口径对照,不重造风格矩阵)。
- 《引擎实现与体验打磨》
与
/posts/game/industry/分别是引擎 API 与行业短文的家;本卷第 14 章做的是纯xml.etreeSVG 的动态可视化(曲线与谱、策略空间热力图、相变图读法)。本卷的前一卷《玩法机制与可执行规格》讲「规格怎么写」,本卷讲「规格跑起来之后是什么」,其分卷目录见《玩法机制与可执行规格》卷末第 16 章 16.3 节的交付说明。
一句话:本卷做的是「机制跑起来之后,动态与体验能不能被算出来、被比较」,不是「机制怎么写」(卷一),也不是「怎么把它做成原型、换成别的品类」(卷三)。
明确不在本卷范围内
为了让边界清楚,下面这些这一卷不讲:
- 玩法规格本身的字段、校验、版本与迁移——见卷一《玩法机制与可执行规格》第 1–2 章。
- 四处消费的工程做法(内联、无头真玩、跨宿主摘要)——见卷一卷五、卷十五、卷十六。
- 产品立项、品类选择、变现与买量——见《小游戏开发实战》卷一《市场品类与产品设计》。
- 叙事、关卡与美术的创作——见
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_play_*.test.ts | node --test '<glob>',fail == 0 |
| W | 同一 spec 内联进单文件 HTML | 浏览器里真的玩:注入整段策略序列、断言状态与胜负、采样可玩性指标 | web/dist/play<NN>.html + out/shots/*.png | Playwright 无头:断言全绿 + 两遍确定性 + canvas ≥ 1px |
| D | 规格文本 | 动因模型表、玩家类型表、指标定义表、装配检查表、交付清单 | JSON / YAML / Markdown 表 | schema / lint;必须与 S/P/W 同节搭配 |
| X | 真实业务 | 真实玩家测试数据、真实测试服、真实榜单 | 无 | 正文逐处显式标注「需真实业务环境,命令行不可复现」 |
| B | 可扰动参数 | 指标对参数的敏感度、相变点、稳健性 | JSON | 软告警不硬失败;数字来自本机实跑 |
「好玩」在本卷被操作化成几个可算的代理指标(策略空间熵、支配策略缺失度、涌现度、相变临界宽度、心流带宽、可解率),只用于相对比较,禁绝对化——它们证明的是「这套规格的动态可控、可分辨、可比较」,不是「这游戏好玩」。
贯穿案例《灰烬牌库》的动态侧面
卷一从机制角度解剖了《灰烬牌库》:一个 12 张牌的牌库、若干张手牌、能量与伤害、回合上限、胜负条件,全部写在 config/play_spec.json 里。本卷换一个角度看同一份规格——它的动态:
- 策略空间有多大:把「每一回合出哪几张牌、按什么顺序」写成动作序列,一局的可选路径有多少条?枚举规模与 Shannon 熵给出一个整数上界(第 1 章)。
- 有没有支配策略:如果「永远先出重击」严格优于其它选择,这个游戏就被解开了。检测严格 / 弱支配、给出算法与复杂度上界(第 2 章)。
- 最优解值多少:极小极大告诉你「双方都最优时会怎样」,混合策略告诉你「随机化能换来什么」,以及求出最优解的计算代价(第 3 章)。
- 涌现出什么:规则简单,跑起来却出现设计者没写过的模式——涌现度衡量「可达模式数 / 规则数」,退化解则提示模式其实很少(第 4 章)。
- 平不平衡、有没有相变:胜率分布是否集中、可用策略是否够多(第 5 章);参数扫过某个点后游戏性质突变(第 6 章)。
这些都是同一份 play_spec.json 在不同维度上的投影,全部由 sim/gd_play_*.py 真跑产出。
全书 16 章 48 节
第一部分 · 策略与均衡(第 1–3 章)
第 1 章 策略空间(S)
- 1.1 策略的表示:动作序列与决策树 :把「怎么打」写成可枚举的对象(S)
- 1.2 策略空间枚举与 Shannon 熵 :枚举规模与熵的整数化(S)
- 1.3 策略空间的规模控制 :剪枝与「何时改用采样」(S)
第 2 章 支配策略检测(S+B)
- 2.1 支配关系:严格与弱 :两种支配的定义(S)
- 2.2 检测算法与复杂度 :可判定的检测与上界(S)
- 2.3 支配策略的修复 :把被解开的游戏修回来(S+B)
第 3 章 均衡与最优(S)
- 3.1 minimax 与极小极大 :双方最优时的值(S)
- 3.2 混合策略与纳什直觉 :随机化能换来什么(S)
- 3.3 最优解的代价 :求出最优要花多少(S)
第二部分 · 涌现与相变(第 4–6 章)
第 4 章 涌现(S+B)
- 4.1 涌现:从规则到模式 :简单规则长出模式(S)
- 4.2 涌现的度量 :可达模式数 / 规则数(S)
- 4.3 退化解与退化模式 :看起来涌现、其实只有一条路(S+B)
第 5 章 平衡(S+B)
- 5.1 平衡的定义与层次 :平衡在不同层次上指什么(S)
- 5.2 平衡的度量 :胜率分布与可用策略数(S)
- 5.3 平衡与多样性 :两者是张力不是同义词(S+B)
第 6 章 相变(S+B)
- 6.1 相变:参数扫过临界点 :游戏在哪一点变性质(S)
- 6.2 序参量与临界指数 :用什么量刻画临界(S)
- 6.3 相变扫描的实现 :粗扫 + 二分细化的工程做法(S+B)
第三部分 · 玩家与体验(第 7–13 章)
第 7 章 玩家动因模型(D+S)
- 7.1 自我决定理论:自主、胜任、关联 :三种基本心理需要(D)
- 7.2 动因模型的可计算化 :把动因写成可算量(D+S)
- 7.3 动因与机制的对齐 :机制喂不喂得上动因(D+S)
第 8 章 玩家类型(D+S)
- 8.1 玩家类型学 :类型划分的几种口径(D)
- 8.2 类型到机制的映射 :哪类玩家吃哪套机制(D+S)
- 8.3 类型的分布与漂移 :分布怎么变(D+S)
第 9 章 情绪曲线与张力(S)
- 9.1 张力与释放 :张力从哪里来(S)
- 9.2 情绪曲线的可计算化 :把曲线算出来(S)
- 9.3 情绪与节奏的对齐 :曲线与节奏对不对得上(S)
第 10 章 心流带宽(S)
- 10.1 心流:挑战与技巧的匹配 :匹配才进心流(S)
- 10.2 心流带宽的可计算化 :带宽是区间不是单点(S)
- 10.3 带宽与难度设计 :按带宽排难度(S)
第 11 章 技巧习得曲线(S+B)
- 11.1 技巧习得的建模 :技巧怎么长(S)
- 11.2 习得曲线与难度曲线 :两条曲线的关系(S)
- 11.3 天花板与瓶颈 :练到头会怎样(S+B)
第 12 章 体验度量(S)
- 12.1 体验指标的选取 :选哪些指标、为什么(S)
- 12.2 从机制仿真到体验指标 :从仿真到指标(S)
- 12.3 指标的置信区间 :指标本身有多准(S)
第 13 章 可玩性的可计算化(S+B)
- 13.1 可玩性的操作化定义 :把可玩性拆成能算的量(S)
- 13.2 可玩性指标与采样 :组合指标怎么采(S)
- 13.3 指标的可比性 :跨配置能不能比(S+B)
第四部分 · 可视化、反推与装配(第 14–16 章)
第 14 章 动态的可视化(S)
- 14.1 曲线与谱
:纯
xml.etree出曲线(S) - 14.2 策略空间的热力图 :把空间画成图(S)
- 14.3 相变图的读法 :相变图怎么看(S)
第 15 章 动态到设计的反推(S+B)
- 15.1 从指标反推参数 :从想要的指标倒推参数(S)
- 15.2 反推的可行域 :哪些指标组合够得着(S)
- 15.3 反推的代价与取舍 :反推不是免费的(S+B)
第 16 章 装配:规格跑起来(S+P+W+B)
16.1 动态度量装配 :度量链路装配检查表(D)
16.2 体验度量的联调 :S / P / W / B 一起跑(S+P+W+B)
16.3 交付卷三 :把动态基线交给卷三(S+P)
三卷递进
三卷不是三个话题,是同一条链上的三段:
- 卷一《玩法机制与可执行规格》(
gd-mech-):一份玩法规格怎么写、怎么被四处消费、怎么证明它自洽。落点是 M 层(Mechanics)。 - 卷二《策略、涌现与体验度量》(
gd-play-,即本卷):规格跑起来之后涌现什么、玩家体验到什么,全部操作化为可计算指标。落点是 D 层(Dynamics)与 A 层(Aesthetics)。 - 卷三《原型、可玩性与品类》(
gd-proto-):把同一份规格实例化到 6 个品类,6/6 通过可玩性闸门,产出品类间机制距离矩阵。落点是跨品类成立性。
三卷共用同一份 config/play_spec.json、同一个 sim/、同一个 core/、同一个 web/。换卷不换底座——这也是「一份规格,四处消费」能被验证的前提。
本卷用到的代理指标速查
下表把本卷反复出现的量集中列一次。它们全部是代理指标(proxy),只用于相对比较,不用于证明「好玩」。
| 指标 | 定义(整数化口径) | 主要出现 |
|---|---|---|
| 策略空间熵 | 动作序列分布的 Shannon 熵 × 1000 取整 | 第 1、13 章 |
| 支配策略缺失度 | 1 − 支配策略数 / 总策略数,千分比 | 第 2、13 章 |
| 涌现度 | 可达模式数 / 规则数,千分比 | 第 4、13 章 |
| 相变临界宽度 | 序参量跨越阈值所对应的参数区间宽度(整数) | 第 6、13 章 |
| 心流带宽 | 挑战-技巧匹配区间的宽度(整数刻度) | 第 10、11 章 |
| 可解率 | 可解种子数 / 总种子数,千分比 | 第 12、15 章 |
| 张力峰值 | 单局张力曲线的最大值(整数) | 第 9、14 章 |
底座:策略枚举的公共入口
本卷与卷一共享同一套底座:S 层公共库 sim/ashlib.py,P 层内核 core/src/ashdeck/{types,rng,cards,combat,digest}.ts,W 层打包器 web/pack.mjs 与验证器 web/verify_mech.mjs。底座只读,各章只在它之上写自己那一节的枚举与度量脚本。
策略枚举的可复现性,前提是随机源可复现。下面这段是本套的随机源,与工作区 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;
}
用规格自带的基线策略跑一局,S 层产出的摘要如下——它与卷一给出的那一行逐字相同:
{"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 血。换卷不换底座——同一份规格在同一台机器上永远给同一行,这是本卷所有动态指标可比较的前提。
复现前提
想在本地把本卷的代码块跑起来,需要这些条件(都已实测可用):
- Python 用
/opt/homebrew/bin/python3(3.14.6,带 numpy / pandas / Pillow;无 matplotlib / scipy,图表一律纯xml.etree生成 SVG)。 - Node 用
node(v26.5.0,原生跑.ts;strip-only,禁enum/namespace)。 - 工作区是
$HOME/.gdbook/ashdeck(不是/tmp,会被系统清理),底座文件config/play_spec.json、sim/ashlib.py、core/src/ashdeck/*.ts、web/pack.mjs与卷一完全相同。 - 随机一律用自实现可播种整数 PRNG(Python 与 TS 同算法同种子),禁
Math.random()与 Pythonrandom——否则跨语言对照必然漂移。 - 每个代码块头部注释都写着
# file:/# tier:/# verify:,file:指向工作区里的真实文件,与正文块逐字节一致。 - 真实玩家数据、测试服、榜单在本机不存在,凡涉及它们的段落一律标 X 并显式写明「需真实业务环境,命令行不可复现」。
怎么读
三条路径,按你的目的挑一条:
- 先看主张:读本页的引语与《灰烬牌库》动态侧面,再跳到第 1 章 1.2 策略空间枚举与 Shannon 熵 看「策略空间有多大」怎么算,最后看第 13 章 13.1 可玩性的操作化定义 看「好玩」怎么被拆成能算的量。
- 直接动手:从第 1 章 1.1 策略的表示:动作序列与决策树 开始枚举策略,依次做支配检测(第 2 章 )、涌现度量(第 4 章 )、相变扫描(第 6 章 ),最后用第 16 章 16.1 动态度量装配 收口。
- 只看结论:直接看第 16 章 16.2 体验度量的联调 与附录 A ——那里有指标公式全表、参数表与全部数据集索引。
可运行性总表(各章档位分布)
| 章 | 主题 | 档位 |
|---|---|---|
| 1 | 策略空间 | S |
| 2 | 支配策略检测 | S + B |
| 3 | 均衡与最优 | S |
| 4 | 涌现 | S + B |
| 5 | 平衡 | S + B |
| 6 | 相变 | S + B |
| 7 | 玩家动因模型 | D + S |
| 8 | 玩家类型 | D + S |
| 9 | 情绪曲线与张力 | S |
| 10 | 心流带宽 | S |
| 11 | 技巧习得曲线 | S + B |
| 12 | 体验度量 | S |
| 13 | 可玩性的可计算化 | S + B |
| 14 | 动态的可视化 | S |
| 15 | 动态到设计的反推 | S + B |
| 16 | 装配:规格跑起来 | S + P + W + B |
整卷口径:每一节至少有一个 S / P / W 档的可跑代码块;S 层脚本逐个跑(/opt/homebrew/bin/python3 sim/gd_play_*.py),P 层写全 glob(node --test 'core/test/gd_play_*.test.ts'),W 层用 web/verify_mech<NN>.mjs 无头断言;B 层软告警不硬失败。完整指标公式表与数据集索引见附录 A
。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。