import { Vec3, v3, Node } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { RType, EType, SkillSet } from "../common/config/SkillSet"; import { BoxSet } from "../common/config/GameSet"; import { SkillView } from "./SkillView"; import { smc } from "../common/SingletonModuleComp"; /** * ==================== 技能移动数据组件 ==================== * * 用途: * - 存储技能实体的移动相关数据 * - 管理移动状态和参数 * - 支持多种移动类型(线性、贝塞尔、固定位置等) */ @ecs.register('SMoveDataComp') export class SMoveDataComp extends ecs.Comp { /** 起始位置 */ startPos: Vec3 = v3(0, 0, 0); /** 目标位置 */ targetPos: Vec3 = v3(0, 0, 0); /** 当前位置 */ currentPos: Vec3 = v3(0, 0, 0); /** 移动速度 */ speed: number = 500; /** 移动进度 (0-1) */ progress: number = 0; /** 移动方向缩放 */ scale: number = 1; /** 技能UUID */ s_uuid: number = 0; /** 运行类型 */ runType: RType = RType.linear; /** 结束类型 */ endType: EType = EType.collision; /** 攻击偏移X - 从视图层传递 */ atk_x: number = 0; /** 攻击偏移Y - 从视图层传递 */ atk_y: number = 0; /** 是否正在移动 */ isMoving: boolean = false; /** 是否已完成移动 */ isCompleted: boolean = false; /** 移动开始时间 */ startTime: number = 0; /** 移动总时间 */ totalTime: number = 0; /** 贝塞尔曲线控制点 */ controlPoint: Vec3 = v3(0, 0, 0); /** 是否自动销毁(到达目标后) */ autoDestroy: boolean = true; reset() { this.startPos.set(0, 0, 0); this.targetPos.set(0, 0, 0); this.currentPos.set(0, 0, 0); this.controlPoint.set(0, 0, 0); this.speed = 500; this.progress = 0; this.scale = 1; this.s_uuid = 0; this.runType = RType.linear; this.endType = EType.collision; this.atk_x = 0; this.atk_y = 0; this.isMoving = false; this.isCompleted = false; this.startTime = 0; this.totalTime = 0; this.autoDestroy = true; } /** * 重新计算位置(用于线性移动的延长) */ rePos(originalStart: Vec3) { if (!originalStart) { return; } // 计算方向向量 const direction = new Vec3(); Vec3.subtract(direction, this.targetPos, originalStart); direction.normalize(); // 延长720像素 const extendedTarget = new Vec3(); Vec3.scaleAndAdd(extendedTarget, originalStart, direction, 720); this.startPos.set(originalStart); this.targetPos.set(extendedTarget); } /** * 开始移动 */ startMove() { this.isMoving = true; this.isCompleted = false; this.progress = 0; this.startTime = Date.now(); this.currentPos.set(this.startPos); // 根据移动类型计算总时间和控制点 this.calculateMoveParameters(); } /** * 计算移动参数 */ private calculateMoveParameters() { const distance = Vec3.distance(this.startPos, this.targetPos); this.totalTime = distance / this.speed; // 为贝塞尔移动生成控制点 if (this.runType === RType.bezier) { this.generateBezierControlPoint(); } } /** * 生成贝塞尔曲线控制点 */ private generateBezierControlPoint() { const midPoint = new Vec3(); Vec3.lerp(midPoint, this.startPos, this.targetPos, 0.5); // 计算垂直方向 const direction = new Vec3(); Vec3.subtract(direction, this.targetPos, this.startPos); const perpendicular = v3(-direction.y, direction.x, 0); perpendicular.normalize(); // 根据scale决定控制点方向 const offset = 100 * this.scale; Vec3.scaleAndAdd(this.controlPoint, midPoint, perpendicular, offset); } /** * 更新移动进度 */ updateProgress(deltaTime: number): boolean { if (!this.isMoving || this.isCompleted) { return false; } this.progress += deltaTime / this.totalTime; if (this.progress >= 1) { this.progress = 1; this.isCompleted = true; this.isMoving = false; } // 根据移动类型计算当前位置 this.calculateCurrentPosition(); return true; } /** * 根据移动类型计算当前位置 */ private calculateCurrentPosition() { switch (this.runType) { case RType.linear: // 直线运动 Vec3.lerp(this.currentPos, this.startPos, this.targetPos, this.progress); break; case RType.bezier: this.calculateBezierPosition(this.progress); break; case RType.fixed: case RType.fixedEnd: // 固定位置类型不需要移动 this.currentPos.set(this.startPos); break; default: Vec3.lerp(this.currentPos, this.startPos, this.targetPos, this.progress); break; } } /** * 计算贝塞尔曲线位置 */ private calculateBezierPosition(t: number) { // 二次贝塞尔曲线公式: B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2 const oneMinusT = 1 - t; const oneMinusTSquared = oneMinusT * oneMinusT; const tSquared = t * t; const twoOneMinusTt = 2 * oneMinusT * t; this.currentPos.x = oneMinusTSquared * this.startPos.x + twoOneMinusTt * this.controlPoint.x + tSquared * this.targetPos.x; this.currentPos.y = oneMinusTSquared * this.startPos.y + twoOneMinusTt * this.controlPoint.y + tSquared * this.targetPos.y; this.currentPos.z = oneMinusTSquared * this.startPos.z + twoOneMinusTt * this.controlPoint.z + tSquared * this.targetPos.z; } /** * 停止移动 */ stopMove() { this.isMoving = false; this.isCompleted = true; } /** * 获取移动统计信息(用于调试) */ getMoveStats(): { isMoving: boolean; isCompleted: boolean; progress: number; runType: RType; endType: EType; totalTime: number; elapsedTime: number; } { const currentTime = Date.now(); return { isMoving: this.isMoving, isCompleted: this.isCompleted, progress: this.progress, runType: this.runType, endType: this.endType, totalTime: this.totalTime, elapsedTime: (currentTime - this.startTime) / 1000 }; } }