TakeAWalk.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import { _decorator, Component, Node, Enum, Vec2, Vec3, v3, EventHandler } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. export enum WalkTargetType {
  4. Line,
  5. Random
  6. }
  7. export enum WalkDeleyDataType {
  8. Const,
  9. Random
  10. }
  11. export enum WalkDeleyType {
  12. Step,
  13. Round
  14. }
  15. @ccclass("WalkDeleyData")
  16. export class WalkDeleyData {
  17. @property({
  18. type: Enum(WalkDeleyDataType),
  19. tooltip: "延迟类型:\nConst:固定时间\nRandom:随机时间"
  20. })
  21. type: WalkDeleyDataType = WalkDeleyDataType.Const;
  22. @property({
  23. tooltip: "延迟时间(常量)", visible() {
  24. return this.type == WalkDeleyDataType.Const;
  25. }
  26. })
  27. private deley_const: number = 0;
  28. @property({
  29. tooltip: "延迟时间(随机值)", visible() {
  30. return this.type == WalkDeleyDataType.Random;
  31. }
  32. })
  33. private deley_random: Vec2 = new Vec2();
  34. public get deley(): number {
  35. if (this.type == WalkDeleyDataType.Const) {
  36. return this.deley_const;
  37. } else if (this.type == WalkDeleyDataType.Random) {
  38. return this.random(this.deley_random.x, this.deley_random.y);
  39. }
  40. return 0;
  41. }
  42. private random(min: number, max: number): number {
  43. return min + Math.random() * (max - min);
  44. }
  45. }
  46. @ccclass('TakeAWalk')
  47. export class TakeAWalk extends Component {
  48. @property({ type: [Node], tooltip: "散步目标点" }) points: Array<Node> = [];
  49. @property({ tooltip: "速度系数(每帧)" }) speed = 1;
  50. @property({
  51. type: Enum(WalkTargetType),
  52. tooltip: "散步目标选择方式:\nLine:根据目标点集合,逐个前往\nRandom:在目标点集合中随机选择前往"
  53. }) walkTargetType: WalkTargetType = WalkTargetType.Random;
  54. @property({
  55. type: Enum(WalkDeleyType),
  56. tooltip: "散步延迟方式:\nStep:每到一个点开始延迟(随机目标,固定使用这个方式)\nRound:所有目标点都经过后开始延迟",
  57. visible() {
  58. return this.walkTargetType == WalkTargetType.Line;
  59. }
  60. }) deleyType: WalkDeleyType = WalkDeleyType.Step;
  61. @property({
  62. tooltip: "线性行走完成后是否循环",
  63. visible() {
  64. return this.walkTargetType == WalkTargetType.Line;
  65. }
  66. }) loop: boolean = true;
  67. @property({
  68. type: EventHandler, tooltip: "非循环模式,完成后的回调",
  69. visible() {
  70. return this.walkTargetType == WalkTargetType.Line && !this.loop;
  71. }
  72. }) complete: EventHandler;
  73. @property({
  74. type: WalkDeleyData, tooltip: "散步延迟数据"
  75. }) deley: WalkDeleyData = new WalkDeleyData();
  76. @property({ tooltip: "初始化时是否设置散步节点到第一个目标点位置" }) resetPosOnLoad = false;
  77. @property({ tooltip: "是否初始化后开始移动" }) walkOnLoad = false;
  78. /**当前移动方向 */
  79. public direction = WalkDirection.up;
  80. private curPointIndex = -1;
  81. private walkTotleFarme = 0;
  82. private beenStop = false;
  83. /**当前目标点 */
  84. public curTargetPoint: Vec3;
  85. /**当前状态 */
  86. public state: WalkState = WalkState.stop;
  87. /**动态速度系数 */
  88. public dySpeed: number = 1;
  89. /**行走总帧数 */
  90. public totleWalkFarme = 0;
  91. start() {
  92. if (this.walkTargetType == WalkTargetType.Random) {
  93. this.deleyType = WalkDeleyType.Step;
  94. }
  95. this.walkOnLoad && this.walk();
  96. }
  97. public walk(): void {
  98. if (this.resetPosOnLoad && this.points[0]) {
  99. this.curPointIndex = 0;
  100. this.node.setPosition(this.points[this.curPointIndex].position);
  101. }
  102. this.beenStop = false;
  103. this.next(0);
  104. }
  105. public stop(): void {
  106. this.beenStop = true;
  107. this.state = WalkState.stop;
  108. }
  109. public pause(): void {
  110. this.state = WalkState.pause;
  111. }
  112. public resume(): void {
  113. this.state = WalkState.walk;
  114. }
  115. private next(deley: number = -1): void {
  116. if (this.walkTargetType == WalkTargetType.Random) {
  117. this.curPointIndex = this.random_int(0, this.points.length - 1);
  118. } else {
  119. this.curPointIndex++;
  120. if (this.curPointIndex >= this.points.length) {
  121. if (this.loop) {
  122. this.curPointIndex = 0;
  123. } else {
  124. this.curPointIndex = -1;
  125. this.stop();
  126. this.complete && this.complete.emit(null);
  127. return;
  128. }
  129. }
  130. }
  131. let d = 0;
  132. if (this.deleyType == WalkDeleyType.Step || (this.deleyType == WalkDeleyType.Round && this.curPointIndex == 0)) {
  133. d = this.deley.deley;
  134. }
  135. deley >= 0 && (d = deley);
  136. this.curTargetPoint = this.points[this.curPointIndex].position;
  137. let distance = Vec3.distance(this.node.position, this.curTargetPoint);
  138. this.walkTotleFarme = distance / this.speed;
  139. this.scheduleOnce(() => {
  140. this.state = WalkState.walk;
  141. }, d);
  142. this.getDirection();
  143. }
  144. update() {
  145. if (this.state == WalkState.walk && !this.beenStop && this.node && this.curTargetPoint) {
  146. this.totleWalkFarme++;
  147. let angle = Math.atan2(this.curTargetPoint.y - this.node.position.y, this.curTargetPoint.x - this.node.position.x);
  148. let x = Math.cos(angle) * this.speed * this.dySpeed;
  149. let y = Math.sin(angle) * this.speed * this.dySpeed;
  150. this.node.setPosition(this.node.position.add(v3(x, y, 0)));
  151. this.walkTotleFarme -= this.dySpeed;
  152. if (this.walkTotleFarme <= 0) {
  153. this.node.setPosition(this.curTargetPoint);
  154. this.next();
  155. this.state = WalkState.stop;
  156. }
  157. }
  158. }
  159. private random_int(min: number, max: number): number {
  160. return min + Math.round(Math.random() * (max - min))
  161. }
  162. private getDirection(): void {
  163. let isH = Math.abs(this.node.position.x - this.curTargetPoint.x) >= Math.abs(this.node.position.y - this.curTargetPoint.y);
  164. if (isH) {
  165. this.direction = this.node.position.x >= this.curTargetPoint.x ? WalkDirection.left : WalkDirection.right;
  166. } else {
  167. this.direction = this.node.position.y >= this.curTargetPoint.y ? WalkDirection.down : WalkDirection.up;
  168. }
  169. }
  170. }
  171. export enum WalkState {
  172. walk,
  173. stop,
  174. pause
  175. }
  176. export enum WalkDirection {
  177. up,
  178. down,
  179. left,
  180. right
  181. }