Files
heros/assets/script/game/common/ecs/position/BattleMoveSystem.ts

153 lines
5.8 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, FacSet } from "../../config/BoxSet";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../../config/GameEvent";
import { FightSet } from "../../config/Mission";
@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) { //在攻击范围内停止移动
// if(view.fac==1){
if(view.is_stop||view.is_dead||view.DEBUFF_STUN>0 ||view.DEBUFF_FROST>0) {
view.status_change("idle");
return; //停止移动或者死亡不移动
}
// 新增墓地位置判断,如果已经在墓地则不再移动
if (view.node.position.x === -1000 || view.node.position.x === 1000) {
view.status_change("idle");
return;
}
// 计算移动量
const delta = ((view.speed-view.DEBUFF_SLOW)/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保持检查状态
}
this.checkEnemiesInBase(e)
// 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 checkInGrave(entity: ecs.Entity): boolean {
const view = entity.get(HeroViewComp);
return view.node.position.x === -1000 || view.node.position.x === 1000;
}
/**驾车敌人是否进入我放基地 */
private checkEnemiesInBase(entity: ecs.Entity) {
const view = entity.get(HeroViewComp);
if(view.fac==FacSet.MON){
if(view.atk_heart) return
if(view.node.position.x <= FightSet.HEARTPOS){
oops.message.dispatchEvent(GameEvent.LifeChange,-1)
view.atk_heart=true
view.is_dead=true
view.BUFFCOMP.dead()
view.do_dead()
}
}
}
/** 检测攻击范围内敌人 */
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);
});
}
}