refactor(hero): 统一击退位移逻辑到MoveSystem
将英雄后退的视图层位移操作迁移到MoveSystem统一处理, 通过knockbackVelocity组件属性实现平滑的击退位移衰减与边界钳制, 移除HeroViewComp中直接操作节点位置的代码,解耦视图与战斗逻辑。
This commit is contained in:
@@ -17,6 +17,7 @@ import { mLogger } from "../common/Logger";
|
||||
import { SkillTriggerHelper } from "./SkillTriggerHelper";
|
||||
import { getMonsterGoldDrop } from "../map/RogueConfig";
|
||||
import { MissionEconomy } from "../map/MissionEconomy";
|
||||
import { MoveComp } from "./MoveComp";
|
||||
|
||||
/** 最终伤害数据接口
|
||||
* 用于封装一次攻击计算的所有结果数据
|
||||
@@ -194,6 +195,17 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
if (targetView) {
|
||||
targetView.do_atked(damage, isCrit, damageEvent.s_uuid, knockbackExtra);
|
||||
targetView.playEnd(skillConf.endAnm);
|
||||
|
||||
// 击退位移下沉到 MoveSystem:直接写入 knockbackVelocity,由 MoveSystem 每帧衰减并叠加位移
|
||||
const moveComp = target.get(MoveComp);
|
||||
if (moveComp) {
|
||||
const dist = FightSet.BACK_RANG + knockbackExtra;
|
||||
const isHero = TAttrsComp.fac === FacSet.HERO;
|
||||
// 击退初速度:0.1 秒时间常数衰减,总位移约等于 dist
|
||||
const knockbackSpeed = dist * 16;
|
||||
moveComp.knockbackVelocity = isHero ? -knockbackSpeed : knockbackSpeed;
|
||||
}
|
||||
|
||||
if (isFrost) {
|
||||
TAttrsComp.toFrost();
|
||||
targetView.in_iced(FightSet.FROST_TIME);
|
||||
|
||||
@@ -415,28 +415,10 @@ export class HeroViewComp extends CCComp {
|
||||
this.showDamage(damage, isCrit);
|
||||
}
|
||||
|
||||
private isBackingUp: boolean = false; // 🔥 添加后退状态标记
|
||||
|
||||
//后退
|
||||
back(distance: number = 0) {
|
||||
// 🔥 防止重复调用后退动画
|
||||
if (this.isBackingUp) return;
|
||||
this.isBackingUp = true; // 🔥 设置后退状态
|
||||
|
||||
// 基础击退距离 + 额外距离强化,双方阵营统一
|
||||
const dist = FightSet.BACK_RANG + distance;
|
||||
const isHero = this.model.fac == FacSet.HERO;
|
||||
// 边界钳制:HERO 不越过 BoxSet.LETF_END,MON 不越过 BoxSet.RIGHT_END
|
||||
const tx = isHero
|
||||
? Math.max(BoxSet.LETF_END, this.node.position.x - dist)
|
||||
: Math.min(BoxSet.RIGHT_END, this.node.position.x + dist);
|
||||
|
||||
tween(this.node)
|
||||
.to(0.1, { position: v3(tx, this.node.position.y, 0) })
|
||||
.call(() => {
|
||||
this.isBackingUp = false; // 🔥 动画完成后重置状态
|
||||
})
|
||||
.start();
|
||||
// 击退位移由 MoveSystem 统一处理,视图层只负责触发,不直接操作 position
|
||||
// 具体击退速度由 HeroAtkSystem 在伤害结算后写入 MoveComp.knockbackVelocity
|
||||
}
|
||||
// 伤害计算和战斗逻辑已迁移到 HeroBattleSystem
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export class MoveComp extends ecs.Comp {
|
||||
baseY: number = 0;
|
||||
/** 出生序,用于同条件渲染排序稳定 */
|
||||
spawnOrder: number = 0;
|
||||
/** 击退速度(像素/秒),受击瞬间赋值,每帧指数衰减至 0 */
|
||||
/** 击退速度(像素/秒),受击瞬间由 HeroAtkSystem 赋值,MoveSystem 每帧指数衰减至 0 */
|
||||
knockbackVelocity: number = 0;
|
||||
|
||||
reset() {
|
||||
@@ -85,11 +85,25 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
return;
|
||||
}
|
||||
|
||||
/** 所有移动都锁定在 baseY,避免出现“漂移” */
|
||||
/** 所有移动都锁定在 baseY,避免出现"漂移" */
|
||||
if (view.node.position.y !== move.baseY) {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
|
||||
/** 击退位移:每帧叠加 knockbackVelocity 并指数衰减,与推进解耦 */
|
||||
if (Math.abs(move.knockbackVelocity) > 0.01) {
|
||||
const newX = view.node.position.x + move.knockbackVelocity * this.dt;
|
||||
const clampedX = this.clampByFacBoundary(newX, model.fac);
|
||||
if (Math.abs(clampedX - view.node.position.x) > 0.01) {
|
||||
view.node.setPosition(clampedX, view.node.position.y, 0);
|
||||
}
|
||||
// 时间常数 τ=0.1s:0.1 秒衰减到约 37%,0.3 秒衰减到约 5%,总位移 ≈ v0 * 0.0632
|
||||
move.knockbackVelocity *= Math.exp(-10 * this.dt);
|
||||
if (Math.abs(move.knockbackVelocity) < 0.01) {
|
||||
move.knockbackVelocity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** 准备阶段:双方原地待命,不推进不索敌 */
|
||||
if (!smc.mission.in_fight) {
|
||||
this.clearCombatTarget(model);
|
||||
|
||||
Reference in New Issue
Block a user