Files
heros/assets/script/game/common/ecs/position/BattleMoveSystem.ts
2025-06-24 00:13:13 +08:00

123 lines
4.5 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 { HeroViewComp } from "../../../hero/HeroViewComp";
import { BattleMoveComp } from "./BattleMoveComp";
import { ecs } from "../../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { smc } from "../../SingletonModuleComp";
import { BoxSet } from "../../config/BoxSet";
@ecs.register('BattleMoveSystem')
export class BattleMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
filter(): ecs.IMatcher {
return ecs.allOf(BattleMoveComp, HeroViewComp);
}
update(e: ecs.Entity) {
if(!smc.mission.play||smc.mission.pause) return
const move = e.get(BattleMoveComp);
const view = e.get(HeroViewComp);
if (!move.moving) return;
const shouldStop = this.checkEnemiesInFace(e);
view.is_atking = this.checkEnemiesInRange(e, view.dis);
// 更新渲染层级
this.updateRenderOrder(e);
// 同步状态
if (!shouldStop&&view.fac==1) { //在攻击范围内停止移动 取消这个判断
// if(view.fac==1){
if(view.is_stop||view.is_dead||view.DEBUFF_STUN>0 ||view.DEBUFF_FROST>0) return //停止移动或者死亡不移动
// 计算移动量
const delta = ((view.speed-view.DEBUFF_SLOW)/3) * this.dt * move.direction;
const newX = view.node.position.x + delta;
view.status_change("move")
// 新增墓地位置判断,如果已经在墓地则不再移动
if (view.node.position.x === -1000 || view.node.position.x === 1000) {
return;
}
// 限制移动范围
if (this.validatePosition(newX, move)) {
view.node.setPosition(newX, view.node.position.y, 0);
}
}
else{
view.status_change("idle")
}
// console.log(`[${view.hero_name}] 类型:${view.type} 是否停止:${shouldStop} 方向:${move.direction} 位置:${view.node.position.x.toFixed(1)}`);
}
/** 验证目标位置有效性 */
private validatePosition(newX: number, move: BattleMoveComp): boolean {
// 我方不能超过右边界,敌方不能超过左边界
return move.direction === 1 ?
newX <= move.targetX :
newX >= move.targetX;
}
/** 检测攻击范围内敌人 */
private checkEnemiesInRange(entity: ecs.Entity, range: number): boolean {
const currentPos = entity.get(HeroViewComp).node.position;
const team = entity.get(HeroViewComp).fac;
let found = false;
ecs.query(ecs.allOf(HeroViewComp)).some(e => {
const view = e.get(HeroViewComp);
const distance = Math.abs(currentPos.x - view.node.position.x);
if (view.fac !== team) {
if (distance <= range) {
found = true;
return true;
}
}
});
return found;
}
private checkEnemiesInFace(entity: ecs.Entity): boolean {
const currentPos = entity.get(HeroViewComp).node.position;
const team = entity.get(HeroViewComp).fac;
let found = false;
ecs.query(ecs.allOf(HeroViewComp)).some(e => {
const view = e.get(HeroViewComp);
const distance = Math.abs(currentPos.x - view.node.position.x);
if (view.fac !== team) {
if (distance <= 75) {
found = true;
return true;
}
}
});
return found;
}
/** 更新渲染层级 */
private updateRenderOrder(entity: ecs.Entity) {
const current = entity.get(HeroViewComp);
// 查找所有单位
const allUnits = ecs.query(ecs.allOf(HeroViewComp))
.filter(e => {
const other = e.get(HeroViewComp);
return other.fac === current.fac; // 按阵营分组
})
.map(e => e);
// 按y坐标从小到大排序y坐标越小显示在上层
const sortedUnits = allUnits.sort((a, b) => {
const posA = a.get(HeroViewComp).node.position.y;
const posB = b.get(HeroViewComp).node.position.y;
return posA - posB; // 修改排序顺序
});
// 设置渲染顺序y坐标越小的显示在上层索引越大
sortedUnits.forEach((unit, index) => {
const view = unit.get(HeroViewComp);
view.node.setSiblingIndex(sortedUnits.length - index - 1);
});
}
}