feat: 地形通行性判断

This commit is contained in:
AncTe committed 2026-06-28 22:42:27 +08:00
1 parent eb34d63e96
commit 0508dfb9e4
9 files changed
+288 -20

No files matched your search

+4 -1
View File
@@ -6,6 +6,7 @@ import { IHeroLocation, IHeroLocationSave, IHeroMover } from './types';
export class HeroLocation implements IHeroLocation {
x: number;
y: number;
floorId: string | undefined = undefined;
readonly state: IDataCommon;
readonly mover: IHeroMover<this>;
@@ -36,13 +37,15 @@ export class HeroLocation implements IHeroLocation {
return {
x: this.x,
y: this.y,
direction: this.mover.faceDirection
direction: this.mover.faceDirection,
floorId: this.floorId
};
}
loadState(state: IHeroLocationSave): void {
this.x = state.x;
this.y = state.y;
this.floorId = state.floorId;
this.mover.setFaceDir(state.direction);
}
}
+26 -14
View File
@@ -12,35 +12,39 @@ import {
HeroMoveCode,
IHeroLocation,
IHeroMover,
IHeroMoverConfig
IHeroMoverConfig,
ITerrainPassChecker
} from './types';
import { isNil } from 'lodash-es';
export class HeroMover<T extends IHeroLocation>
extends ObjectMover<T>
implements IHeroMover<T>
{
readonly tile: T;
/** 本次移动是否不记录进路线系统 */
private noRoute: boolean = false;
/** 本次移动是否忽略地形碰撞检测 */
private ignoreTerrain: boolean = false;
/** 本次移动是否在特定时机触发自动存档 */
private autoSave: boolean = false;
/** 自定义地形通行判定器 */
private terrainChecker: ITerrainPassChecker | null = null;
constructor(tile: T, faceHandler: IFaceHandler<FaceDirection>) {
constructor(
readonly tile: T,
faceHandler: IFaceHandler<FaceDirection>
) {
super(faceHandler);
this.tile = tile;
}
config(config: Readonly<IHeroMoverConfig>): this {
if (config.noRoute !== undefined) {
if (!isNil(config.noRoute)) {
this.noRoute = config.noRoute;
}
if (config.ignoreTerrain !== undefined) {
if (!isNil(config.ignoreTerrain)) {
this.ignoreTerrain = config.ignoreTerrain;
}
if (config.autoSave !== undefined) {
if (!isNil(config.autoSave)) {
this.autoSave = config.autoSave;
}
return this;
@@ -54,6 +58,10 @@ export class HeroMover<T extends IHeroLocation>
};
}
useTerrainChecker(checker: ITerrainPassChecker | null): void {
this.terrainChecker = checker;
}
protected async onMoveStart(
_tile: IHeroLocation,
_controller: Readonly<IMoverController>
@@ -81,9 +89,7 @@ export class HeroMover<T extends IHeroLocation>
if (!this.ignoreTerrain) {
const result = this.checkTerrain(tile, controller);
if (result !== HeroMoveCode.Step) {
return result;
}
if (result !== HeroMoveCode.Step) return result;
}
if (this.autoSave) {
@@ -168,10 +174,16 @@ export class HeroMover<T extends IHeroLocation>
* 检测当前移动方向前方一格的地形是否可通行
*/
private checkTerrain(
_tile: IHeroLocation,
tile: IHeroLocation,
_controller: Readonly<IMoverController>
): HeroMoveCode {
// TODO: 需要地形检测接口(替代 core.noPass / core.canMoveHero)
return HeroMoveCode.Step;
if (!this.terrainChecker) return HeroMoveCode.CannotMove;
const locator: ITileLocator = { x: tile.x, y: tile.y };
const pass = this.terrainChecker.canPass(
locator,
this.moveDirection,
tile.floorId
);
return pass ? HeroMoveCode.Step : HeroMoveCode.CannotMove;
}
}
+42 -2
View File
@@ -1,5 +1,11 @@
import { IFacedTileLocator, IHookBase, IHookable } from '@motajs/common';
import {
IFacedTileLocator,
IHookBase,
IHookable,
ITileLocator
} from '@motajs/common';
import {
FaceDirection,
IDataCommonExtended,
IObjectMovable,
IObjectMover,
@@ -186,13 +192,24 @@ export interface IHeroAttribute<THero> extends IReadonlyHeroAttribute<THero> {
//#region 勇士位置
export interface IHeroLocationSave extends Readonly<IFacedTileLocator> {}
export interface IHeroLocationSave {
/** 当前横坐标 */
readonly x: number;
/** 当前纵坐标 */
readonly y: number;
/** 当前朝向 */
readonly direction: FaceDirection;
/** 当前所在楼层 id,undefined 表示尚不处于任何楼层 */
readonly floorId: string | undefined;
}
export interface IHeroLocation
extends
ISaveableContent<IHeroLocationSave>,
IObjectMovable,
IDataCommonExtended {
/** 当前所在楼层 id,undefined 表示尚不处于任何楼层 */
readonly floorId: string | undefined;
/** 勇士的移动对象 */
readonly mover: IObjectMover<this>;
}
@@ -212,6 +229,23 @@ export const enum HeroMoveCode {
CannotMove
}
export interface ITerrainPassChecker {
/** 对应的勇士状态对象 */
readonly hero: IHeroState<unknown>;
/**
* 判断在指定楼层中,从指定坐标向指定方向移动一格是否可通行
* @param locator 当前位置
* @param direction 移动方向
* @param floorId 当前楼层 id,可能为 undefined
*/
canPass(
locator: ITileLocator,
direction: FaceDirection,
floorId: string | undefined
): boolean;
}
export interface IHeroMoverConfig {
/** 本次移动是否不记录进路线系统 */
noRoute?: boolean;
@@ -232,6 +266,12 @@ export interface IHeroMover<T extends IHeroLocation> extends IObjectMover<T> {
* 获取当前移动配置的只读快照
*/
getConfig(): Readonly<IHeroMoverConfig>;
/**
* 设置地形通行判定器,传入 null 移除判定器
* @param checker 地形判定器,null 表示移除
*/
useTerrainChecker(checker: ITerrainPassChecker | null): void;
}
//#endregion