diff --git a/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md b/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md index a997467..f5657ad 100644 --- a/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md +++ b/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md @@ -349,3 +349,38 @@ - 构建门禁:`cmd /c "pnpm exec tsx docs/.vitepress/init.ts && pnpm docs:build"` → **green**,输出 `build complete`,dead link = 0(高级教程预留使用代码 span 与 HTML 注释,不产生链接)。 - 边界:仅改 `docs/intermediate/*.md`;未改 `config.ts` 与任何生产代码;未新增文件;U-03 不在本批。 +--- + +## 用户循环 · batch 4 记录(D-48 实操) + +**范围:** 用户修订循环第 1 轮 batch 4(D-48 实操写法)——概念与导航组(`data-vs-render`、`src-tour`、`code-basics`、`hooks`)与基础接口组(`data-state-overview`、`hero-attribute`、`hero-items`、`hero-equipment`、`hero-location`、`map-structure`、`map-tiles`、`flags`)共 12 篇。按 `10-CONTEXT.md` D-48:**保留系统/原理讲解**,只重做「实操/示例」部分,使其可分步照抄(目标 → 改哪里 → 复制什么 → 改什么 → 怎么验证 → 注意);代码片段不含 `import`,并显式给出「顶部通常已有、不要重复粘,报缺再补」的说明。 + +### 逐条处置 + +| 文档 | 处置 | +| --- | --- | +| `data-vs-render.md` | 无「实操/示例」段落(纯概念 + mermaid),本批不改。 | +| `src-tour.md` | 无代码片段与「实操/示例」段落(目录导览 + 「该不该改」表),本批不改。 | +| `code-basics.md` | ①删除 dev.md 引擎开发约定句「文件顶部的 `import` 必须紧挨在一起,中间不夹注释或空行」(D-48 明确不写此类约定);②在「模块与引入」下新增「照抄教程里的代码时,怎么处理 import」小节,作为其余各篇统一引用的复制约定(三步:直接粘 → 报缺再补 → 不重复引入);教学示例代码块保留不动。 | +| `hooks.md` | 「注册与移除钩子」改写为 D-48 六步实操(目标 / 改哪里 / 复制什么 / 改什么 / 怎么验证 / 注意),片段含钩子对象 + `addHook`,附复制说明;移除方式保留。 | +| `data-state-overview.md` | 属查表入口,无独立实操;在「state 从哪来」补一句「示例一律省略 `import`,照抄办法见 code-basics」,指向统一复制约定。 | +| `hero-attribute.md` | ①「修饰器」代码块删去 `import { ValueModifier, PercentageModifier } from '@user/data-base'`,改为复制说明;②「示例」改写为六步实操「永久加攻与临时减防」。 | +| `hero-items.md` | ①「常用接口」示例改写为六步实操(发 / 扣 / 使用 / 查询道具);②「道具效果属内容层」示例改写为六步实操(内容层道具效果:加攻 + 提示)。 | +| `hero-equipment.md` | 「装备槽」示例改写为六步实操(获得装备 → 装备到 0 号槽 → 卸下)。 | +| `hero-location.md` | 新增六步实操「读取勇士位置信息」(坐标 + 朝向 + 楼层 + 提示)。 | +| `map-structure.md` | U-04 的「如何取到指定图层」改写为六步实操;把 `addLayer` 的提醒并入「注意」。 | +| `map-tiles.md` | ①「读取与写入单点」示例改写为六步实操;②U-05 的「完整示例(批量)」改写为六步实操(保留 `// prettier-ignore` 的按行数组)。 | +| `flags.md` | U-06 的「示例:记录开关与计数」改写为六步实操。 | + +### 共用复制说明(各篇统一) + +> 复制说明:片段已省略 `import`;文件顶部通常已有,不要再粘。若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +### 校验 + +- 结构门禁:本批改动的 10 篇全部 CRLF、单 H1(`STRUCT-OK`)。 +- 格式门禁:`node node_modules/prettier/bin/prettier.cjs --write`(D-45)已跑,改动篇目全部 `unchanged`(内容本就符合 prettier)。 +- 构建门禁:`cmd /c "pnpm exec tsx docs/.vitepress/init.ts && pnpm docs:build"` → **green**,输出 `build complete`,dead link = 0。 +- 边界:仅改 `docs/intermediate/*.md`(`data-vs-render`、`src-tour` 无实操、不改);未改 `config.ts` 与任何生产代码;未新增文件;未引入指向 `docs/advanced/` 的真实链接(D-47 预留仍为代码 span + HTML 注释)。 +- 未决:战斗组与「其他」组(`combat-overview`、`enemy-*`、`events`、`replay-commands`、`data-plugins`)的实操尚未按 D-48 重做,其中仍是含 `import` 的代码块;留待后续批次。 + diff --git a/docs/intermediate/code-basics.md b/docs/intermediate/code-basics.md index 3588e34..b15d73f 100644 --- a/docs/intermediate/code-basics.md +++ b/docs/intermediate/code-basics.md @@ -58,7 +58,7 @@ hero.atk = hero.atk + 5; ## 二、模块与引入 -当代码变多,就要拆成多个文件。一个文件就是一个模块:用 `export` 把内容暴露出去,用 `import` 从别的模块引入。在本引擎里,文件顶部的 `import` 必须紧挨在一起,中间不夹注释或空行。 +当代码变多,就要拆成多个文件。一个文件就是一个模块:用 `export` 把内容暴露出去,用 `import` 从别的模块引入。 ```ts // math.ts @@ -84,6 +84,16 @@ import * as math from './math'; math.add(1, 2); ``` +### 照抄教程里的代码时,怎么处理 import + +本教程其余篇章给出的都是**要粘进你文件的代码片段**。为了不啰嗦,片段里一律**不写 `import`**——照着下面三步处理即可: + +1. **直接粘片段**。你所在文件的顶部通常**已经有**这些引入,不用再粘一遍; +2. 粘完若编辑器提示「找不到名称 Xxx」,说明这个文件还没引入它,再回到**文件顶部**补一行对应的 `import`(写法同上面的 `import { add } from './math'`); +3. 不确定某个名字该从哪个包装入,看 [src 导览](./src-tour.md) 的「包从哪来」。 + +不要把片段里没出现的 `import` 也一并照抄,重复引入反而会让编辑器报错。 + ## 三、类型入门 TypeScript 在 JavaScript 之上增加了类型,用来描述「这份数据长什么样」。类型会在编写与编译阶段被检查,帮你在运行之前就发现错误。 diff --git a/docs/intermediate/data-state-overview.md b/docs/intermediate/data-state-overview.md index 47cf9fd..717c167 100644 --- a/docs/intermediate/data-state-overview.md +++ b/docs/intermediate/data-state-overview.md @@ -49,7 +49,7 @@ class MySystem { } ``` -本教程后续的代码示例都假设 `state` 已经在当前作用域中(由上面任一方式获得),因此示例不再重复它的来源。 +本教程后续的代码示例都假设 `state` 已经在当前作用域中(由上面任一方式获得),因此示例不再重复它的来源;示例也一律**省略 `import`**,照抄时怎么处理引入见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」。 ## 常用对象与获取方式 diff --git a/docs/intermediate/flags.md b/docs/intermediate/flags.md index df03664..588fb21 100644 --- a/docs/intermediate/flags.md +++ b/docs/intermediate/flags.md @@ -73,6 +73,12 @@ Flag 常与游戏关键动作配合使用,例如在钩子中读写,见[钩 ## 示例:记录开关与计数 +**目标**:记下「Boss 已被击败」这个开关,以及「门被开过几次」这个计数——两者都要跟着存档走。 + +**改哪里**:你要记录这些状态的地方——例如某个事件函数或钩子里。 + +**复制什么**: + ```ts // 记录一个开关 state.flags.setFieldValue('boss-defeated', true); @@ -82,4 +88,12 @@ const times = state.flags.getOrInsert('open-count', 0); times.add(1); ``` +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'boss-defeated'`、`'open-count'` 换成你的字段名,把 `true`、`1` 换成你的值。只需一次读写的开关用「值」那组更简单;要反复增减的计数,用 `getOrInsert` 拿到字段对象后再 `add` 更省事。 + +**怎么验证**:写入后读 `state.flags.getFieldValue('boss-defeated')` / `getFieldValue('open-count')`,应返回你写入的值;存档后再读档依然存在。 + +**注意**:Flag 会进存档,不再需要的变量要及时 `deleteField`,避免一直残留在存档里。 + 想从 `state` 出发找到 Flag 对象,见[数据端总览](./data-state-overview.md)。 diff --git a/docs/intermediate/hero-attribute.md b/docs/intermediate/hero-attribute.md index 8f11af1..6e9ae83 100644 --- a/docs/intermediate/hero-attribute.md +++ b/docs/intermediate/hero-attribute.md @@ -41,11 +41,9 @@ attr.mul('money', 2); // 金币翻倍 - `ValueModifier`(type `@system/value`):数值加减,最终值 = 原值 + 修饰值; - `PercentageModifier`(type `@system/percentage`):按**基础值**计算百分比,最终值 = 原值 + 基础值 × 修饰值。 -用 `addModifier(name, modifier, save?)` 挂上修饰器,用 `deleteModifier(name, modifier)` 移除(示例里的 `@user/*`、`@motajs/*` 是包名,含义见 [src 导览](./src-tour.md) 的「包从哪来」): +用 `addModifier(name, modifier, save?)` 挂上修饰器,用 `deleteModifier(name, modifier)` 移除: ```ts -import { ValueModifier, PercentageModifier } from '@user/data-base'; - const attr = state.hero.getModifiableAttribute(); // 攻击永久 +5:加一个数值修饰器 @@ -59,6 +57,8 @@ attr.addModifier('def', defDown); attr.deleteModifier('def', defDown); ``` +> 复制说明:片段已省略 `import`(`ValueModifier`、`PercentageModifier` 来自 `@user/data-base`);文件顶部通常已有,不要再粘,报缺少时再补(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + 想要一段**临时**加成时,就先 `addModifier(...)` 挂上修饰器,在不再需要时用 `deleteModifier(...)` 把它移除,加成随即消失;反之,只要一直不移除,它就是永久加成。 `PercentageModifier` 的百分比以**基础值**为基数,而非当前最终值,因此多个百分比修饰器不会彼此叠乘。装备产生的加成走的也是同一套修饰器机制,见[勇士装备](./hero-equipment.md)。 @@ -83,17 +83,31 @@ trial.add('atk', 999); const preview = trial.getFinalAttribute('atk'); ``` -## 示例 +## 示例:永久加攻与临时减防 + +**目标**:让勇士攻击永久 +15;再给一个「防御 -20%」的临时减益,战斗结束后撤掉。 + +**改哪里**:希望效果生效的地方——例如某个事件函数、钩子或道具效果里。 + +**复制什么**: ```ts -// 攻击 +15 永久:直接改基础属性 +// 攻击永久 +15:直接改基础属性 state.hero.getModifiableAttribute().add('atk', 15); -// 防御 -20% 临时:挂一个百分比修饰器,战斗结束后再删除 +// 防御临时 -20%:挂一个百分比修饰器 const weaken = new PercentageModifier(-0.2); state.hero.getModifiableAttribute().addModifier('def', weaken); ``` +> 复制说明:片段已省略 `import`(`PercentageModifier` 来自 `@user/data-base`);文件顶部通常已有,不要再粘,报缺少时再补(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'atk'`、`'def'` 换成你要改的属性名,把 `15`、`-0.2` 换成你的数值(`-0.2` 即 -20%)。 + +**怎么验证**:加攻后读 `state.hero.attribute.getFinalAttribute('atk')`,应比原来高 15;挂上减益后读 `getFinalAttribute('def')`,应比基础值低 20%。 + +**注意**:`add('atk', 15)` 改的是**基础属性**,是永久的;临时减益要自己留住 `weaken` 这个修饰器对象,在不再需要时用 `deleteModifier('def', weaken)` 撤销,否则它会一直生效。 + 想在属性变化时收到通知,可以用属性钩子族的 `onUpdateAttribute`,见[钩子](./hooks.md)。 > 修饰器的底层原理(修饰器如何参与属性求值、加减乘除类修饰器的组合规则等)会在**高级教程**中讲解(预留标记:`高级教程 · 修饰器原理`);待高级教程就位后,此处会替换为链接。 diff --git a/docs/intermediate/hero-equipment.md b/docs/intermediate/hero-equipment.md index 3e90edf..eb0b580 100644 --- a/docs/intermediate/hero-equipment.md +++ b/docs/intermediate/hero-equipment.md @@ -20,13 +20,31 @@ `equip` 的 `autoUnload` 参数默认为 `true`:当要装备的装备当前穿在别的槽上时,自动把它从原槽卸下。`equip` 与 `unequip` 都会返回被卸下的装备 uid(没有则为 `undefined`)。 +**目标**:给勇士获得一件装备并穿上 0 号槽,随后再把它卸下。 + +**改哪里**:你要操作装备的地方——例如某个事件函数或道具效果里。 + +**复制什么**: + ```ts +// 获得一件新装备实例,拿到它的 uid const uid = state.hero.items.equipment.add('sword'); +// 穿到 0 号槽;返回被自动卸下的装备 uid(没有则 undefined) state.hero.equip.equip(uid, 0); + +// 卸下 0 号槽,返回被卸下的装备 uid const off = state.hero.equip.unequip(0); ``` +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员,一般无需额外引入);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'sword'` 换成你的装备 id 或图块数字;把 `0`(槽位)换成目标槽的索引或名称;`uid`、`off` 不需要时可省去接收。 + +**怎么验证**:穿装备后看 `state.hero.equip.getEquipped(0)` 是否返回该 uid、`state.hero.equip.equipped(uid)` 是否为 `true`;卸下后应为 `undefined` / `false`。 + +**注意**:`equip` 的 `autoUnload` 默认为 `true`(自动从原槽卸下);要事先判断能否装备,用 `canEquipTo(uid, slot)`,它返回 `CanEquip` / `CannotEquip` / `NeedReplace`。 + ## 装备实例仓库(IHeroEquipsStore) `state.hero.items.equipment` 管的是「背包里所有的装备实例」——同一件装备可以有多件,各自独立,所以这里存的是**实例**而非装备本身。它提供: diff --git a/docs/intermediate/hero-items.md b/docs/intermediate/hero-items.md index 637c1f3..efce8fe 100644 --- a/docs/intermediate/hero-items.md +++ b/docs/intermediate/hero-items.md @@ -27,6 +27,12 @@ `item` 参数可以传道具的图块数字或字符串 id(图块数字的含义见[地图图块](./map-tiles.md))。 +**目标**:给勇士发一把黄钥匙、扣掉两把、再使用一把,并查回持有数量。 + +**改哪里**:你要发放或消耗道具的地方——例如某个事件函数或道具效果里。 + +**复制什么**: + ```ts // 发一把黄钥匙(+1) state.hero.items.addItem('yellow-key'); @@ -41,6 +47,14 @@ state.hero.items.useItem('yellow-key'); const count = state.hero.items.itemCount('yellow-key'); ``` +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员,一般无需额外引入);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'yellow-key'` 换成你的道具 id 或图块数字;只用得到哪几行就留哪几行,不必全抄。 + +**怎么验证**:执行后看 `state.hero.items.itemCount('yellow-key')` 有没有随之变化;`useItem` 会让 `Consumable` 类道具数量减一。 + +**注意**:对 `Pick` 类道具调用 `addItem` 会**立刻触发它的效果**、不进入背包;`useItem` 只对 `Constant` 与 `Consumable` 生效,对其它类别不起作用。`count` 只在需要数量时才写。 + ## 迭代背包 想一次看遍勇士拥有的全部道具,用 `iterateItems()`。它每一项的键是道具图块数字,值是道具状态: @@ -56,6 +70,14 @@ for (const [num, item] of state.hero.items.iterateItems()) { 道具「被捡起或使用时具体做什么」,写在内容层的 `src/content/item.ts`,用 `IItemEffect` 描述:`useEffect` 在 `Pick` 拾取或 `Constant` / `Consumable` 使用时触发,`canUse` 决定能否使用,`useEvent` 关联使用事件。道具效果可以调用 `state`(数据端主对象)与道具数据,因而能修改勇士属性、设置 Flag、发送提示等。 +下面是一个完整的道具效果示例。 + +**目标**:某件道具被捡起或使用时,给勇士加 5 点攻击,并弹出一条提示。 + +**改哪里**:内容层 `src/content/item.ts` 中该道具对应的效果条目。 + +**复制什么**: + ```ts // src/content/item.ts(内容层) export const item200: ItemEffect = { @@ -66,4 +88,12 @@ export const item200: ItemEffect = { }; ``` +> 复制说明:片段已省略 `import`(`ItemEffect` 等类型来自内容层);这是**内容层**文件,不是你平时写逻辑的 `src/data`。若编辑器提示缺少名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `item200` 的编号换成你的道具编号;把 `useEffect` 里的效果换成你要的(这里是把 `+5` 攻击与提示文字改成你的)。 + +**怎么验证**:在游戏里捡起或使用这件道具,看攻击是否 +5、提示是否弹出。 + +**注意**:`useEffect` 只在 `Pick` 拾取或 `Constant` / `Consumable` 使用时触发,对 `Pick` 用 `useItem` 不生效;想给道具加「能否使用」的条件,用 `canUse`。 + 想了解从 `state` 能取到哪些对象,见[数据端总览](./data-state-overview.md)。 diff --git a/docs/intermediate/hero-location.md b/docs/intermediate/hero-location.md index 0392a20..13e8377 100644 --- a/docs/intermediate/hero-location.md +++ b/docs/intermediate/hero-location.md @@ -42,4 +42,29 @@ const floorId = state.hero.location.floorId; const map = state.hero.location.map; ``` +## 示例:读取勇士位置信息 + +**目标**:读取勇士当前的坐标、朝向与所在楼层,并弹出一条提示。 + +**改哪里**:任何需要这些信息的地方——例如钩子、事件函数或战斗计算里。 + +**复制什么**: + +```ts +const loc = state.hero.getLocation(); +const floorId = state.hero.location.floorId; + +state.emitTip( + `坐标 (${loc.x}, ${loc.y}),朝向 ${loc.direction},楼层 ${floorId}` +); +``` + +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:只保留你要用的那几行;提示文字换成你自己的。 + +**怎么验证**:触发一次,看提示里的坐标、朝向、楼层是否与勇士当前状态一致。 + +**注意**:`floorId` 为 `undefined`、`map` 为 `null` 时表示勇士不处于任何楼层,用到它们前要考虑这种情况(例如勇士尚未上场时)。 + 楼层的结构与激活状态见[地图结构](./map-structure.md);想从 `state` 出发找到勇士与地图对象,见[数据端总览](./data-state-overview.md)。 diff --git a/docs/intermediate/hooks.md b/docs/intermediate/hooks.md index 29cd513..7fa640b 100644 --- a/docs/intermediate/hooks.md +++ b/docs/intermediate/hooks.md @@ -64,16 +64,32 @@ const hook = { ## 注册与移除钩子 -写好了钩子对象,还要挂到目标主对象上。用 `addHook` 完成注册,它会返回一个控制器: +写好了钩子对象,还要挂到目标主对象上。用 `addHook` 完成注册,它会返回一个控制器。 + +**目标**:在勇士某个属性变化时,立刻执行你写好的处理。 + +**改哪里**:希望效果生效的地方——事件函数、道具效果,或 `src/data/hook/` 下你新增的钩子文件都可以。 + +**复制什么**: ```ts -const controller = state.hero.attribute.addHook({ +const hook = { onUpdateAttribute(name, value) { - // 属性变化时的处理 + // 属性变化时要做的事 } -}); +}; + +const controller = state.hero.attribute.addHook(hook); ``` +> 复制说明:片段已省略 `import`;文件顶部通常已有,不要再粘。若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `onUpdateAttribute` 换成你要用的钩子方法名(对照上两张表),把方法体换成你的处理;把 `state.hero.attribute` 换成要挂接的目标主对象。 + +**怎么验证**:手动触发一次对应动作(例如改一次攻击力),看方法体里的效果有没有执行。 + +**注意**:一个钩子方法会对该主对象的**所有**同类动作触发——例如 `onUpdateAttribute` 对每个属性变化都触发,需要时要在方法体里判断 `name`,别误以为只对某一个属性生效。 + 需要移除时,有两种方式:把**原来的钩子对象**传给 `removeHook`,或调用 `addHook` 返回的控制器的 `unload` 方法。 ```ts diff --git a/docs/intermediate/map-structure.md b/docs/intermediate/map-structure.md index 4ffdb95..187615d 100644 --- a/docs/intermediate/map-structure.md +++ b/docs/intermediate/map-structure.md @@ -58,6 +58,12 @@ const active = state.maps.getActiveMap('floor-1'); `layerList` 是一个集合(`Set`),本身没有「按名字直接取」的方法,所以从 `layerList` 里筛出想要的那一个即可:按 **`alias`** 找(最常用),或按 **`zIndex`** 找。 +**目标**:从某个楼层里取出指定图层(例如名为 `ground` 的图层)。 + +**改哪里**:任何需要操作图层的地方——例如某个事件函数或钩子里。 + +**复制什么**: + ```ts const map = state.maps.getMap('floor-1')!; @@ -68,14 +74,20 @@ const ground = [...map.layerList].find(layer => layer.alias === 'ground'); const second = [...map.layerList].find(layer => layer.zIndex === 2); ``` +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'floor-1'` 换成你的楼层 id;把 `'ground'` / `2` 换成你要找的别名或纵深;只保留你要用的那种找法。 + +**怎么验证**:取到的图层若非 `undefined`,再读它的 `alias` 应与你要找的一致;找不到时为 `undefined`。 + +**注意**:别把 `addLayer(alias)` 当成「取图层」——它是**新建**一个图层并返回,用同一个别名调用会再建一个。取已有图层请按上面的方式从 `layerList` 里找。 + 事件层是个例外:它可以直接从楼层的 `eventLayer` 取得,不必去筛 `layerList`。 ```ts const eventLayer = map.eventLayer; // IMapLayer | null ``` -注意别把 `addLayer(alias)` 当成「取图层」——它是**新建**一个图层并返回,用同一个别名调用会再建一个。取已有图层请按上面的方式从 `layerList` 里找。 - 图块的读写见[地图图块](./map-tiles.md)。 > 地图的通行性判定、图块移动与踩踏触发等更底层的内容,会在**高级教程**中讲解(预留标记:`高级教程 · 地图通行与踩踏`);待高级教程就位后,此处会替换为链接。 diff --git a/docs/intermediate/map-tiles.md b/docs/intermediate/map-tiles.md index 8350c6c..94545b0 100644 --- a/docs/intermediate/map-tiles.md +++ b/docs/intermediate/map-tiles.md @@ -31,12 +31,26 @@ for (const layer of map.layerList) { - `setBlock(block, x, y)`:设置指定点的静态图块; - `removeBlock(x, y)`:移除指定点的静态图块。 +**目标**:在坐标 `(3, 5)` 摆一格图块数字为 21 的图块,读一下,再擦掉。 + +**改哪里**:拿到目标图层后即可操作——例如某个事件函数或钩子里(取图层的写法见上一节)。 + +**复制什么**: + ```ts layer.setBlock(21, 3, 5); const num = layer.getBlock(3, 5); layer.removeBlock(3, 5); ``` +> 复制说明:片段已省略 `import`;`layer` 是上一步取到的图层对象(`IMapLayer`)。 + +**改什么**:把 `21` 换成你的图块数字;把 `(3, 5)` 换成目标坐标。 + +**怎么验证**:`setBlock` 后 `getBlock(3, 5)` 应返回你写入的数字;`removeBlock` 后再读应为 0。 + +**注意**:`setBlock` 的参数顺序是 `(图块数字, x, y)`,别把坐标写反;这里操作的是「静态图块」,动态图块走另一套接口。 + ## 批量读写 要一次处理一片区域,用批量接口: @@ -47,7 +61,11 @@ layer.removeBlock(3, 5); 返回的数组是对内部存储的拷贝,修改它不会直接改动地图。 -**完整示例:一次写入一片 3 列 × 2 行的区域,再读回来。** +**目标**:一次写入一片 3 列 × 2 行的区域,再把它读回来。 + +**改哪里**:拿到目标图层后即可操作——例如某个事件函数或钩子里。 + +**复制什么**: ```ts const width = 3; @@ -65,6 +83,14 @@ const back = layer.getMapData(5, 5, width, 2); // back 与 data 内容一致:长度 6、按行排列 ``` +> 复制说明:片段已省略 `import`;`layer` 是目标图层对象。 + +**改什么**:把 `width` 与数组内容换成你的图块数字,把 `(5, 5)` 换成起始坐标;数组长度必须是 `width` 的整数倍。 + +**怎么验证**:读回的 `back` 长度应为 `width × 高度`,内容与写入的 `data` 一致。 + +**注意**:高度不用传,由 `array.length / width` 推出(除不尽时引擎会告警)。 + `putMapData` 与 `getMapData` 用的都是「扁平」的一维数组:第 `row * width + col` 项,对应左上角偏移 `(col, row)` 的那一格。日常读写用这两个接口就够了;它们更深入的用法与性能取向会在**高级教程**中讲解(预留标记:`高级教程 · 地图批量接口`);待高级教程就位后,此处会替换为链接。