这是《游戏设计》三卷本的第三卷,也是收官的一卷。它接住卷二留下的那条基线——机制跑起来的动态与体验都被算出来了——然后问最后一个问题:同一份玩法规格,换成别的品类,还成不成立?
卷一(《玩法机制与可执行规格》)做 M 层(Mechanics):一份规格怎么写、怎么被 S / P / W / B 四处消费、四处怎么逐字一致;卷二(《策略、涌现与体验度量》)做 D 层与 A 层:规格跑起来涌现什么、玩家体验到什么。这一卷做的是「跨品类成立性」:把同一份
config/play_spec.json实例化到 6 个品类变体,跑同一套 sim + kernel + 可玩原型,要求 6/6 通过可玩性闸门,并给出 6×6 品类机制距离矩阵证明「同源但可区分」。关键先说清楚:这不是 6 个游戏,是同一份规格在 6 组规则参数下的实例。 六个变体是
deckbuilder(贯穿案例本体)/tower-defense/match3/platformer/autobattler/idle——它们共用同一个规格骨架(动词 / 规则 / 状态 / 资源 / 目标 / 反馈),只覆盖rules与params两段。换品类不换底座,这正是「一份规格,四处消费」能推广到品类层的证据。做法仍是那句话:把「好玩」拆成能算的量。这一卷把代理指标用在品类之间——策略空间熵、支配策略缺失度、涌现度、相变临界宽度、可解率——算出 6×6 距离矩阵,用来回答「这六个变体到底像不像、能不能被区分开」。它们是代理指标(proxy),只用于相对比较,不用于证明「好玩」。
贯穿案例仍是虚构的卡牌构筑 Roguelike 《灰烬牌库》(工程名
ashdeck),底座与卷一、卷二完全相同:config/放规格,sim/是 Python 仿真,core/是 TypeScript 确定性内核,web/把内核内联进单文件 HTML 供无头浏览器真玩。
本卷定位:同一份规格,六个品类变体
前两卷证明了「一份规格能在四个宿主里逐字一致地跑」。这一卷把问题抬高一层:如果把规格里的 rules 与 params 换掉,同一套仿真、同一套内核、同一套可玩原型还能不能跑通、跑出可玩的东西?
- 换的是规则参数,不是代码:六个变体共享同一个规格骨架与同一份底座,只在
config/里覆盖rules/params。所以「跨品类」在本卷是一个可执行的命题,不是一句口号。 - 闸门是 6/6:每个变体都要通过同一套可玩性闸门(在浏览器里真玩、断言状态与胜负、采样代理指标、两遍确定性一致)。第 15 章给出 6/6 的回归结果,任何一个变体不通过都要诚实报告(15.3)。
- 可区分性是硬指标:六个变体如果互相像到分不开,那「跨品类」就是假的。第 14 章把每个变体写成特征向量,算出 6×6 机制距离矩阵,证明它们同源但可区分。
- 收官在第 16 章:第 16 章是三卷的总装配——三卷装配检查表、一份规格的全链路回放(从
config/play_spec.json到六个变体的可玩原型)、以及交付与后续。
一句话:卷一讲「规格怎么写」,卷二讲「规格跑起来是什么」,这一卷讲「规格换品类还成不成立」。
这套书与站内既有内容的分工
站内已经有大量相邻内容,写清分工比重复写一遍更有价值。下面这些边界是本卷最容易混淆的,务必分清:
- 《小游戏开发实战》卷一《市场品类与产品设计》 是产品口径:品类选择、用户动机、立项预算、变现前置。本卷是机制口径:同一份规格在六组品类参数下还成不成立。它那一卷有几处最像本卷,逐个划清:① 可玩性指标测试 是占比类指标 + 二项区间,本卷第 4 章是可玩性测试设计(假设 / 样本 / 决策),不是算区间而是设计怎么测;② 最小可玩原型 与 原型迭代决策 是原型范围 / 止损 / 迭代决策(产品口径),本卷第 2 章是规格驱动的最小内核(工程口径);③ 品类分类与商业矩阵 是品类分类 / 商业矩阵,本卷第 13 章是品类机制参数化(把品类写成可覆盖的规则参数);④ 成长曲线 是成长曲线,本卷第 10 章是放置的相变与动因;⑤ 交付物验收与交接 是交付物验收,本卷第 15 章是六品类变体的机制闸门回归。
- 独立游戏核心循环与手感设计
是散文式手感参数体系(Unity
csharp片段、不可跑),本卷第 12 章把「手感」换成可断言的输入-反馈机制(手感不是渲染、参数可计算化、度量与断言)。 - 输入与打击感 讲输入 / 帧缓冲 / 打击感实现,本卷第 11 章把战斗当机制(伤害、时序、资源),算它的策略空间、平衡与相变。
- 关卡设计与环境叙事 讲关卡设计(空间引导 / 难度曲线 / 环境叙事),本卷第 8 章做平台跳跃机制的可算化(跳跃曲线、技巧曲线、心流带宽)。
- 《数值平衡与商业化运营》 管 SLG 的赛季膨胀 / 数值 / 商业化,本卷第 9 章只取自走棋经济(利息、连胜、刷新成本的经济平衡与涌现),不做商业化数值。
- 《风格与品类美术实战》 做的是风格距离矩阵,本卷第 14 章做的是机制距离矩阵——两者是口径对照:同一套「特征向量 + 距离 + 可区分性」的方法,一个量风格、一个量机制,不重造风格矩阵。
- 《引擎实现与体验打磨》
是引擎 API 的家,本卷第 3 章做的是规格驱动的可玩原型(规格内联、浏览器真玩、可分享可回放),底座只复用
web/pack.mjs。 /posts/game/client/phaser/是引擎实现口径(塔防索敌怎么用 Phaser 写),本卷第 6 章是机制口径(塔防的机制解剖、策略空间、难度曲线)。- 《小游戏开发实战》总目录 是单款产品口径的整套开发目录(从立项到上线),本套是机制与规格口径——把玩法写成规格、把规格跑起来、把规格换成别的品类。
一句话:本卷做的是「同一份玩法规格换成品类参数后还成不成立、六个变体能不能被区分」,不是「机制怎么写」(卷一),也不是「动态与体验怎么算」(卷二)。
明确不在本卷范围内
为了让边界清楚,下面这些这一卷不讲:
- 玩法规格本身的字段、校验、版本与迁移——见卷一《玩法机制与可执行规格》第 1–2 章。
- 动态与体验的度量(策略熵、涌现度、心流带宽、参数反推)——见卷二《策略、涌现与体验度量》第 1–15 章。
- 产品立项、品类选择、变现与买量——见《小游戏开发实战》卷一《市场品类与产品设计》。
- 引擎 API 与渲染(输入、帧缓冲、资源加载)——见
game/专题与《引擎实现与体验打磨》。 - 真实玩家测试数据、真实测试服、真实榜单:本机没有,一律标 X,正文逐处显式标注「需真实业务环境,命令行不可复现」。
- 任何第三方素材:贯穿案例为虚构游戏,所有 PNG / SVG 由程序化生成。
可运行性六档口径
本卷每一节的代码块头部注释里都写着它属于哪一档。所有代码块都在本机实跑过,正文数字等于实跑输出;但「整卷项目复现」(把全部配置与共享模块一次性组装跑通)由第 16 章交付,本页不单独声称。
| 档 | 数据源 | 算什么(真跑) | 产出 | 断言 |
|---|---|---|---|---|
| S | config/play_spec.json | 纸面规则的形式化与守恒 / 可玩性测试的采样与假设检验 / 六品类的特征向量与距离矩阵 / 战斗与手感的机制度量 / 变体回归 | JSON + CSV + 纯 xml.etree SVG | 脚本 exit 0;SVG 可 ET.parse;整数指标误差 = 0 |
| P | 同一 spec | 机制不变量(守恒 / 不可达 / 单调 / 无死锁)+ 确定性回放 + 六变体的规则内核 | core/src/ashdeck/*.ts + core/test/gd_proto_*.test.ts | node --test '<glob>',fail == 0 |
| W | 同一 spec 内联进单文件 HTML | 浏览器里真的玩:六个品类变体各跑一局、断言状态与胜负、采样可玩性指标 | web/dist/proto<NN>.html + out/shots/*.png | Playwright 无头:断言全绿 + 两遍确定性 + canvas ≥ 1px |
| D | 规格文本 | 纸面原型记录表、测试假设表、品类参数表、装配检查表、交付清单 | JSON / YAML / Markdown 表 | schema / lint;必须与 S/P/W 同节搭配 |
| X | 真实业务 | 真实玩家测试数据、真实测试服、真实榜单 | 无 | 正文逐处显式标注「需真实业务环境,命令行不可复现」 |
| B | 可扰动参数 | 可玩性指标对参数的敏感度、相变点、稳健性、变体回归的告警 | JSON | 软告警不硬失败;数字来自本机实跑 |
「好玩」在本卷被操作化成几个可算的代理指标(策略空间熵、支配策略缺失度、涌现度、相变临界宽度、可解率),只用于相对比较,禁绝对化——它们在本卷用来比较六个品类变体(像不像、能不能区分),不是用来证明「这游戏好玩」。
六个品类变体
同一份 play_spec.json,只覆盖 rules / params 段。不是 6 个游戏,是同一份规格在 6 组规则参数下的实例。
| 变体 | 品类 | 规则参数覆盖的机制 | 主要出现 |
|---|---|---|---|
deckbuilder | 卡牌构筑 Roguelike | 贯穿案例本体:能量 / 手牌 / 牌库 / 伤害 | 第 5 章(另见卷一卷二) |
tower-defense | 塔防 | 波次 / 索敌 / 塔位 / 资源产出 | 第 6 章 |
match3 | 三消 | 交换 / 消除 / 连锁 / 保底 | 第 7 章 |
platformer | 平台跳跃 | 跳跃曲线 / 输入缓冲 / 碰撞 / 关卡节奏 | 第 8 章 |
autobattler | 自走棋 | 商店 / 利息 / 连胜 / 阵容协同 | 第 9 章 |
idle | 放置 | 离线收益 / 成长曲线 / 相变 / 动因 | 第 10 章 |
六个变体共用同一套 sim / kernel / 可玩原型,只在 config/ 里换参数——第 13 章把这件事写成规格的品类参数化,第 15 章给出 6/6 通过闸门的回归结果。
全书 16 章 48 节
第一部分 · 原型方法(第 1–4 章)
第 1 章 纸面原型(D+S)
- 1.1 不写代码先验规则 :用纸面把规则先跑一遍(D)
- 1.2 纸面原型的记录与回放 :纸面记录如何可回放(D+S)
- 1.3 纸面到规格的转换 :从纸面记录抽出规格字段(D+S)
第 2 章 数字原型(P+W)
- 2.1 数字原型的最小内核 :规格驱动的最小可跑内核(P)
- 2.2 数字原型的迭代循环 :改参数、看结果、再改(P+W)
- 2.3 原型的范围与止损 :什么时候该停(P+W)
第 3 章 可玩原型(W)
- 3.1 可玩原型的规格内联 :把规格内联进单文件 HTML(W)
- 3.2 浏览器里的真玩与断言 :无头浏览器里真玩并断言(W)
- 3.3 原型的可分享与可回放 :单文件原型的分享与回放(W)
第 4 章 可玩性测试设计(S+B)
- 4.1 测试的目标与假设 :先写假设再测(S)
- 4.2 采样与置信区间 :样本量与区间(S)
- 4.3 从测试到决策 :测试结果如何变成决策(S+B)
第二部分 · 六个品类机制解剖(第 5–10 章)
第 5 章 品类机制解剖:卡牌构筑 Roguelike(W+P)
- 5.1 卡牌构筑的机制解剖 :贯穿案例的机制总览(W)
- 5.2 构筑的方差与平衡 :抽牌方差与构筑平衡(W+P)
- 5.3 构筑的相变 :牌库被解开的点(W+P)
第 6 章 品类机制解剖:塔防(W+P)
- 6.1 塔防的机制解剖 :波次、塔位、索敌(W)
- 6.2 塔防的策略空间 :布局与升级的组合(W+P)
- 6.3 塔防的难度曲线 :波次强度与难度(W+P)
第 7 章 品类机制解剖:三消(W+P)
- 7.1 三消的机制解剖 :交换、消除、连锁(W)
- 7.2 三消的随机与保底 :随机结构与保底机制(W+P)
- 7.3 三消的节奏 :连锁与节奏(W+P)
第 8 章 品类机制解剖:平台跳跃(W+P)
- 8.1 平台跳跃的机制解剖 :跳跃、缓冲、碰撞(W)
- 8.2 平台跳跃的技巧曲线 :跳跃难度的技巧维度(W+P)
- 8.3 平台跳跃的心流带宽 :跳跃机制的心流带宽(W+P)
第 9 章 品类机制解剖:自走棋(W+P)
- 9.1 自走棋的机制解剖 :商店、利息、连胜(W)
- 9.2 自走棋的经济与平衡 :经济循环与平衡(W+P)
- 9.3 自走棋的涌现 :阵容协同的涌现(W+P)
第 10 章 品类机制解剖:放置(W+P)
- 10.1 放置的机制解剖 :离线收益与成长(W)
- 10.2 放置的曲线与相变 :成长曲线与相变(W+P)
- 10.3 放置的动因 :放置为什么留人(W+P)
第三部分 · 机制的两个横切面(第 11–12 章)
第 11 章 战斗作为机制(S+P)
- 11.1 战斗的机制解剖:伤害、时序、资源 :把战斗拆成机制(S)
- 11.2 战斗的策略空间与平衡 :战斗的策略与平衡(S+P)
- 11.3 战斗的相变与支配 :战斗被解开的点(S+P)
第 12 章 手感作为机制(P+W)
- 12.1 手感不是渲染:输入-反馈的机制 :手感是机制不是画面(P)
- 12.2 手感参数的可计算化 :把手感参数算出来(P+W)
- 12.3 手感的度量与断言 :把手感写成断言(P+W)
第四部分 · 跨品类与装配(第 13–16 章)
第 13 章 跨品类:同一份规格(S+P+W)
- 13.1 规格的品类参数化 :把品类写成可覆盖参数(S)
- 13.2 六个品类变体的实例化 :六个变体怎么实例化(S+P)
- 13.3 变体的可玩性闸门 :变体要过同一道闸门(S+P+W)
第 14 章 品类间距离矩阵(S)
- 14.1 品类的特征向量 :把品类写成特征向量(S)
- 14.2 距离矩阵与可区分性 :6×6 距离矩阵(S)
- 14.3 距离的读法与边界 :矩阵怎么读、边界在哪(S)
第 15 章 品类变体的验收(S+P+W+B)
- 15.1 六品类变体的回归 :六个变体一起回归(S+P+W)
- 15.2 六分之六通过闸门 :6/6 通过闸门(S+P+W+B)
- 15.3 失败的诚实报告 :没过的怎么报(S+B)
第 16 章 装配:三卷总收官(S+P+W+B)
16.1 三卷装配检查表 :三卷一起装配的检查表(D)
16.2 一份规格的全链路回放 :从规格到六变体的回放(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 取整 | 第 4、6、11、14 章 |
| 支配策略缺失度 | 1 − 支配策略数 / 总策略数,千分比 | 第 11、14 章 |
| 涌现度 | 可达模式数 / 规则数,千分比 | 第 9、14 章 |
| 相变临界宽度 | 序参量跨越阈值所对应的参数区间宽度(整数) | 第 5、10、14 章 |
| 心流带宽 | 挑战-技巧匹配区间的宽度(整数刻度) | 第 8、14 章 |
| 可解率 | 可解种子数 / 总种子数,千分比 | 第 15 章 |
底座:品类参数化的公共入口
本卷与卷一、卷二共享同一套底座:S 层公共库 sim/ashlib.py,P 层内核 core/src/ashdeck/{types,rng,cards,combat,digest}.ts,W 层打包器 web/pack.mjs 与验证器 web/verify_proto<NN>.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)。 - Playwright 1.59.1 全局装在
/opt/homebrew/lib/node_modules,供 W 层无头真玩六个品类变体。 - 工作区是
$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 并显式写明「需真实业务环境,命令行不可复现」。
怎么读
三条路径,按你的目的挑一条:
- 先看主张:读本页的引语与「同一份规格,六个品类变体」,再跳到第 13 章 13.1 规格的品类参数化 看品类怎么被写成参数,最后看第 14 章 14.2 距离矩阵与可区分性 看六个变体怎么被证明「同源但可区分」。
- 直接动手:从第 1 章 1.1 不写代码先验规则 开始把规则先写在纸面,依次做数字原型(第 2 章 )、可玩原型(第 3 章 )、可玩性测试(第 4 章 ),再用第 13 章 13.2 六个品类变体的实例化 把规格铺到六个品类。
- 只看结论:直接看第 15 章 15.2 六分之六通过闸门 与第 16 章 16.2 一份规格的全链路回放 ,再翻附录 A ——那里有品类参数表、机制距离矩阵与全部数据集索引。
可运行性总表(各章档位分布)
| 章 | 主题 | 档位 |
|---|---|---|
| 1 | 纸面原型 | D + S |
| 2 | 数字原型 | P + W |
| 3 | 可玩原型 | W |
| 4 | 可玩性测试设计 | S + B |
| 5 | 品类机制解剖:卡牌构筑 Roguelike | W + P |
| 6 | 品类机制解剖:塔防 | W + P |
| 7 | 品类机制解剖:三消 | W + P |
| 8 | 品类机制解剖:平台跳跃 | W + P |
| 9 | 品类机制解剖:自走棋 | W + P |
| 10 | 品类机制解剖:放置 | W + P |
| 11 | 战斗作为机制 | S + P |
| 12 | 手感作为机制 | P + W |
| 13 | 跨品类:同一份规格 | S + P + W |
| 14 | 品类间距离矩阵 | S |
| 15 | 品类变体的验收 | S + P + W + B |
| 16 | 装配:三卷总收官 | S + P + W + B |
整卷口径:每一节至少有一个 S / P / W 档的可跑代码块;S 层脚本逐个跑(/opt/homebrew/bin/python3 sim/gd_proto_*.py),P 层写全 glob(node --test 'core/test/gd_proto_*.test.ts'),W 层用 web/verify_proto<NN>.mjs 无头断言;B 层软告警不硬失败。完整品类参数表、机制距离矩阵与数据集索引见附录 A
。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。