mirror of
https://github.com/motajs/template.git
synced 2026-09-26 21:28:14 +08:00
refactor(04-03): rebind hero renderer to IHeroLocation and existing hooks
- manager.ts / types.ts: heroMap, addHero, removeHero keyed by IHeroLocation - hero.ts: bind IHeroLocation, read getCurrentFaceDirection, use ObjectAnimDirection - MapHeroHook subscribes IHeroLocationHooks / IObjectMoverHooks with existing member names (D-21) - IMapHeroRenderer drops the 8 external drive members per D-20; D-18 / D-22 members preserved - hero.image read converged to one minimal compile bridge annotated for D-18
This commit is contained in:
parent
f6cd958876
commit
a3826bfa6a
@ -2,15 +2,14 @@ import {
|
||||
degradeFace,
|
||||
FaceDirection,
|
||||
getFaceMovement,
|
||||
// @ts-expect-error 需要重构
|
||||
HeroAnimateDirection,
|
||||
// @ts-expect-error 需要重构
|
||||
IHeroMoveController,
|
||||
// @ts-expect-error 需要重构
|
||||
IHeroMoveControllerHooks,
|
||||
nextFaceDirection
|
||||
IObjectMover,
|
||||
IObjectMoverHooks,
|
||||
nextFaceDirection,
|
||||
ObjectAnimDirection,
|
||||
ObjectMoveStep,
|
||||
ObjectMoveType
|
||||
} from '@user/data-common';
|
||||
import { IMapLayer } from '@user/data-base';
|
||||
import { IHeroLocation, IHeroLocationHooks, IMapLayer } from '@user/data-base';
|
||||
import { IMapRenderer, IMapRendererTicker, IMovingBlock } from '../types';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { IHookController, logger } from '@motajs/common';
|
||||
@ -50,15 +49,17 @@ interface HeroRenderEntity {
|
||||
/** 移动的 `Promise`,移动完成时兑现,如果停止,则一直是兑现状态 */
|
||||
promise: Promise<void>;
|
||||
/** 勇士移动的动画方向 */
|
||||
animateDirection: HeroAnimateDirection;
|
||||
animateDirection: ObjectAnimDirection;
|
||||
}
|
||||
|
||||
export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
private static readonly splitter: ITextureSplitter<number> =
|
||||
new TextureRowSplitter();
|
||||
|
||||
/** 勇士钩子 */
|
||||
readonly controller: IHookController<IHeroMoveControllerHooks>;
|
||||
/** 勇士位置钩子 */
|
||||
readonly locationController: IHookController<IHeroLocationHooks>;
|
||||
/** 勇士移动钩子 */
|
||||
readonly moverController: IHookController<IObjectMoverHooks<IHeroLocation>>;
|
||||
/** 勇士每个朝向的贴图对象 */
|
||||
readonly textureMap: Map<FaceDirection, IMaterialFramedData> = new Map();
|
||||
/** 勇士渲染实体,与 `entities[0]` 同引用 */
|
||||
@ -76,17 +77,20 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
constructor(
|
||||
readonly renderer: IMapRenderer,
|
||||
readonly layer: IMapLayer,
|
||||
readonly hero: IHeroMoveController
|
||||
readonly hero: IHeroLocation
|
||||
) {
|
||||
this.controller = hero.addHook(new MapHeroHook(this));
|
||||
this.controller.load();
|
||||
const hook = new MapHeroHook(this);
|
||||
this.locationController = hero.addHook(hook);
|
||||
this.locationController.load();
|
||||
this.moverController = hero.mover.addHook(hook);
|
||||
this.moverController.load();
|
||||
const moving = this.addHeroMoving(renderer, layer, hero);
|
||||
const heroEntity: HeroRenderEntity = {
|
||||
block: moving,
|
||||
identifier: '',
|
||||
targetX: hero.x,
|
||||
targetY: hero.y,
|
||||
direction: hero.direction,
|
||||
direction: hero.getCurrentFaceDirection(),
|
||||
nextDirection: FaceDirection.Unknown,
|
||||
moving: false,
|
||||
animating: false,
|
||||
@ -94,7 +98,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
lastAnimateTime: 0,
|
||||
animateFrame: 0,
|
||||
promise: Promise.resolve(),
|
||||
animateDirection: HeroAnimateDirection.Forward
|
||||
animateDirection: ObjectAnimDirection.Forward
|
||||
};
|
||||
this.heroEntity = heroEntity;
|
||||
this.entities.push(heroEntity);
|
||||
@ -110,19 +114,23 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
private addHeroMoving(
|
||||
renderer: IMapRenderer,
|
||||
layer: IMapLayer,
|
||||
hero: IHeroMoveController
|
||||
hero: IHeroLocation
|
||||
) {
|
||||
if (isNil(hero.image)) {
|
||||
// @ts-expect-error 需要重构(贴图别名来源属 D-18,待用户先改数据端后处理)
|
||||
const imageAlias = hero.image;
|
||||
if (isNil(imageAlias)) {
|
||||
logger.warn(88);
|
||||
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
|
||||
}
|
||||
const image = this.renderer.manager.getImageByAlias(hero.image);
|
||||
const image = this.renderer.manager.getImageByAlias(imageAlias);
|
||||
if (!image) {
|
||||
logger.warn(89, hero.image);
|
||||
logger.warn(89, imageAlias);
|
||||
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
|
||||
}
|
||||
this.updateHeroTexture(image);
|
||||
const tex = this.textureMap.get(degradeFace(hero.direction));
|
||||
const tex = this.textureMap.get(
|
||||
degradeFace(hero.getCurrentFaceDirection())
|
||||
);
|
||||
if (!tex) {
|
||||
return renderer.addMovingBlock(layer, 0, hero.x, hero.y);
|
||||
}
|
||||
@ -167,7 +175,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
if (v.animating) {
|
||||
const dt = time - v.lastAnimateTime;
|
||||
if (dt > v.animateInterval) {
|
||||
if (v.animateDirection === HeroAnimateDirection.Forward) {
|
||||
if (v.animateDirection === ObjectAnimDirection.Forward) {
|
||||
v.animateFrame++;
|
||||
} else {
|
||||
v.animateFrame--;
|
||||
@ -190,7 +198,9 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
|
||||
setImage(image: ITexture): void {
|
||||
this.updateHeroTexture(image);
|
||||
const tex = this.textureMap.get(degradeFace(this.hero.direction));
|
||||
const tex = this.textureMap.get(
|
||||
degradeFace(this.hero.getCurrentFaceDirection())
|
||||
);
|
||||
if (!tex) return;
|
||||
this.heroEntity.block.setTexture(tex);
|
||||
}
|
||||
@ -369,7 +379,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
lastAnimateTime: 0,
|
||||
animateFrame: 0,
|
||||
promise: Promise.resolve(),
|
||||
animateDirection: HeroAnimateDirection.Forward
|
||||
animateDirection: ObjectAnimDirection.Forward
|
||||
};
|
||||
moving.useSpecifiedFrame(0);
|
||||
this.entities.push(entity);
|
||||
@ -434,7 +444,7 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
follower.block.setAlpha(alpha);
|
||||
}
|
||||
|
||||
setHeroAnimateDirection(direction: HeroAnimateDirection): void {
|
||||
setHeroAnimateDirection(direction: ObjectAnimDirection): void {
|
||||
this.heroEntity.animateDirection = direction;
|
||||
}
|
||||
|
||||
@ -450,11 +460,14 @@ export class MapHeroRenderer implements IMapHeroRenderer {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.controller.unload();
|
||||
this.locationController.unload();
|
||||
this.moverController.unload();
|
||||
}
|
||||
}
|
||||
|
||||
class MapHeroHook implements Partial<IHeroMoveControllerHooks> {
|
||||
class MapHeroHook implements Partial<
|
||||
IHeroLocationHooks & IObjectMoverHooks<IHeroLocation>
|
||||
> {
|
||||
constructor(readonly hero: MapHeroRenderer) {}
|
||||
|
||||
onSetImage(image: ImageIds): void {
|
||||
@ -466,33 +479,55 @@ class MapHeroHook implements Partial<IHeroMoveControllerHooks> {
|
||||
this.hero.setImage(texture);
|
||||
}
|
||||
|
||||
onSetPosition(x: number, y: number): void {
|
||||
onSetPos(x: number, y: number): void {
|
||||
if (this.hero.hero.mover.moving) return;
|
||||
this.hero.setPosition(x, y);
|
||||
}
|
||||
|
||||
onTurnHero(direction: FaceDirection): void {
|
||||
this.hero.turn(direction);
|
||||
}
|
||||
|
||||
onStartMove(): void {
|
||||
async onMoveStart(): Promise<void> {
|
||||
this.hero.startMove();
|
||||
}
|
||||
|
||||
onMoveHero(direction: FaceDirection, time: number): Promise<void> {
|
||||
return this.hero.move(direction, time);
|
||||
async onMoveEnd(): Promise<void> {
|
||||
await this.hero.waitMoveEnd();
|
||||
}
|
||||
|
||||
onEndMove(): Promise<void> {
|
||||
return this.hero.waitMoveEnd();
|
||||
}
|
||||
|
||||
onJumpHero(
|
||||
x: number,
|
||||
y: number,
|
||||
time: number,
|
||||
waitFollower: boolean
|
||||
async onStepEnd(
|
||||
_code: number,
|
||||
step: Readonly<ObjectMoveStep>,
|
||||
tile: IHeroLocation,
|
||||
mover: IObjectMover<IHeroLocation>
|
||||
): Promise<void> {
|
||||
return this.hero.jumpTo(x, y, time, waitFollower);
|
||||
this.hero.setHeroAnimateDirection(mover.currAnimDir);
|
||||
switch (step.type) {
|
||||
case ObjectMoveType.Dir:
|
||||
return this.hero.move(step.move, mover.currentSpeed);
|
||||
case ObjectMoveType.DirFace:
|
||||
this.hero.turn(step.face);
|
||||
return this.hero.move(step.move, mover.currentSpeed);
|
||||
case ObjectMoveType.Special:
|
||||
return this.hero.move(mover.moveDirection, mover.currentSpeed);
|
||||
case ObjectMoveType.Face:
|
||||
this.hero.turn(step.value);
|
||||
break;
|
||||
case ObjectMoveType.Teleport:
|
||||
this.hero.setPosition(tile.x, tile.y);
|
||||
break;
|
||||
case ObjectMoveType.Jump:
|
||||
return this.hero.jumpTo(
|
||||
tile.x,
|
||||
tile.y,
|
||||
mover.currentSpeed,
|
||||
false
|
||||
);
|
||||
case ObjectMoveType.AnimDir:
|
||||
case ObjectMoveType.Speed:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onSetFaceDir(dir: FaceDirection): void {
|
||||
this.hero.turn(dir);
|
||||
}
|
||||
|
||||
onSetAlpha(alpha: number): void {
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
// @ts-expect-error 需要重构
|
||||
import { IHeroMoveController } from '@user/data-base';
|
||||
import { IMapLayer } from '@user/data-base';
|
||||
import { IHeroLocation, IMapLayer } from '@user/data-base';
|
||||
import {
|
||||
IMapDoorRenderer,
|
||||
IMapExtensionManager,
|
||||
@ -15,7 +13,7 @@ import { IOnMapTextRenderer } from './types';
|
||||
|
||||
export class MapExtensionManager implements IMapExtensionManager {
|
||||
/** 勇士状态至勇士渲染器的映射 */
|
||||
readonly heroMap: Map<IHeroMoveController, IMapHeroRenderer> = new Map();
|
||||
readonly heroMap: Map<IHeroLocation, IMapHeroRenderer> = new Map();
|
||||
/** 地图图层到门渲染器的映射 */
|
||||
readonly doorMap: Map<IMapLayer, IMapDoorRenderer> = new Map();
|
||||
/** 单例的文字渲染拓展(独立图层) */
|
||||
@ -23,10 +21,7 @@ export class MapExtensionManager implements IMapExtensionManager {
|
||||
|
||||
constructor(readonly renderer: IMapRenderer) {}
|
||||
|
||||
addHero(
|
||||
state: IHeroMoveController,
|
||||
layer: IMapLayer
|
||||
): IMapHeroRenderer | null {
|
||||
addHero(state: IHeroLocation, layer: IMapLayer): IMapHeroRenderer | null {
|
||||
if (this.heroMap.has(state)) {
|
||||
logger.error(45, 'hero renderer');
|
||||
return null;
|
||||
@ -36,7 +31,7 @@ export class MapExtensionManager implements IMapExtensionManager {
|
||||
return heroRenderer;
|
||||
}
|
||||
|
||||
removeHero(state: IHeroMoveController): void {
|
||||
removeHero(state: IHeroLocation): void {
|
||||
const renderer = this.heroMap.get(state);
|
||||
if (!renderer) return;
|
||||
renderer.destroy();
|
||||
|
||||
@ -1,18 +1,11 @@
|
||||
import { ITexture, Font } from '@motajs/render';
|
||||
import {
|
||||
FaceDirection,
|
||||
// @ts-expect-error 需要重构
|
||||
HeroAnimateDirection,
|
||||
// @ts-expect-error 需要重构
|
||||
IHeroMoveController
|
||||
} from '@user/data-common';
|
||||
import { IMapLayer } from '@user/data-base';
|
||||
import { IHeroLocation, IMapLayer } from '@user/data-base';
|
||||
|
||||
import { IMapRenderResult } from '../types';
|
||||
|
||||
export interface IMapExtensionManager {
|
||||
/** 勇士状态至勇士渲染器的映射 */
|
||||
readonly heroMap: Map<IHeroMoveController, IMapHeroRenderer>;
|
||||
readonly heroMap: Map<IHeroLocation, IMapHeroRenderer>;
|
||||
/** 地图图层到门渲染器的映射 */
|
||||
readonly doorMap: Map<IMapLayer, IMapDoorRenderer>;
|
||||
/** 单例的文字渲染拓展(独立图层) */
|
||||
@ -23,16 +16,13 @@ export interface IMapExtensionManager {
|
||||
* @param state 勇士状态
|
||||
* @param layer 勇士所在图层
|
||||
*/
|
||||
addHero(
|
||||
state: IHeroMoveController,
|
||||
layer: IMapLayer
|
||||
): IMapHeroRenderer | null;
|
||||
addHero(state: IHeroLocation, layer: IMapLayer): IMapHeroRenderer | null;
|
||||
|
||||
/**
|
||||
* 移除勇士渲染拓展
|
||||
* @param state 勇士状态
|
||||
*/
|
||||
removeHero(state: IHeroMoveController): void;
|
||||
removeHero(state: IHeroLocation): void;
|
||||
|
||||
/**
|
||||
* 添加开门动画拓展
|
||||
@ -86,47 +76,6 @@ export interface IMapHeroRenderer {
|
||||
*/
|
||||
removeAllFollowers(): void;
|
||||
|
||||
/**
|
||||
* 设置勇士位置
|
||||
*/
|
||||
setPosition(x: number, y: number): void;
|
||||
|
||||
/**
|
||||
* 开始移动,在移动前需要调用此方法切换勇士状态
|
||||
*/
|
||||
startMove(): void;
|
||||
|
||||
/**
|
||||
* 等待勇士移动停止后,将移动状态切换为停止
|
||||
* @param waitFollower 是否也等待跟随者移动结束
|
||||
*/
|
||||
waitMoveEnd(waitFollower: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* 立刻停止移动,勇士和跟随者瞬移到目标点
|
||||
*/
|
||||
stopMove(): void;
|
||||
|
||||
/**
|
||||
* 勇士朝某个方向移动
|
||||
* @param direction 移动方向
|
||||
*/
|
||||
move(direction: FaceDirection, time: number): Promise<void>;
|
||||
|
||||
/**
|
||||
* 跳跃勇士至目标点
|
||||
* @param x 目标点横坐标
|
||||
* @param y 目标点纵坐标
|
||||
* @param time 跳跃时长
|
||||
* @param waitFollower 是否等待跟随者也跳跃完毕
|
||||
*/
|
||||
jumpTo(
|
||||
x: number,
|
||||
y: number,
|
||||
time: number,
|
||||
waitFollower: boolean
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* 设置勇士不透明度
|
||||
* @param alpha 不透明度
|
||||
@ -140,18 +89,6 @@ export interface IMapHeroRenderer {
|
||||
*/
|
||||
setFollowerAlpha(identifier: string, alpha: number): void;
|
||||
|
||||
/**
|
||||
* 设置勇士移动的动画播放方向,一般后退会使用反向播放的动画,前进使用正向播放的动画
|
||||
* @param direction 动画方向
|
||||
*/
|
||||
setHeroAnimateDirection(direction: HeroAnimateDirection): void;
|
||||
|
||||
/**
|
||||
* 设置勇士朝向
|
||||
* @param direction 勇士朝向,不填表示顺时针旋转
|
||||
*/
|
||||
turn(direction?: FaceDirection): void;
|
||||
|
||||
/**
|
||||
* 摧毁这个勇士渲染拓展,释放相关资源
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user