feat(怪物): 添加怪物y轴移动逻辑和死亡时间优化
为怪物添加y轴移动能力,使其能够向目标y坐标移动。同时优化怪物死亡时间,使用单独的monDeadTime变量控制怪物死亡时间,区别于英雄的realDeadTime。主要修改包括: 1. 在MonMoveComp中添加targetY字段用于y轴移动目标 2. 实现y轴移动逻辑和位置检查 3. 为HeroViewComp添加monDeadTime字段并应用
This commit is contained in:
@@ -47,6 +47,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
box_group:number = BoxSet.HERO; // 碰撞组
|
box_group:number = BoxSet.HERO; // 碰撞组
|
||||||
realDeadTime:number=10
|
realDeadTime:number=10
|
||||||
deadCD:number=0
|
deadCD:number=0
|
||||||
|
monDeadTime:number=0.5
|
||||||
// 血条显示相关
|
// 血条显示相关
|
||||||
hpBarShowTime:number = 5; // 血条显示持续时间(秒)
|
hpBarShowTime:number = 5; // 血条显示持续时间(秒)
|
||||||
hpBarShowCD:number = 0; // 血条显示计时器
|
hpBarShowCD:number = 0; // 血条显示计时器
|
||||||
@@ -357,6 +358,12 @@ export class HeroViewComp extends CCComp {
|
|||||||
if(this.model.is_count_dead) return;
|
if(this.model.is_count_dead) return;
|
||||||
this.model.is_count_dead = true; // 防止重复触发,必须存在防止重复调用
|
this.model.is_count_dead = true; // 防止重复触发,必须存在防止重复调用
|
||||||
this.top_node.active=false
|
this.top_node.active=false
|
||||||
|
|
||||||
|
// 怪物使用0.5秒死亡时间,英雄使用realDeadTime
|
||||||
|
if(this.model.fac === FacSet.MON){
|
||||||
|
this.realDeadTime = this.monDeadTime;
|
||||||
|
}
|
||||||
|
|
||||||
// 播放死亡特效
|
// 播放死亡特效
|
||||||
this.as.dead();
|
this.as.dead();
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ export class MonMoveComp extends ecs.Comp {
|
|||||||
lane: number = 0;
|
lane: number = 0;
|
||||||
/** 生成顺序:用于同线路内的层级排序,数值越大越晚生成,层级越前 */
|
/** 生成顺序:用于同线路内的层级排序,数值越大越晚生成,层级越前 */
|
||||||
spawnOrder: number = 0;
|
spawnOrder: number = 0;
|
||||||
|
/** 目标y坐标 */
|
||||||
|
targetY: number = 0;
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.direction = 1;
|
this.direction = 1;
|
||||||
@@ -26,6 +28,7 @@ export class MonMoveComp extends ecs.Comp {
|
|||||||
this.moving = true;
|
this.moving = true;
|
||||||
this.lane = 0;
|
this.lane = 0;
|
||||||
this.spawnOrder = 0;
|
this.spawnOrder = 0;
|
||||||
|
this.targetY = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,26 +62,34 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
view.status_change("idle");
|
view.status_change("idle");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否需要y轴靠近
|
||||||
|
this.checkAndSetTargetY(e);
|
||||||
|
|
||||||
|
// 怪物移动逻辑:同时向目标x和y方向移动
|
||||||
|
const deltaX = (model.Attrs[Attrs.SPEED]/3) * this.dt * move.direction;
|
||||||
|
const newX = view.node.position.x + deltaX;
|
||||||
|
|
||||||
|
let newY = view.node.position.y;
|
||||||
|
if (move.targetY !== 0) {
|
||||||
// 怪物简单移动逻辑:向目标方向移动
|
const deltaY = (model.Attrs[Attrs.SPEED]/3) * this.dt * Math.sign(move.targetY - newY);
|
||||||
const delta = (model.Attrs[Attrs.SPEED]/3) * this.dt * move.direction;
|
newY = newY + deltaY;
|
||||||
const newX = view.node.position.x + delta;
|
if (Math.abs(newY - move.targetY) < Math.abs(deltaY)) {
|
||||||
|
newY = move.targetY;
|
||||||
|
move.targetY = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 限制移动范围
|
// 限制移动范围
|
||||||
if (this.validatePosition(newX, move)) {
|
if (this.validatePosition(newX, move)) {
|
||||||
view.status_change("move");
|
view.status_change("move");
|
||||||
view.node.setPosition(newX, view.node.position.y, 0);
|
view.node.setPosition(newX, newY, 0);
|
||||||
} else {
|
} else {
|
||||||
// 当达到目标位置边界时也切换为idle状态
|
|
||||||
view.status_change("idle");
|
view.status_change("idle");
|
||||||
// 达到边界是永久停止,设置moving为false
|
|
||||||
move.moving = false;
|
move.moving = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
view.status_change("idle");
|
view.status_change("idle");
|
||||||
// 因为敌人在面前而暂时停止,不设置moving为false,保持检查状态
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,4 +203,46 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 检查并设置y轴目标位置 */
|
||||||
|
private checkAndSetTargetY(entity: ecs.Entity): void {
|
||||||
|
const move = entity.get(MonMoveComp);
|
||||||
|
const currentView = entity.get(HeroViewComp);
|
||||||
|
const heroAttrs = entity.get(HeroAttrsComp);
|
||||||
|
|
||||||
|
if (!currentView || !currentView.node || !heroAttrs) return;
|
||||||
|
if (move.targetY !== 0) return;
|
||||||
|
|
||||||
|
const currentPos = currentView.node.position;
|
||||||
|
const team = heroAttrs.fac;
|
||||||
|
|
||||||
|
let nearestHero: ecs.Entity | null = null;
|
||||||
|
let nearestDist = Infinity;
|
||||||
|
|
||||||
|
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => {
|
||||||
|
const model = e.get(HeroAttrsComp);
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
if (!view || !view.node) return;
|
||||||
|
if (model.fac === team || model.is_dead) return;
|
||||||
|
|
||||||
|
const dist = Math.abs(currentPos.x - view.node.position.x);
|
||||||
|
if (dist < nearestDist) {
|
||||||
|
nearestDist = dist;
|
||||||
|
nearestHero = e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!nearestHero || nearestDist > 100) return;
|
||||||
|
|
||||||
|
const heroView = nearestHero.get(HeroViewComp);
|
||||||
|
if (!heroView || !heroView.node) return;
|
||||||
|
|
||||||
|
const heroY = heroView.node.position.y;
|
||||||
|
const yDist = Math.abs(currentPos.y - heroY);
|
||||||
|
|
||||||
|
if (yDist > 50) {
|
||||||
|
const direction = heroY > currentPos.y ? 1 : -1;
|
||||||
|
move.targetY = heroY + direction * 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user