refactor: 修改 mover 名称

This commit is contained in:
unanmed 2026-05-29 14:07:21 +08:00
parent 2c89a4ac37
commit c48f91c25c
9 changed files with 92 additions and 45 deletions

4
dev.md
View File

@ -98,7 +98,7 @@
- 只进行必要的非空判断,非必要时直接使用非空断言 `!`
- 除非参数要求传入函数等情况,不建议在函数内定义局部函数。
- 语句尽量不换行,除非必要,尤其注意三元运算符与 `private readonly` 类成员。
- 任何时候都不应该写 `getter``setter`
- 一般不建议写 `getter``setter`,但某些场景下还是可以使用的
## 双端分离
@ -133,4 +133,4 @@
| `@user/data-common | Layer 0 | 公共层,定义 `IDataCommon` 及公共无依赖接口 |
| `@user/data-base` | Layer 1 | 数据层,定义 `IStateBase` 及可存档游戏数据(地图、怪物、玩家属性等) |
| `@user/data-system` | Layer 2 | 执行层,定义 `ICoreState`,依赖数据层实现玩家控制、战斗计算等影响游戏进程的动作 |
| `@user/data-state` | — | 数据端的顶层模块,指导 Layer 2 的执行行为,不直接参与执行 |
| `@user/data-state` | Layer 3 | 数据端的顶层模块,一般仅用于初始化以及仅供渲染端调用的顶层模块 |

View File

@ -3,8 +3,8 @@ import {
FaceDirection,
getFaceMovement,
HeroAnimateDirection,
IHeroMover,
IHeroMovingHooks,
IHeroMoveController,
IHeroMoveControllerHooks,
nextFaceDirection
} from '@user/data-base';
import { IMapLayer } from '@user/data-base';
@ -55,7 +55,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
new TextureRowSplitter();
/** 勇士钩子 */
readonly controller: IHookController<IHeroMovingHooks>;
readonly controller: IHookController<IHeroMoveControllerHooks>;
/** 勇士每个朝向的贴图对象 */
readonly textureMap: Map<FaceDirection, IMaterialFramedData> = new Map();
/** 勇士渲染实体,与 `entities[0]` 同引用 */
@ -73,7 +73,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
constructor(
readonly renderer: IMapRenderer,
readonly layer: IMapLayer,
readonly hero: IHeroMover
readonly hero: IHeroMoveController
) {
this.controller = hero.addHook(new MapHeroHook(this));
this.controller.load();
@ -107,7 +107,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
private addHeroMoving(
renderer: IMapRenderer,
layer: IMapLayer,
hero: IHeroMover
hero: IHeroMoveController
) {
if (isNil(hero.image)) {
logger.warn(88);
@ -451,7 +451,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
}
}
class MapHeroHook implements Partial<IHeroMovingHooks> {
class MapHeroHook implements Partial<IHeroMoveControllerHooks> {
constructor(readonly hero: MapHeroRenderer) {}
onSetImage(image: ImageIds): void {

View File

@ -1,4 +1,4 @@
import { IHeroMover } from '@user/data-base';
import { IHeroMoveController } from '@user/data-base';
import { IMapLayer } from '@user/data-base';
import {
IMapDoorRenderer,
@ -14,7 +14,7 @@ import { IOnMapTextRenderer } from './types';
export class MapExtensionManager implements IMapExtensionManager {
/** 勇士状态至勇士渲染器的映射 */
readonly heroMap: Map<IHeroMover, IMapHeroRenderer> = new Map();
readonly heroMap: Map<IHeroMoveController, IMapHeroRenderer> = new Map();
/** 地图图层到门渲染器的映射 */
readonly doorMap: Map<IMapLayer, IMapDoorRenderer> = new Map();
/** 单例的文字渲染拓展(独立图层) */
@ -22,7 +22,10 @@ export class MapExtensionManager implements IMapExtensionManager {
constructor(readonly renderer: IMapRenderer) {}
addHero(state: IHeroMover, layer: IMapLayer): IMapHeroRenderer | null {
addHero(
state: IHeroMoveController,
layer: IMapLayer
): IMapHeroRenderer | null {
if (this.heroMap.has(state)) {
logger.error(45, 'hero renderer');
return null;
@ -32,7 +35,7 @@ export class MapExtensionManager implements IMapExtensionManager {
return heroRenderer;
}
removeHero(state: IHeroMover): void {
removeHero(state: IHeroMoveController): void {
const renderer = this.heroMap.get(state);
if (!renderer) return;
renderer.destroy();

View File

@ -2,7 +2,7 @@ import { ITexture, Font } from '@motajs/render';
import {
FaceDirection,
HeroAnimateDirection,
IHeroMover
IHeroMoveController
} from '@user/data-base';
import { IMapLayer } from '@user/data-base';
@ -10,7 +10,7 @@ import { IMapRenderResult } from '../types';
export interface IMapExtensionManager {
/** 勇士状态至勇士渲染器的映射 */
readonly heroMap: Map<IHeroMover, IMapHeroRenderer>;
readonly heroMap: Map<IHeroMoveController, IMapHeroRenderer>;
/** 地图图层到门渲染器的映射 */
readonly doorMap: Map<IMapLayer, IMapDoorRenderer>;
/** 单例的文字渲染拓展(独立图层) */
@ -21,13 +21,16 @@ export interface IMapExtensionManager {
* @param state
* @param layer
*/
addHero(state: IHeroMover, layer: IMapLayer): IMapHeroRenderer | null;
addHero(
state: IHeroMoveController,
layer: IMapLayer
): IMapHeroRenderer | null;
/**
*
* @param state
*/
removeHero(state: IHeroMover): void;
removeHero(state: IHeroMoveController): void;
/**
*

View File

@ -87,6 +87,24 @@ export class HeroAttribute<THero> implements IHeroAttribute<THero> {
this.finalAttribute[name] = value;
}
*catchCalculateProgress<K extends keyof THero>(name: K) {
const modifierList = this.modifier.get(name);
if (!modifierList) return;
const baseValue = this.attribute[name];
let value = baseValue;
for (const modifier of modifierList as IHeroModifier<THero[K]>[]) {
const nextValue = modifier.modify(value, baseValue, name);
// 部署之后就没必要弹这个警告了,额外判断反而可能会有一定的性能损失,直接 tree-shaking 优化掉
if (import.meta.env.DEV && this.isSameReference(value, nextValue)) {
const modiferName = modifier.constructor.name;
logger.warn(109, modiferName, String(name));
}
value = nextValue;
yield [modifier, value] as [IHeroModifier<THero[K]>, THero[K]];
}
}
getBaseAttribute<K extends keyof THero>(name: K): THero[K] {
return this.attribute[name];
}

View File

@ -1,14 +1,18 @@
import { Hookable, HookController, IHookController } from '@motajs/common';
import { isNil } from 'lodash-es';
import { getFaceMovement, nextFaceDirection } from '@user/data-common';
import { IHeroFollower, IHeroMover, IHeroMovingHooks } from './types';
import {
IHeroFollower,
IHeroMoveController,
IHeroMoveControllerHooks
} from './types';
import { FaceDirection } from '@user/data-common';
const DEFAULT_HERO_IMAGE: ImageIds = 'hero.png';
export class HeroMover
extends Hookable<IHeroMovingHooks>
implements IHeroMover
export class HeroMoveController
extends Hookable<IHeroMoveControllerHooks>
implements IHeroMoveController
{
x: number = 0;
y: number = 0;
@ -22,8 +26,8 @@ export class HeroMover
readonly followers: IHeroFollower[] = [];
protected createController(
hook: Partial<IHeroMovingHooks>
): IHookController<IHeroMovingHooks> {
hook: Partial<IHeroMoveControllerHooks>
): IHookController<IHeroMoveControllerHooks> {
return new HookController(this, hook);
}

View File

@ -2,7 +2,7 @@ import { HeroAttribute } from './attribute';
import {
IHeroAttribute,
IHeroModifier,
IHeroMover,
IHeroMoveController,
IHeroState,
IHeroStateSave,
IModifierStateSave,
@ -16,11 +16,11 @@ export class HeroState<THero> implements IHeroState<THero> {
private readonly registry: Map<string, () => IHeroModifier> = new Map();
constructor(
public mover: IHeroMover,
public mover: IHeroMoveController,
public attribute: IHeroAttribute<THero>
) {}
attachMover(mover: IHeroMover): void {
attachMover(mover: IHeroMoveController): void {
this.mover = mover;
}
@ -28,7 +28,7 @@ export class HeroState<THero> implements IHeroState<THero> {
this.attribute = attribute;
}
getHeroMover(): IHeroMover {
getHeroMover(): IHeroMoveController {
return this.mover;
}

View File

@ -4,10 +4,10 @@ import { FaceDirection, ISaveableContent } from '@user/data-common';
//#region 勇士属性
export interface IHeroModifier<
T = unknown,
K = unknown,
V = unknown,
S = unknown
> extends ISaveableContent<S> {
Save = unknown
> extends ISaveableContent<Save> {
/** 修饰器类型 */
readonly type: string;
/** 修饰器优先级 */
@ -40,12 +40,12 @@ export interface IHeroModifier<
* @param baseValue
* @param name
*/
modify(value: T, baseValue: T, name: PropertyKey): T;
modify(value: K, baseValue: K, name: PropertyKey): K;
/**
*
*/
clone(): IHeroModifier<T, V>;
clone(): IHeroModifier<K, V>;
}
export interface IModifierStateSave {
@ -129,7 +129,7 @@ export interface IHeroAttribute<THero> extends IReadonlyHeroAttribute<THero> {
*/
addModifier<K extends keyof THero>(
name: K,
modifier: IHeroModifier<THero[K], unknown>
modifier: IHeroModifier<THero[K]>
): void;
/**
@ -139,7 +139,7 @@ export interface IHeroAttribute<THero> extends IReadonlyHeroAttribute<THero> {
*/
deleteModifier<K extends keyof THero>(
name: K,
modifier: IHeroModifier<THero[K], unknown>
modifier: IHeroModifier<THero[K]>
): void;
/**
@ -147,6 +147,15 @@ export interface IHeroAttribute<THero> extends IReadonlyHeroAttribute<THero> {
* @param cloneModifier
*/
clone(cloneModifier?: boolean): IHeroAttribute<THero>;
/**
*
*
* @param name
*/
catchCalculateProgress<K extends keyof THero>(
name: K
): Iterable<[IHeroModifier<THero[K]>, THero[K]]>;
}
//#endregion
@ -169,7 +178,7 @@ export interface IHeroFollower {
alpha: number;
}
export interface IHeroMovingHooks extends IHookBase {
export interface IHeroMoveControllerHooks extends IHookBase {
/**
*
* @param x
@ -253,7 +262,7 @@ export interface IHeroMovingHooks extends IHookBase {
onSetFollowerAlpha(identifier: string, alpha: number): void;
}
export interface IHeroMover extends IHookable<IHeroMovingHooks> {
export interface IHeroMoveController extends IHookable<IHeroMoveControllerHooks> {
/** 勇士横坐标 */
readonly x: number;
/** 勇士纵坐标 */
@ -372,7 +381,7 @@ export interface IHeroState<THero> extends ISaveableContent<
IHeroStateSave<THero>
> {
/** 勇士移动对象 */
readonly mover: IHeroMover;
readonly mover: IHeroMoveController;
/** 勇士属性对象 */
readonly attribute: IReadonlyHeroAttribute<THero>;
@ -380,12 +389,12 @@ export interface IHeroState<THero> extends ISaveableContent<
*
* @param mover
*/
attachMover(mover: IHeroMover): void;
attachMover(mover: IHeroMoveController): void;
/**
*
*/
getHeroMover(): IHeroMover;
getHeroMover(): IHeroMoveController;
/**
*

View File

@ -17,7 +17,7 @@ import {
} from '@user/data-common';
import {
EnemyManager,
HeroMover,
HeroMoveController,
IEnemyManager,
HeroAttribute,
HeroState,
@ -69,23 +69,23 @@ import { logger } from '@motajs/common';
import { ISaveSystem, SaveSystem } from './save';
export class CoreState implements ICoreState {
// Layer 0 公共层
// Layer 0 公共层,最底层的接口,不会依赖任何其他内容,一般是工具性接口及不需要存档的数据
readonly roleFace: IRoleFaceBinder;
readonly faceManager: IFaceManager;
readonly tileStore: ITileStore<LegacyTileData>;
// Layer 1 数据层,所有可存档内容都在这
// Layer 1 数据层,所有可存档内容都在这,一般用于数据存储
readonly maps: IMapStore;
readonly hero: IHeroState<IHeroAttr>;
readonly enemyManager: IEnemyManager<IEnemyAttr>;
readonly flags: IFlagSystem;
// Layer 2 执行层,游戏逻辑对象都在这
// Layer 2 执行层,游戏逻辑对象都在这,包括一些需要操作数据层的逻辑系统等
readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
readonly triggerRegistry: ITriggerRegistry;
readonly triggerCollector: ITriggerCollector;
// 用户层内容,也就是最顶层的内容,一般仅用于初始化
// Layer 3 用户层,也就是最顶层的内容,一般仅用于初始化以及仅供渲染端调用的顶层模块
readonly loadProgress: ILoadProgressTotal;
readonly dataLoader: IMotaDataLoader;
readonly saveSystem: ISaveSystem;
@ -129,7 +129,7 @@ export class CoreState implements ICoreState {
this.maps = new MapStore(tileStore, this);
// 勇士
const heroMover = new HeroMover();
const heroMover = new HeroMoveController();
const heroAttribute = new HeroAttribute(HERO_DEFAULT_ATTRIBUTE);
const heroState = new HeroState(heroMover, heroAttribute);
this.hero = heroState;
@ -179,7 +179,7 @@ export class CoreState implements ICoreState {
//#endregion
//#region 顶层初始化
//#region L3 初始化
// 存档系统
this.saveSystem = new SaveSystem();
@ -209,8 +209,12 @@ export class CoreState implements ICoreState {
core.floors as Record<FloorIds, ResolvedFloor>
);
});
//#endregion
}
//#region 私有方法
/**
*
* @param data
@ -355,6 +359,10 @@ export class CoreState implements ICoreState {
this.maps.compareWith(reference);
}
//#endregion
//#region 存档方法
addSaveableContent(id: string, content: ISaveableContent<unknown>): void {
if (this.saveables.has(id)) {
logger.warn(112, id);
@ -385,4 +393,6 @@ export class CoreState implements ICoreState {
this.executors.set(content, executor);
}
}
//#endregion
}