mirror of
https://github.com/motajs/template.git
synced 2026-10-21 23:00:29 +08:00
docs(10-11): 按 D-48 重做实操(概念+基础接口)
- 概念/基础接口 12 篇的实操部分改为六步照抄式(目标/改哪里/复制什么/改什么/怎么验证/注意) - 片段一律去掉 import,统一附复制说明并指向 code-basics 的复制约定 - code-basics 删除 dev.md 的 import 置顶约定句,新增「照抄教程里的代码时,怎么处理 import」小节 - 仅改 docs/intermediate/*.md 与本篇审阅记录
This commit is contained in:
parent
687e248ac1
commit
cfa602f25c
@ -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` 的代码块;留待后续批次。
|
||||
|
||||
|
||||
@ -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 之上增加了类型,用来描述「这份数据长什么样」。类型会在编写与编译阶段被检查,帮你在运行之前就发现错误。
|
||||
|
||||
@ -49,7 +49,7 @@ class MySystem {
|
||||
}
|
||||
```
|
||||
|
||||
本教程后续的代码示例都假设 `state` 已经在当前作用域中(由上面任一方式获得),因此示例不再重复它的来源。
|
||||
本教程后续的代码示例都假设 `state` 已经在当前作用域中(由上面任一方式获得),因此示例不再重复它的来源;示例也一律**省略 `import`**,照抄时怎么处理引入见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」。
|
||||
|
||||
## 常用对象与获取方式
|
||||
|
||||
|
||||
@ -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)。
|
||||
|
||||
@ -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)。
|
||||
|
||||
> 修饰器的底层原理(修饰器如何参与属性求值、加减乘除类修饰器的组合规则等)会在**高级教程**中讲解(预留标记:`高级教程 · 修饰器原理`);待高级教程就位后,此处会替换为链接。
|
||||
|
||||
@ -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` 管的是「背包里所有的装备实例」——同一件装备可以有多件,各自独立,所以这里存的是**实例**而非装备本身。它提供:
|
||||
|
||||
@ -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)。
|
||||
|
||||
@ -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)。
|
||||
|
||||
@ -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
|
||||
|
||||
@ -58,6 +58,12 @@ const active = state.maps.getActiveMap('floor-1');
|
||||
|
||||
`layerList` 是一个集合(`Set<IMapLayer>`),本身没有「按名字直接取」的方法,所以从 `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)。
|
||||
|
||||
> 地图的通行性判定、图块移动与踩踏触发等更底层的内容,会在**高级教程**中讲解(预留标记:`高级教程 · 地图通行与踩踏`);待高级教程就位后,此处会替换为链接。
|
||||
|
||||
@ -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)` 的那一格。日常读写用这两个接口就够了;它们更深入的用法与性能取向会在**高级教程**中讲解(预留标记:`高级教程 · 地图批量接口`);待高级教程就位后,此处会替换为链接。
|
||||
|
||||
<!-- TODO(advanced): 地图批量接口 -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user