Files
heros/assets/script/game/hero/MonMove.ts
walkpan 9fcb6d3121 feat(渲染): 重构渲染层级管理并添加BOSS层级
移除动态渲染层级更新逻辑,改为在实体加载时设置固定层级
- 在Hero和Monster的load方法中设置初始siblingIndex
- 添加BOSS枚举值到IndexSet
- 为Monster添加溢出保护,防止层级索引过大
- 删除墓地位置判断等不再需要的逻辑
2025-11-03 13:36:33 +08:00

135 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { HeroViewComp } from "./HeroViewComp";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { smc } from "../common/SingletonModuleComp";
import { FacSet, IndexSet } from "../common/config/GameSet";
import { Attrs } from "../common/config/HeroAttrs";
/** 怪物移动组件 */
@ecs.register('MonMove')
export class MonMoveComp extends ecs.Comp {
/** 移动方向1向右-1向左 */
direction: number = 1;
/** 目标x坐标 */
targetX: number = 0;
/** 是否处于移动状态 */
moving: boolean = true;
/** 线路标识0=一线(y=120)1=二线(y=80) */
lane: number = 0;
/** 生成顺序:用于同线路内的层级排序,数值越大越晚生成,层级越前 */
spawnOrder: number = 0;
reset() {
this.direction = 1;
this.targetX = 0;
this.moving = true;
this.lane = 0;
this.spawnOrder = 0;
}
}
/** 怪物移动系统 - 专门处理怪物的移动逻辑 */
@ecs.register('MonMoveSystem')
export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
filter(): ecs.IMatcher {
return ecs.allOf(MonMoveComp, HeroViewComp, HeroAttrsComp);
}
update(e: ecs.Entity) {
if (!smc.mission.play || smc.mission.pause) return;
const move = e.get(MonMoveComp);
const model = e.get(HeroAttrsComp);
const view = e.get(HeroViewComp);
// 只处理怪物
if (model.fac !== FacSet.MON) return;
if (!move.moving) return;
const shouldStop = this.checkEnemiesInFace(e);
model.is_atking = this.checkEnemiesInRange(e, model.Attrs[Attrs.DIS]);
// 🔥 移除渲染层级更新:各线路固定,后召唤的天然层级更高,无需动态调整
if (!shouldStop) {
if (model.is_stop || model.is_dead || model.isStun() || model.isFrost()) {
view.status_change("idle");
return;
}
// 怪物简单移动逻辑:向目标方向移动
const delta = (model.Attrs[Attrs.SPEED]/3) * this.dt * move.direction;
const newX = view.node.position.x + delta;
// 限制移动范围
if (this.validatePosition(newX, move)) {
view.status_change("move");
view.node.setPosition(newX, view.node.position.y, 0);
} else {
// 当达到目标位置边界时也切换为idle状态
view.status_change("idle");
// 达到边界是永久停止设置moving为false
move.moving = false;
}
} else {
view.status_change("idle");
// 因为敌人在面前而暂时停止不设置moving为false保持检查状态
}
}
/** 验证目标位置有效性 */
private validatePosition(newX: number, move: MonMoveComp): boolean {
// 我方不能超过右边界,敌方不能超过左边界
return move.direction === 1 ?
newX <= move.targetX :
newX >= move.targetX;
}
/** 检测攻击范围内敌人 */
private checkEnemiesInRange(entity: ecs.Entity, range: number): boolean {
const currentView = entity.get(HeroViewComp);
if (!currentView || !currentView.node) return false;
const currentPos = currentView.node.position;
const team = entity.get(HeroAttrsComp).fac;
let found = false;
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => {
const model = e.get(HeroAttrsComp);
const view = e.get(HeroViewComp);
if (!view || !view.node) return false;
const distance = Math.abs(currentPos.x - view.node.position.x);
if (model.fac !== team && !model.is_dead) {
if (distance <= range) {
found = true;
return true;
}
}
});
return found;
}
/** 检测面前是否有敌人 */
private checkEnemiesInFace(entity: ecs.Entity): boolean {
const currentView = entity.get(HeroViewComp);
if (!currentView || !currentView.node) return false;
const currentPos = currentView.node.position;
const team = entity.get(HeroAttrsComp).fac;
let found = false;
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => {
const model = e.get(HeroAttrsComp);
const view = e.get(HeroViewComp);
if (!view || !view.node) return false;
const distance = Math.abs(currentPos.x - view.node.position.x);
if (model.fac !== team && !model.is_dead) {
if (distance <= 75) {
found = true;
return true;
}
}
});
return found;
}
}