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 { 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 ) return; if(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(); } } }