TakeAWalk.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. private curPointIndex = -1;
  79. private walkTotleFarme = 0;
  80. private beenStop = false;
  81. /**当前目标点 */
  82. public curTargetPoint: Vec3;
  83. /**当前状态 */
  84. public state: WalkState = WalkState.Stop;
  85. start() {
  86. if (this.resetPosOnLoad) {
  87. this.curPointIndex = 0;
  88. this.node.setPosition(this.points[this.curPointIndex].position);
  89. }
  90. if (this.walkTargetType == WalkTargetType.Random) {
  91. this.deleyType = WalkDeleyType.Step;
  92. }
  93. this.walkOnLoad && this.walk();
  94. }
  95. public walk(): void {
  96. this.beenStop = false;
  97. this.next(0);
  98. }
  99. public stop(): void {
  100. this.beenStop = true;
  101. this.state = WalkState.Stop;
  102. }
  103. private next(deley: number = -1): void {
  104. if (this.walkTargetType == WalkTargetType.Random) {
  105. this.curPointIndex = this.random_int(0, this.points.length - 1);
  106. } else {
  107. this.curPointIndex++;
  108. if (this.curPointIndex >= this.points.length) {
  109. if (this.loop) {
  110. this.curPointIndex = 0;
  111. } else {
  112. this.curPointIndex = -1;
  113. this.stop();
  114. this.complete && this.complete.emit(null);
  115. return;
  116. }
  117. }
  118. }
  119. let d = 0;
  120. if (this.deleyType == WalkDeleyType.Step || (this.deleyType == WalkDeleyType.Round && this.curPointIndex == 0)) {
  121. d = this.deley.deley;
  122. }
  123. deley >= 0 && (d = deley);
  124. this.curTargetPoint = this.points[this.curPointIndex].position;
  125. let distance = Vec3.distance(this.node.position, this.curTargetPoint);
  126. this.walkTotleFarme = distance / this.speed;
  127. this.scheduleOnce(() => {
  128. this.state = WalkState.Walk;
  129. }, d);
  130. }
  131. update() {
  132. if (this.state == WalkState.Walk && !this.beenStop) {
  133. let angle = Math.atan2(this.curTargetPoint.y - this.node.position.y, this.curTargetPoint.x - this.node.position.x);
  134. let x = Math.cos(angle) * this.speed;
  135. let y = Math.sin(angle) * this.speed;
  136. this.node.setPosition(this.node.position.add(v3(x, y, 0)));
  137. this.walkTotleFarme--;
  138. if (this.walkTotleFarme <= 0) {
  139. this.node.setPosition(this.curTargetPoint);
  140. this.next();
  141. this.state = WalkState.Stop;
  142. }
  143. }
  144. }
  145. private random_int(min: number, max: number): number {
  146. return min + Math.round(Math.random() * (max - min))
  147. }
  148. }
  149. export enum WalkState {
  150. Walk,
  151. Stop,
  152. }