Bezier2DMove.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { Vec2 } from "cc";
  2. //二维贝塞尔曲线移动
  3. export class Bezier2DMove {
  4. private _s: Vec2;//起始点
  5. private _e: Vec2;//终点
  6. private _k: Vec2;//控制点
  7. private _percentSpeed: number;
  8. private _percentAddSpeed: number;
  9. private _percent: number;//进度
  10. private _current: Vec2;
  11. private _currentDir: Vec2;
  12. /**
  13. *
  14. * @param start_x 起始点
  15. * @param start_y
  16. * @param end_x 终点
  17. * @param end_y
  18. * @param speed 速度
  19. * @param addSpeed 加速度
  20. * @param controlPointScale 控制点比例
  21. * @param controlPointDir 控制点方向 0(随机1,-1) 2目标点左侧-1右侧1 3重力抛物线
  22. * @param curvRatio 曲线强度比例
  23. * @param ratioRand 曲线强度随机值
  24. */
  25. // 简化一下
  26. constructor(star: Vec2, end: Vec2, speed: number, addSpeed: number, controlPointScale: number = 0.25, controlPointDir = 0, curvRatio: number = 0.1, ratioRand: number = 0.1) {
  27. this.init(star.x, star.y, end.x, end.y, speed, addSpeed, controlPointScale, controlPointDir, curvRatio, ratioRand)
  28. }
  29. 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) {
  30. this._s = new Vec2(start_x, start_y);
  31. this._e = new Vec2(end_x, end_y);
  32. this._current = new Vec2(start_x, start_y);
  33. this._currentDir = new Vec2(this._e.x - this._s.x, this._e.y - this._s.y).normalize();
  34. this._k = this.getCalculateBezierPoint(this._s, this._e, controlPointScale, controlPointDir, curvRatio, ratioRand);
  35. let dis = (new Vec2(end_x, end_y).subtract2f(start_x, start_y)).length();
  36. this._percent = 0;
  37. this._percentSpeed = speed / dis;
  38. this._percentAddSpeed = addSpeed / dis;
  39. }
  40. // init(){
  41. // }
  42. public get target_pos_x(): number {
  43. return this._e.x;
  44. }
  45. public get target_pos_y(): number {
  46. return this._e.y;
  47. }
  48. public get current_dir(): Vec2 {
  49. return this._currentDir;
  50. }
  51. public get isEnd(): boolean {
  52. return this._percent >= 1;
  53. }
  54. public get percent(): number {
  55. return this._percent;
  56. }
  57. /**
  58. * 向目标运动
  59. * @param dt 帧时间
  60. * @param mb 目标点,没有的话为初始定义的点
  61. * @returns
  62. */
  63. public MoveTo(dt: number, mb: Vec2 = null): Vec2 {
  64. this._percentSpeed += this._percentAddSpeed * dt;
  65. this._percent += this._percentSpeed * dt;
  66. //if(this._percent>1) this._percent=1;
  67. let nextpos = this.getPos(this._percent, this._s, this._k, mb == null ? this._e : mb);
  68. if (nextpos.x != this._current.x || nextpos.y != this._current.y) {
  69. this._currentDir.x = nextpos.x - this._current.x;
  70. this._currentDir.y = nextpos.y - this._current.y;
  71. this._currentDir.normalize();
  72. }
  73. this._current.x = nextpos.x;
  74. this._current.y = nextpos.y;
  75. return this._current;
  76. }
  77. /**
  78. * 获取进度位置
  79. * @param t 当前时间进度 0-1
  80. * @param a 起点
  81. * @param b 控制点
  82. * @param c 终点
  83. */
  84. private _ab = new Vec2();
  85. private _bc = new Vec2();
  86. private _ac = new Vec2();
  87. private getPos(t: number, a: Vec2, b: Vec2, c: Vec2): Vec2 {
  88. Vec2.lerp(this._ab, a, b, t);
  89. Vec2.lerp(this._bc, b, c, t);
  90. Vec2.lerp(this._ac, this._ab, this._bc, t);
  91. return this._ac;
  92. }
  93. //获取控制点
  94. private getCalculateBezierPoint(a: Vec2, b: Vec2, controlPointScale: number, controlPointDir: number, curvRatio: number, ratioRand: number): Vec2 {
  95. const ab = new Vec2();
  96. Vec2.lerp(ab, a, b, controlPointScale);
  97. const diff = a.clone().subtract(b);
  98. const perpendicular = new Vec2(-diff.y, diff.x);
  99. let normal = perpendicular.normalize();
  100. if (controlPointDir == 2) {
  101. controlPointDir = a.x >= b.x ? 1 : -1;
  102. } else if (controlPointDir == 0) {
  103. //随机
  104. controlPointDir = this.getRandomDir();
  105. } else if (controlPointDir == 3) {
  106. //重力
  107. controlPointDir = 1;
  108. normal = new Vec2(0, 1);
  109. }
  110. curvRatio += this.getRandomNumberInRange(-ratioRand, ratioRand);
  111. const dis = diff.length() * curvRatio * controlPointDir;
  112. return ab.add(normal.multiplyScalar(dis));
  113. }
  114. //
  115. private getRandomNumberInRange(min: number, max: number): number {
  116. return Math.random() * (max - min) + min;
  117. }
  118. private getRandomDir(): number {
  119. return Math.floor(Math.random() * 2) === 0 ? -1 : 1;
  120. }
  121. }