diff --git a/assets/script/game/hero/SACastSystem.ts b/assets/script/game/hero/SACastSystem.ts index b2a2f2e8..667a48c8 100644 --- a/assets/script/game/hero/SACastSystem.ts +++ b/assets/script/game/hero/SACastSystem.ts @@ -253,6 +253,7 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat // 获取施法者位置作为起始位置 const startPos = caster.node.position.clone(); + startPos.y += 50; const targetPos = targets[0]; // 使用第一个目标位置 // console.log(`[SACastSystem]: ${s_uuid}, 起始位置: ${startPos}, 目标位置: ${targetPos}`); @@ -327,11 +328,12 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat if (!model || !view || !view.node) return false; if (model.is_dead) return false; if (model.fac === fac) return false; - const pos = view.node.position; + const pos = view.node.position.clone(); + pos.y += 50; const dist = Math.abs(currentPos.x - pos.x); if (dist <= range) { const laneBias = Math.abs(currentPos.y - pos.y); - results.push({ pos: pos.clone(), dist, laneBias }); + results.push({ pos: pos, dist, laneBias }); } return false; }); diff --git a/assets/script/game/skill/SMoveComp.ts b/assets/script/game/skill/SMoveComp.ts index a03cb1a3..94da3173 100644 --- a/assets/script/game/skill/SMoveComp.ts +++ b/assets/script/game/skill/SMoveComp.ts @@ -94,18 +94,14 @@ export class SMoveDataComp extends ecs.Comp { return; } - // 对于直线运动,只在x轴方向延长,y轴保持不变 - const originalTarget = v3(this.targetPos.x, this.targetPos.y); + // 计算方向向量 + const direction = new Vec3(); + Vec3.subtract(direction, this.targetPos, originalStart); + direction.normalize(); - // 计算x轴方向 - const xDirection = originalTarget.x > originalStart.x ? 1 : -1; - - // 延长720像素,但只在x轴方向 - const extendedTarget = v3( - originalTarget.x + (xDirection * 720), - originalStart.y, // y轴保持起始位置不变 - originalStart.z // z轴保持起始位置不变 - ); + // 延长720像素 + const extendedTarget = new Vec3(); + Vec3.scaleAndAdd(extendedTarget, originalStart, direction, 720); this.startPos.set(originalStart); this.targetPos.set(extendedTarget); @@ -184,10 +180,8 @@ export class SMoveDataComp extends ecs.Comp { private calculateCurrentPosition() { switch (this.runType) { case RType.linear: - // 直线运动:只在x轴移动,y轴保持不变 - this.currentPos.x = this.startPos.x + (this.targetPos.x - this.startPos.x) * this.progress; - this.currentPos.y = this.startPos.y; // y轴保持不变 - this.currentPos.z = this.startPos.z; // z轴保持不变 + // 直线运动 + Vec3.lerp(this.currentPos, this.startPos, this.targetPos, this.progress); break; case RType.bezier: @@ -262,213 +256,3 @@ export class SMoveDataComp extends ecs.Comp { } } -/** - * ==================== 技能移动系统 ==================== - * - * 职责: - * 1. 处理技能实体的移动逻辑 - * 2. 更新技能位置 - * 3. 管理移动生命周期 - * 4. 支持多种移动类型 - * - * 设计理念: - * - 参考DamageQueueComp的实现方式 - * - 独立的移动处理系统 - * - 支持从视图层获取的参数 - */ -@ecs.register('SMoveSystem') -export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { - - filter(): ecs.IMatcher { - return ecs.allOf(SMoveDataComp, SkillView); - } - - entityEnter(entity: ecs.Entity): void { - if(!smc.mission.play || smc.mission.pause) return; - const moveComp = entity.get(SMoveDataComp); - const skillView = entity.get(SkillView); - - if (!moveComp || !skillView || !skillView.node) return; - - // 获取技能配置 - const skillConfig = SkillSet[moveComp.s_uuid]; - if (!skillConfig) { - console.warn(`[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`); - return; - } - - // 根据配置设置移动速度 - if (skillConfig.speed > 0) { - moveComp.speed = skillConfig.speed; - } - - // 根据runType设置初始位置 - this.initializePosition(moveComp, skillView); - - // 开始移动(除了固定位置类型) - if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) { - moveComp.startMove(); - } - - // console.log(`[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`); - } - - /** - * 根据runType初始化技能位置 - */ - private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void { - const node = skillView.node; - - switch(moveComp.runType) { - case RType.linear: - // linear类型:根据atk_x和atk_y调整位置 - const linearPos = v3( - node.position.x + moveComp.atk_x, - node.position.y + moveComp.atk_y, - node.position.z - ); - moveComp.rePos(linearPos); - break; - - case RType.fixed: - // 固定起始位置 - node.setPosition(moveComp.startPos.x, node.position.y, 0); - break; - - case RType.fixedEnd: - // 固定结束位置 - node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, node.position.y, 0); - break; - - default: - // 其他类型(包括bezier):根据atk_x和atk_y调整起始位置 - if (moveComp.atk_x !== 0 || moveComp.atk_y !== 0) { - const adjustedStartPos = v3( - moveComp.startPos.x + moveComp.atk_x * moveComp.scale, - moveComp.startPos.y + moveComp.atk_y, - moveComp.startPos.z - ); - moveComp.startPos.set(adjustedStartPos); - node.setPosition(adjustedStartPos); - } - break; - } - } - - update(entity: ecs.Entity): void { - if(!smc.mission.play || smc.mission.pause) return; - const moveComp = entity.get(SMoveDataComp); - const skillView = entity.get(SkillView); - - if (!moveComp || !skillView || !skillView.node) return; - - // 更新移动进度 - const isMoving = moveComp.updateProgress(this.dt); - - if (isMoving) { - // 更新节点位置 - skillView.node.setPosition(moveComp.currentPos); - - // 处理自动旋转(贝塞尔移动) - if (moveComp.runType === RType.bezier) { - this.updateRotation(skillView.node, moveComp); - } - } - - // 检查移动完成 - if (moveComp.isCompleted && moveComp.autoDestroy) { - // 根据结束类型决定是否销毁 - if (moveComp.endType === EType.timeEnd || moveComp.endType === EType.collision) { - entity.destroy(); - } - } - } - - /** - * 更新节点旋转(用于贝塞尔移动) - */ - private updateRotation(node: Node, moveComp: SMoveDataComp) { - if (moveComp.progress < 1) { - // 计算下一帧的位置来确定方向 - const nextProgress = Math.min(moveComp.progress + 0.01, 1); - const nextPos = v3(0, 0, 0); - - // 计算下一个位置 - const t = nextProgress; - const oneMinusT = 1 - t; - const oneMinusTSquared = oneMinusT * oneMinusT; - const tSquared = t * t; - const twoOneMinusTt = 2 * oneMinusT * t; - - nextPos.x = oneMinusTSquared * moveComp.startPos.x + - twoOneMinusTt * moveComp.controlPoint.x + - tSquared * moveComp.targetPos.x; - - nextPos.y = oneMinusTSquared * moveComp.startPos.y + - twoOneMinusTt * moveComp.controlPoint.y + - tSquared * moveComp.targetPos.y; - - // 计算方向角度 - const direction = new Vec3(); - Vec3.subtract(direction, nextPos, moveComp.currentPos); - - if (direction.length() > 0.01) { - const angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI); - node.angle = angle; - } - } - } -} - -/** - * ==================== 技能移动辅助工具 ==================== - */ -export class SMoveHelper { - /** - * 为技能实体设置移动参数 - */ - static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void { - let moveComp = entity.get(SMoveDataComp); - - if (!moveComp) { - moveComp = entity.add(SMoveDataComp); - } - - moveComp.startPos.set(startPos); - moveComp.targetPos.set(targetPos); - moveComp.s_uuid = s_uuid; - - // 从技能配置获取默认参数 - const skillConfig = SkillSet[s_uuid]; - if (skillConfig) { - moveComp.runType = skillConfig.RType || RType.linear; - moveComp.speed = skillConfig.speed || 500; - } - } - - /** - * 检查技能是否正在移动 - */ - static isSkillMoving(entity: ecs.Entity): boolean { - const moveComp = entity.get(SMoveDataComp); - return moveComp ? moveComp.isMoving : false; - } - - /** - * 获取技能移动统计信息 - */ - static getSkillMoveStats(entity: ecs.Entity): any { - const moveComp = entity.get(SMoveDataComp); - return moveComp ? moveComp.getMoveStats() : null; - } - - /** - * 停止技能移动 - */ - static stopSkillMove(entity: ecs.Entity): void { - const moveComp = entity.get(SMoveDataComp); - if (moveComp) { - moveComp.stopMove(); - } - } -} \ No newline at end of file diff --git a/assets/script/game/skill/SMoveSystem.ts b/assets/script/game/skill/SMoveSystem.ts new file mode 100644 index 00000000..afdb8233 --- /dev/null +++ b/assets/script/game/skill/SMoveSystem.ts @@ -0,0 +1,225 @@ +import { v3, Vec3 ,Node} from "cc"; +import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; +import { EType, RType, SkillSet } from "../common/config/SkillSet"; +import { SMoveDataComp } from "./SMoveComp"; +import { smc } from "../common/SingletonModuleComp"; +import { SkillView } from "./SkillView"; + +/** + * ==================== 技能移动系统 ==================== + * + * 职责: + * 1. 处理技能实体的移动逻辑 + * 2. 更新技能位置 + * 3. 管理移动生命周期 + * 4. 支持多种移动类型 + * + * 设计理念: + * - 参考DamageQueueComp的实现方式 + * - 独立的移动处理系统 + * - 支持从视图层获取的参数 + */ +@ecs.register('SMoveSystem') +export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { + + filter(): ecs.IMatcher { + return ecs.allOf(SMoveDataComp, SkillView); + } + + entityEnter(entity: ecs.Entity): void { + if(!smc.mission.play || smc.mission.pause) return; + const moveComp = entity.get(SMoveDataComp); + const skillView = entity.get(SkillView); + + if (!moveComp || !skillView || !skillView.node) return; + + // 获取技能配置 + const skillConfig = SkillSet[moveComp.s_uuid]; + if (!skillConfig) { + console.warn(`[SMoveSystem] 技能配置不存在: ${moveComp.s_uuid}`); + return; + } + + // 根据配置设置移动速度 + if (skillConfig.speed > 0) { + moveComp.speed = skillConfig.speed; + } + + // 根据runType设置初始位置 + this.initializePosition(moveComp, skillView); + + // 开始移动(除了固定位置类型) + if (moveComp.runType !== RType.fixed && moveComp.runType !== RType.fixedEnd) { + moveComp.startMove(); + } + + // console.log(`[SMoveSystem] 技能 ${skillConfig.name} 开始移动,类型: ${moveComp.runType}`); + } + + /** + * 根据runType初始化技能位置 + */ + private initializePosition(moveComp: SMoveDataComp, skillView: SkillView): void { + const node = skillView.node; + + switch(moveComp.runType) { + case RType.linear: + // linear类型:根据atk_x和atk_y调整位置 + const linearPos = v3( + node.position.x + moveComp.atk_x, + node.position.y + moveComp.atk_y, + node.position.z + ); + moveComp.rePos(linearPos); + + // 设置旋转角度 + const direction = new Vec3(); + Vec3.subtract(direction, moveComp.targetPos, moveComp.startPos); + if (direction.length() > 0.01) { + const angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI); + node.angle = angle; + } + break; + + case RType.fixed: + // 固定起始位置 + node.setPosition(moveComp.startPos.x, node.position.y, 0); + break; + + case RType.fixedEnd: + // 固定结束位置 + node.setPosition(moveComp.targetPos.x > 360 ? 300 : moveComp.targetPos.x, node.position.y, 0); + break; + + default: + // 其他类型(包括bezier):根据atk_x和atk_y调整起始位置 + if (moveComp.atk_x !== 0 || moveComp.atk_y !== 0) { + const adjustedStartPos = v3( + moveComp.startPos.x + moveComp.atk_x * moveComp.scale, + moveComp.startPos.y + moveComp.atk_y, + moveComp.startPos.z + ); + moveComp.startPos.set(adjustedStartPos); + node.setPosition(adjustedStartPos); + } + break; + } + } + + update(entity: ecs.Entity): void { + if(!smc.mission.play || smc.mission.pause) return; + const moveComp = entity.get(SMoveDataComp); + const skillView = entity.get(SkillView); + + if (!moveComp || !skillView || !skillView.node) return; + + // 更新移动进度 + const isMoving = moveComp.updateProgress(this.dt); + + if (isMoving) { + // 更新节点位置 + skillView.node.setPosition(moveComp.currentPos); + + // 处理自动旋转(贝塞尔移动) + if (moveComp.runType === RType.bezier) { + this.updateRotation(skillView.node, moveComp); + } + } + + // 检查移动完成 + if (moveComp.isCompleted && moveComp.autoDestroy) { + // 根据结束类型决定是否销毁 + if (moveComp.endType === EType.timeEnd || moveComp.endType === EType.collision) { + entity.destroy(); + } + } + } + + /** + * 更新节点旋转(用于贝塞尔移动) + */ + private updateRotation(node: Node, moveComp: SMoveDataComp) { + if (moveComp.progress < 1) { + // 计算下一帧的位置来确定方向 + const nextProgress = Math.min(moveComp.progress + 0.01, 1); + const nextPos = v3(0, 0, 0); + + // 计算下一个位置 + const t = nextProgress; + const oneMinusT = 1 - t; + const oneMinusTSquared = oneMinusT * oneMinusT; + const tSquared = t * t; + const twoOneMinusTt = 2 * oneMinusT * t; + + nextPos.x = oneMinusTSquared * moveComp.startPos.x + + twoOneMinusTt * moveComp.controlPoint.x + + tSquared * moveComp.targetPos.x; + + nextPos.y = oneMinusTSquared * moveComp.startPos.y + + twoOneMinusTt * moveComp.controlPoint.y + + tSquared * moveComp.targetPos.y; + + // 计算方向角度 + const direction = new Vec3(); + Vec3.subtract(direction, nextPos, moveComp.currentPos); + + if (direction.length() > 0.01) { + const angle = Math.atan2(direction.y, direction.x) * (180 / Math.PI); + node.angle = angle; + } + } + } +} + +/** + * ==================== 技能移动辅助工具 ==================== + */ +export class SMoveHelper { + /** + * 为技能实体设置移动参数 + */ + static setupMoveForSkill(entity: ecs.Entity, startPos: Vec3, targetPos: Vec3, s_uuid: number): void { + let moveComp = entity.get(SMoveDataComp); + + if (!moveComp) { + moveComp = entity.add(SMoveDataComp); + } + + moveComp.startPos.set(startPos); + moveComp.targetPos.set(targetPos); + moveComp.s_uuid = s_uuid; + + // 从技能配置获取默认参数 + const skillConfig = SkillSet[s_uuid]; + if (skillConfig) { + moveComp.runType = skillConfig.RType || RType.linear; + moveComp.speed = skillConfig.speed || 500; + } + } + + /** + * 检查技能是否正在移动 + */ + static isSkillMoving(entity: ecs.Entity): boolean { + const moveComp = entity.get(SMoveDataComp); + return moveComp ? moveComp.isMoving : false; + } + + /** + * 获取技能移动统计信息 + */ + static getSkillMoveStats(entity: ecs.Entity): any { + const moveComp = entity.get(SMoveDataComp); + return moveComp ? moveComp.getMoveStats() : null; + } + + /** + * 停止技能移动 + */ + static stopSkillMove(entity: ecs.Entity): void { + const moveComp = entity.get(SMoveDataComp); + if (moveComp) { + moveComp.stopMove(); + } + } +} \ No newline at end of file diff --git a/assets/script/game/skill/SMoveSystem.ts.meta b/assets/script/game/skill/SMoveSystem.ts.meta new file mode 100644 index 00000000..846f6b9f --- /dev/null +++ b/assets/script/game/skill/SMoveSystem.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "5c973fdb-ae0b-45e9-86e6-c6d7d73bf429", + "files": [], + "subMetas": {}, + "userData": {} +}