Joystick_mag.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. const { ccclass, property } = cc._decorator;
  2. /**
  3. * 方向类型
  4. */
  5. export enum DirectionType {
  6. FOUR,
  7. EIGHT,
  8. ALL,
  9. }
  10. /**
  11. * 速度类型
  12. */
  13. export enum SpeedType {
  14. STOP,
  15. NORMAL,
  16. FAST,
  17. }
  18. /**
  19. * 摇杆类型
  20. */
  21. export enum JoystickType {
  22. FIXED,
  23. FOLLOW,
  24. }
  25. /**
  26. * 摇杆类
  27. */
  28. @ccclass
  29. export default class Joystick_mag extends cc.Component {
  30. @property({
  31. type: cc.Node,
  32. displayName: "Dot",
  33. tooltip: "摇杆操纵点",
  34. })
  35. dot = null;
  36. @property({
  37. type: cc.Node,
  38. displayName: "Ring",
  39. tooltip: "摇杆背景节点",
  40. })
  41. ring = null;
  42. @property({
  43. type: cc.Enum(JoystickType),
  44. displayName: "Touch Type",
  45. tooltip: "触摸类型",
  46. })
  47. joystickType = JoystickType.FIXED;
  48. @property({
  49. type: cc.Enum(DirectionType),
  50. displayName: "Direction Type",
  51. tooltip: "方向类型",
  52. })
  53. directionType = DirectionType.ALL;
  54. @property({
  55. type: cc.Node,
  56. tooltip: "摇杆所在位置",
  57. })
  58. _stickPos = null;
  59. @property({
  60. type: cc.Node,
  61. tooltip: "触摸位置",
  62. })
  63. _touchLocation = null;
  64. @property({
  65. tooltip: "半径",
  66. })
  67. _radius = 0;
  68. /**
  69. * 事件回调
  70. */
  71. private callback:(speedType:SpeedType,moveVec?:cc.Vec2)=>void = undefined;
  72. onLoad() {
  73. this._radius = this.ring.width / 2;
  74. this._initTouchEvent();
  75. // hide joystick when follow
  76. if (this.joystickType === JoystickType.FOLLOW) {
  77. this.node.opacity = 0;
  78. }
  79. cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyPressed, this);
  80. cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyReleased, this);
  81. }
  82. /**
  83. * 改变摇杆类型
  84. * @param type
  85. */
  86. _onSetJoystickType(type: JoystickType) {
  87. this.joystickType = type;
  88. this.node.opacity = type === JoystickType.FIXED ? 255 : 0;
  89. }
  90. /**
  91. * 初始化触摸事件
  92. */
  93. _initTouchEvent() {
  94. // set the size of joystick node to control scale
  95. this.node.on(cc.Node.EventType.TOUCH_START, this._touchStartEvent, this);
  96. this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this);
  97. this.node.on(cc.Node.EventType.TOUCH_END, this._touchEndEvent, this);
  98. this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this);
  99. }
  100. /**
  101. * 触摸开始回调函数
  102. * @param event
  103. */
  104. _touchStartEvent(event: cc.Event.EventTouch) {
  105. const touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
  106. if (this.joystickType === JoystickType.FIXED) {
  107. this._stickPos = this.ring.getPosition();
  108. // 触摸点与圆圈中心的距离
  109. const distance = touchPos.sub(this.ring.getPosition()).mag();
  110. // 手指在圆圈内触摸,控杆跟随触摸点
  111. this._radius > distance && this.dot.setPosition(touchPos);
  112. } else if (this.joystickType === JoystickType.FOLLOW) {
  113. // 记录摇杆位置,给 touch move 使用
  114. this._stickPos = touchPos;
  115. this.node.opacity = 255;
  116. this._touchLocation = event.getLocation();
  117. // 更改摇杆的位置
  118. this.ring.setPosition(touchPos);
  119. this.dot.setPosition(touchPos);
  120. }
  121. }
  122. /**
  123. * 触摸移动回调函数
  124. * @param event
  125. */
  126. _touchMoveEvent(event: cc.Event.EventTouch) {
  127. // 如果 touch start 位置和 touch move 相同,禁止移动
  128. if (
  129. this.joystickType === JoystickType.FOLLOW &&
  130. this._touchLocation === event.getLocation()
  131. ) {
  132. return false;
  133. }
  134. // 以圆圈为锚点获取触摸坐标
  135. const touchPos = this.ring.convertToNodeSpaceAR(event.getLocation());
  136. const distance = touchPos.mag();
  137. // 由于摇杆的 postion 是以父节点为锚点,所以定位要加上 touch start 时的位置
  138. const posX = this._stickPos.x + touchPos.x;
  139. const posY = this._stickPos.y + touchPos.y;
  140. // 归一化
  141. const p = cc.v2(posX, posY).sub(this.ring.getPosition()).normalize();
  142. let speedType;
  143. if (this._radius > distance) {
  144. this.dot.setPosition(cc.v2(posX, posY));
  145. speedType = SpeedType.NORMAL;
  146. } else {
  147. // 控杆永远保持在圈内,并在圈内跟随触摸更新角度
  148. const x = this._stickPos.x + p.x * this._radius;
  149. const y = this._stickPos.y + p.y * this._radius;
  150. this.dot.setPosition(cc.v2(x, y));
  151. speedType = SpeedType.FAST;
  152. }
  153. if(this.callback != undefined){
  154. if(p.x == 0 && p.y == 0){
  155. this.callback(SpeedType.STOP)
  156. }else{
  157. this.callback(speedType,p)
  158. }
  159. }
  160. }
  161. /**
  162. * 触摸结束回调函数
  163. * @param event
  164. */
  165. _touchEndEvent(event: cc.Event.EventTouch) {
  166. this.dot.setPosition(this.ring.getPosition());
  167. if (this.joystickType === JoystickType.FOLLOW) {
  168. this.node.opacity = 0;
  169. }
  170. if(this.callback != undefined){
  171. this.callback(SpeedType.STOP)
  172. }
  173. }
  174. public stop(){
  175. this._touchEndEvent(null)
  176. }
  177. public setListen(callback:(speedType:SpeedType,moveVec?:cc.Vec2)=>void){
  178. this.callback = callback;
  179. }
  180. private keyDir = cc.v2(0,0)
  181. private onKeyPressed(event) {
  182. let keyCode = event.keyCode;
  183. switch(keyCode) {
  184. case cc.macro.KEY.w:
  185. case cc.macro.KEY.up:
  186. this.keyDir.y = 1;
  187. break;
  188. case cc.macro.KEY.s:
  189. case cc.macro.KEY.down:
  190. this.keyDir.y = -1;
  191. break;
  192. case cc.macro.KEY.a:
  193. case cc.macro.KEY.left:
  194. this.keyDir.x = -1;
  195. break;
  196. case cc.macro.KEY.d:
  197. case cc.macro.KEY.right:
  198. this.keyDir.x = 1;
  199. break;
  200. }
  201. if(this.callback){
  202. let dmg = this.keyDir.normalize()
  203. if(dmg.x == 0 && dmg.y == 0){
  204. this.callback(SpeedType.STOP)
  205. }else{
  206. this.callback(SpeedType.FAST,dmg)
  207. }
  208. }
  209. }
  210. private onKeyReleased(event) {
  211. let keyCode = event.keyCode;
  212. switch(keyCode) {
  213. case cc.macro.KEY.w:
  214. case cc.macro.KEY.up:
  215. this.keyDir.y = 0;
  216. break;
  217. case cc.macro.KEY.s:
  218. case cc.macro.KEY.down:
  219. this.keyDir.y = 0;
  220. break;
  221. case cc.macro.KEY.a:
  222. case cc.macro.KEY.left:
  223. this.keyDir.x = 0;
  224. break;
  225. case cc.macro.KEY.d:
  226. case cc.macro.KEY.right:
  227. this.keyDir.x = 0;
  228. break;
  229. }
  230. if(this.callback){
  231. let dmg = this.keyDir.normalize()
  232. if(dmg.x == 0 && dmg.y == 0){
  233. this.callback(SpeedType.STOP)
  234. }else{
  235. this.callback(SpeedType.FAST,dmg)
  236. }
  237. }
  238. }
  239. }