import { Vec2 } from "cc"; //二维贝塞尔曲线移动 export class Bezier2DMove { private _s: Vec2;//起始点 private _e: Vec2;//终点 private _k: Vec2;//控制点 private _percentSpeed: number; private _percentAddSpeed: number; private _percent: number;//进度 private _current: Vec2; private _currentDir: Vec2; /** * * @param start_x 起始点 * @param start_y * @param end_x 终点 * @param end_y * @param speed 速度 * @param addSpeed 加速度 * @param controlPointScale 控制点比例 * @param controlPointDir 控制点方向 0(随机1,-1) 2目标点左侧-1右侧1 3重力抛物线 * @param curvRatio 曲线强度比例 * @param ratioRand 曲线强度随机值 */ // 简化一下 constructor(star: Vec2, end: Vec2, speed: number, addSpeed: number, controlPointScale: number = 0.25, controlPointDir = 0, curvRatio: number = 0.1, ratioRand: number = 0.1) { this.init(star.x, star.y, end.x, end.y, speed, addSpeed, controlPointScale, controlPointDir, curvRatio, ratioRand) } init(start_x: number, start_y: number, end_x: number, end_y: number, speed: number, addSpeed: number, controlPointScale: number = 0.25, controlPointDir = 0, curvRatio: number = 0.1, ratioRand: number = 0.1) { this._s = new Vec2(start_x, start_y); this._e = new Vec2(end_x, end_y); this._current = new Vec2(start_x, start_y); this._currentDir = new Vec2(this._e.x - this._s.x, this._e.y - this._s.y).normalize(); this._k = this.getCalculateBezierPoint(this._s, this._e, controlPointScale, controlPointDir, curvRatio, ratioRand); let dis = (new Vec2(end_x, end_y).subtract2f(start_x, start_y)).length(); this._percent = 0; this._percentSpeed = speed / dis; this._percentAddSpeed = addSpeed / dis; } // init(){ // } public get target_pos_x(): number { return this._e.x; } public get target_pos_y(): number { return this._e.y; } public get current_dir(): Vec2 { return this._currentDir; } public get isEnd(): boolean { return this._percent >= 1; } public get percent(): number { return this._percent; } /** * 向目标运动 * @param dt 帧时间 * @param mb 目标点,没有的话为初始定义的点 * @returns */ public MoveTo(dt: number, mb: Vec2 = null): Vec2 { this._percentSpeed += this._percentAddSpeed * dt; this._percent += this._percentSpeed * dt; //if(this._percent>1) this._percent=1; let nextpos = this.getPos(this._percent, this._s, this._k, mb == null ? this._e : mb); if (nextpos.x != this._current.x || nextpos.y != this._current.y) { this._currentDir.x = nextpos.x - this._current.x; this._currentDir.y = nextpos.y - this._current.y; this._currentDir.normalize(); } this._current.x = nextpos.x; this._current.y = nextpos.y; return this._current; } /** * 获取进度位置 * @param t 当前时间进度 0-1 * @param a 起点 * @param b 控制点 * @param c 终点 */ private _ab = new Vec2(); private _bc = new Vec2(); private _ac = new Vec2(); private getPos(t: number, a: Vec2, b: Vec2, c: Vec2): Vec2 { Vec2.lerp(this._ab, a, b, t); Vec2.lerp(this._bc, b, c, t); Vec2.lerp(this._ac, this._ab, this._bc, t); return this._ac; } //获取控制点 private getCalculateBezierPoint(a: Vec2, b: Vec2, controlPointScale: number, controlPointDir: number, curvRatio: number, ratioRand: number): Vec2 { const ab = new Vec2(); Vec2.lerp(ab, a, b, controlPointScale); const diff = a.clone().subtract(b); const perpendicular = new Vec2(-diff.y, diff.x); let normal = perpendicular.normalize(); if (controlPointDir == 2) { controlPointDir = a.x >= b.x ? 1 : -1; } else if (controlPointDir == 0) { //随机 controlPointDir = this.getRandomDir(); } else if (controlPointDir == 3) { //重力 controlPointDir = 1; normal = new Vec2(0, 1); } curvRatio += this.getRandomNumberInRange(-ratioRand, ratioRand); const dis = diff.length() * curvRatio * controlPointDir; return ab.add(normal.multiplyScalar(dis)); } // private getRandomNumberInRange(min: number, max: number): number { return Math.random() * (max - min) + min; } private getRandomDir(): number { return Math.floor(Math.random() * 2) === 0 ? -1 : 1; } }