feat: 大幅优化战斗体验与编队系统
1. 扩展英雄/怪物网格站位到10个槽位 2. 重构默认攻击距离计算逻辑,按职业动态适配 3. 重做英雄站位与移动系统,新增同阵营间距约束 4. 调整rogue模式怪物数量与强度配置,提升战斗爽感 5. 重构刷怪逻辑为匀速曲线+欠账补刷,优化刷怪节奏
This commit is contained in:
@@ -223,8 +223,10 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
// 未贴近:向怪物方向推进(攻击范围内也继续移动),于接触距离处停下
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
move.direction = dir;
|
||||
// 终止点取接触距离与推进上限的较小者,防止越过 300 继续追击
|
||||
const stopX = Math.min(enemyX - dir * MoveSystem.MELEE_ENGAGE_X, MoveSystem.HERO_ADVANCE_LIMIT_X);
|
||||
// 终止点取接触距离与推进上限的较小者,防止越过 150 继续追击
|
||||
let stopX = Math.min(enemyX - dir * MoveSystem.MELEE_ENGAGE_X, MoveSystem.HERO_ADVANCE_LIMIT_X);
|
||||
// 同阵营最小间距约束:防止近战推进时穿越前方队友
|
||||
stopX = this.clampAllySpacing(e, view, move, model, stopX);
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, dir, speed, stopX);
|
||||
model.is_atking = false;
|
||||
@@ -292,7 +294,9 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
/** 近战贴近怪物的固定接触距离:小于攻击距离 dis,使英雄进攻击范围后仍继续贴近到此间距才停 */
|
||||
private static readonly MELEE_ENGAGE_X = 60;
|
||||
/** 英雄向敌人推进的最远终止点 X,防止近战追敌时无限右移脱离战场 */
|
||||
private static readonly HERO_ADVANCE_LIMIT_X = 300;
|
||||
private static readonly HERO_ADVANCE_LIMIT_X = 100;
|
||||
/** 同阵营英雄间最小间距:小于该值时低优先级一方需让位 */
|
||||
private static readonly ALLY_MIN_GAP_X = 30;
|
||||
|
||||
/**
|
||||
* 计算某个槽位的目标 X。
|
||||
@@ -328,7 +332,57 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
move.direction = dir;
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, dir, speed, targetX);
|
||||
// 同阵营最小间距约束:防止编队挤压时穿越前方队友
|
||||
const clampedTargetX = this.clampAllySpacing(view.ent, view, move, model, targetX);
|
||||
this.moveEntity(view, dir, speed, clampedTargetX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同阵营横向最小间距约束。
|
||||
* Why: 编队/追击时英雄可能挤到一起,低优先级一方需要保持在高优先级身后 ALLY_MIN_GAP_X 处,
|
||||
* 避免视觉重叠与站位混乱。
|
||||
* 优先级:编队优先级高者在前;同级时召唤早(spawnOrder 小)者在前。
|
||||
* @returns 裁剪后的目标 X(保证不越过身前队友)
|
||||
*/
|
||||
private clampAllySpacing(self: ecs.Entity, view: HeroViewComp, selfMove: MoveComp, model: HeroAttrsComp, targetX: number): number {
|
||||
const selfX = view.node.position.x;
|
||||
const selfY = view.node.position.y;
|
||||
let clamped = targetX;
|
||||
|
||||
ecs.query(this.getHeroMoveMatcher()).forEach(e => {
|
||||
if (e === self) return;
|
||||
const attrs = e.get(HeroAttrsComp);
|
||||
const v = e.get(HeroViewComp);
|
||||
const mv = e.get(MoveComp);
|
||||
if (!attrs || !v?.node || !mv) return;
|
||||
if (attrs.is_dead || attrs.is_reviving) return;
|
||||
if (attrs.fac !== model.fac) return;
|
||||
// 只约束同排(Y 差在阈值内)的队友
|
||||
if (Math.abs(v.node.position.y - selfY) > this.minSpacingY) return;
|
||||
|
||||
const otherX = v.node.position.x;
|
||||
// 判断对方是否在自己前方(以目标方向为前)
|
||||
const isAhead = clamped > selfX ? otherX > selfX : otherX < selfX;
|
||||
if (!isAhead) return;
|
||||
|
||||
// 判定谁该在前:编队优先级高者在前;同级时 spawnOrder 小者在前
|
||||
const myPriority = this.getFormationPriority(model);
|
||||
const otherPriority = this.getFormationPriority(attrs);
|
||||
let selfIsFront = false;
|
||||
if (myPriority !== otherPriority) {
|
||||
selfIsFront = myPriority > otherPriority;
|
||||
} else {
|
||||
selfIsFront = selfMove.spawnOrder <= mv.spawnOrder;
|
||||
}
|
||||
|
||||
if (!selfIsFront) {
|
||||
// 自己靠后:不能越过 otherX - ALLY_MIN_GAP_X(朝右)或 otherX + ALLY_MIN_GAP_X(朝左)
|
||||
const limitX = clamped > selfX ? otherX - MoveSystem.ALLY_MIN_GAP_X : otherX + MoveSystem.ALLY_MIN_GAP_X;
|
||||
clamped = clamped > selfX ? Math.min(clamped, limitX) : Math.max(clamped, limitX);
|
||||
}
|
||||
});
|
||||
|
||||
return clamped;
|
||||
}
|
||||
|
||||
private moveEntity(view: HeroViewComp, direction: number, speed: number, stopAtX?: number) {
|
||||
|
||||
Reference in New Issue
Block a user