8.0 KiB
需求综述
本次改动目标:
- 自动化分区激活器:将楼层按游戏进程划分为若干"区域",
到达新区域时自动激活对应楼层、失活旧区域楼层,
从而替代目前繁琐的手动
setActiveStatus调用。 - 楼层尺寸上移至
LayerState:同一楼层的所有图层尺寸应当 保持一致,因此将尺寸的权威来源从MapLayer移至LayerState。
实现思路
1. 有序地图 id 列表
当前 IMapStore.maps 是 ReadonlySet<string>,无序且随楼层创建
自动填充。区域功能需要以下标标识范围,因此需改为有序数组。
修改方案:
IMapStore.maps类型改为ReadonlyArray<string>;- 新增
setMapList(maps: string[]): void,由外部显式指定有序列表 (一般在游戏初始化时调用一次); - 新增
useManualOrder(sort: (arr: string[]) => string[]): void, 允许自定义地图列表排序函数。调用时将当前maps的slice拷贝 传入sort,再对输出做合法性校验:将新旧数组各转为Set, 校验size相等且新集合是旧集合的子集(利用Set.prototype.isSubsetOf); 校验通过后用返回值替换内部的maps。这样当地图是动态生成时, 作者依然可以自定义顺序,而不必手动维护全量列表; createLayerState不再维护maps,maps完全由setMapList管理;- 若
createLayerState传入的 id 不在maps中,仍可正常创建, 不影响存档逻辑,但该楼层不参与任何区域判断。
2. 区域定义与管理
类型定义
/** 单段闭区间 [start, end],start 和 end 均为 maps 下标 */
export interface IMapAreaInterval {
readonly start: number;
readonly end: number;
}
/** 一个区域由一个或多个独立区间组成 */
export type MapArea = IMapAreaInterval[];
接口
setArea(areas: Set<MapArea>): void:一次性设置所有区域信息, 覆盖原有区域定义;每个元素代表一个区域,区域可包含多个区间, 使用Set<MapArea>表示无序区域集合;activeArea(id: string): void:手动激活指定楼层所在区域的所有楼层。 系统遍历areaList,找到包含该楼层 id 的区域后,对该区域内的所有 楼层调用setMapActiveStatus(floor, true);deactiveArea(id: string): void:手动取消激活指定楼层所在区域的 所有楼层,逻辑与activeArea对称;判断时遍历areaList, 此操作为低频调用,无需缓存;
3. 自动分区激活器
接口
useAutoActivitor(enable: boolean): void:是否启用自动激活器。
触发接口
需要一个通知接口供玩家相关模块调用:
notifyEnterFloor(id: string): void:玩家进入指定楼层时调用此接口, 通知地图管理器进行自动激活判断。
逻辑
notifyEnterFloor(id) 的执行流程(每次进入楼层均调用,内部短路):
- 若自动激活器未启用,直接返回;
- 若
isMapActive(id)为true,直接返回(楼层已激活,无需操作); - 遍历
areaList,找出包含id的区域; - 若未找到,直接返回(该楼层不在任何区域内);
- 若
lastFloorId !== null,调用deactiveArea(lastFloorId)失活上一个区域; - 调用
activeArea(id)激活新区域,更新lastFloorId = id。
内部状态
MapStore 新增:
private areaList: Set<MapArea>:所有区域定义;private lastFloorId: string | null = null:上一次触发notifyEnterFloor的楼层 id,用于定位并失活上一个激活区域;private autoActivitorEnabled: boolean = false:自动激活器开关。
4. 楼层尺寸上移至 LayerState
动机
当前 MapLayer.width / MapLayer.height 存储在图层中,
但同一楼层的所有图层尺寸必须一致,权威来源应当是 LayerState。
接口变动
ILayerState 新增:
readonly width: number;
readonly height: number;
addLayer 签名调整:
目前 addLayer(width: number, height: number): IMapLayer,
移除 width/height 参数,改为 addLayer(): IMapLayer,
使用 LayerState 内部存储的尺寸创建图层。
楼层尺寸在 createLayerState 创建时指定,createLayerState 签名改为:
createLayerState(id: string, width: number, height: number): ILayerState;
运行时仍可通过 resizeLayer 修改楼层尺寸,该方法会同步对楼层内所有
图层执行 resize,保持尺寸一致。
resizeLayer 签名调整:
当前 resizeLayer(layer, width, height, keepBlock?) 只 resize 单个图层,
但既然尺寸是楼层级的,建议改为对该楼层的所有图层同步 resize:
resizeLayer(width: number, height: number, keepBlock?: boolean): void;
IMapLayer.resize / IMapLayer.resize2:
从 IMapLayer 接口中移除,保留为 MapLayer 的内部实现,
仅由 LayerState.resizeLayer 调用。
IMapLayer.width / IMapLayer.height:
保留在 IMapLayer 接口中,供外部通过图层对象直接获取尺寸。
其值始终与所属 LayerState 的 width/height 保持一致。
附加建议结论
IMapLayer.setMapRef可见性:保留现有设计,偶尔有外部需求。active状态管理:不需要单独维护区域激活状态;activeArea(id)/deactiveArea(id)是setMapActiveStatus的 快捷方式,遍历区域楼层批量调用即可,无需额外的区域状态字段。notifyEnterFloor返回值:暂不添加,后续有需求再改进。
涉及文件
需要引用的文件
@user/data-base/src/map/types.ts: 全部现有地图接口@user/data-base/src/map/mapStore.ts:MapStore实现类@user/data-base/src/map/layerState.ts:LayerState实现类@user/data-base/src/map/mapLayer.ts:MapLayer实现类
需要修改的文件
@user/data-base/src/map/types.ts
- 新增
IMapAreaInterval接口:区间定义,含start、end - 新增
MapArea类型别名:IMapAreaInterval[],表示一个区域 - 修改
ILayerState:- 新增
readonly width: number和readonly height: number - 修改
addLayer签名,移除width/height参数(使用LayerState自身尺寸) - 修改
resizeLayer签名:移除layer参数,改为对整个楼层所有图层同步 resize
- 新增
- 修改
IMapLayer:- 移除
resize/resize2(改为MapLayer内部方法)
- 移除
- 修改
IMapStore:- 将
readonly maps类型改为ReadonlyArray<string> - 修改
createLayerState签名:新增width: number、height: number参数 - 新增
setMapList(maps: string[]): void - 新增
useManualOrder(sort: (arr: string[]) => string[]): void - 新增
setArea(areas: Set<MapArea>): void - 新增
activeArea(id: string): void - 新增
deactiveArea(id: string): void - 新增
useAutoActivitor(enable: boolean): void - 新增
notifyEnterFloor(id: string): void
- 将
@user/data-base/src/map/mapStore.ts
- 将
maps: Set<string>改为maps: string[] - 修改
createLayerState:添加width/height参数,不再维护maps - 实现
setMapList - 实现
useManualOrder - 新增
private areaList: Set<MapArea> - 新增
private lastFloorId: string | null - 新增
private autoActivitorEnabled: boolean - 实现
setArea、activeArea、deactiveArea - 实现
useAutoActivitor - 实现
notifyEnterFloor
@user/data-base/src/map/layerState.ts
- 新增
width: number和height: number成员(由构造参数初始化) - 修改
addLayer,移除width/height参数,使用this.width/this.height - 修改
resizeLayer,移除layer参数,改为对所有图层同步 resize
@user/data-base/src/map/mapLayer.ts
- 将
resize/resize2改为内部方法(从公共接口移除)