Joystick_8d.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /**
  2. * 8方向摇杆
  3. */
  4. const {ccclass, property} = cc._decorator;
  5. @ccclass
  6. export default class Joystick_8d extends cc.Component {
  7. @property({
  8. type: cc.Node,
  9. displayName: '按下显示效果',
  10. })
  11. mTouchView: cc.Node = null;
  12. @property({
  13. type: cc.Node,
  14. displayName: '摇杆中心',
  15. })
  16. mCneter: cc.Node = null;
  17. @property({
  18. type: cc.Sprite,
  19. displayName: '上',
  20. })
  21. mUp: cc.Sprite = null;
  22. @property({
  23. type: cc.Sprite,
  24. displayName: '下',
  25. })
  26. mDown: cc.Sprite = null;
  27. @property({
  28. type: cc.Sprite,
  29. displayName: '左',
  30. })
  31. mLeft: cc.Sprite = null;
  32. @property({
  33. type: cc.Sprite,
  34. displayName: '右',
  35. })
  36. mRight: cc.Sprite = null;
  37. @property({
  38. type: cc.SpriteFrame,
  39. displayName: '点击高亮',
  40. })
  41. mTouchOn: cc.SpriteFrame = null;
  42. @property({
  43. type: cc.SpriteFrame,
  44. displayName: '灰色',
  45. })
  46. mTouchOff: cc.SpriteFrame = null;
  47. private tmpDir = {x:0,y:0}
  48. /**
  49. * @runing 行走
  50. * @angle 角度
  51. * @distance 距离[0-1]
  52. */
  53. private callback:(dir:any)=>void;
  54. onLoad () {
  55. this.mTouchView.active = false;
  56. this._initTouchEvent();
  57. }
  58. public setCallback(callback:(dir:cc.Vec2)=>void){
  59. this.callback = callback;
  60. }
  61. //对圆圈的触摸监听
  62. private _initTouchEvent() {
  63. this.node.on(cc.Node.EventType.TOUCH_START, this._touchStartEvent, this);
  64. this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this);
  65. // // 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0
  66. this.node.on(cc.Node.EventType.TOUCH_END, this._touchEndEvent, this);
  67. this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this);
  68. cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyPressed, this);
  69. cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyReleased, this);
  70. }
  71. private _touchStartEvent(event) {
  72. let p1 = this.node.convertToNodeSpaceAR(event.getLocation());
  73. let p2 = this.mCneter.getPosition();
  74. let distance = this._getDistance(p1,p2);
  75. // cc.log('distance = ',distance);
  76. if(distance > 10 &&distance < 175){
  77. this.mTouchView.active = true;
  78. this.mTouchView.x = p1.x;
  79. this.mTouchView.y = p1.y;
  80. let angle = this._getAngle(p1,p2);
  81. let dir = this.getDir(angle);
  82. this.updateIcon(dir);
  83. if(this.callback){
  84. this.callback(dir);
  85. }
  86. }
  87. }
  88. private _touchMoveEvent(event) {
  89. if(this.mTouchView.active){
  90. let p1 = this.node.convertToNodeSpaceAR(event.getLocation());
  91. let p2 = this.mCneter.getPosition();
  92. this.mTouchView.x = p1.x;
  93. this.mTouchView.y = p1.y;
  94. let angle = this._getAngle(p1,p2);
  95. let dir = this.getDir(angle);
  96. this.updateIcon(dir);
  97. if(this.callback){
  98. this.callback(dir);
  99. }
  100. }
  101. }
  102. private _touchEndEvent(event) {
  103. this.stop();
  104. }
  105. private onKeyPressed(event) {
  106. let keyCode = event.keyCode;
  107. switch(keyCode) {
  108. case cc.macro.KEY.w:
  109. case cc.macro.KEY.up:
  110. this.tmpDir.y = 1;
  111. break;
  112. case cc.macro.KEY.s:
  113. case cc.macro.KEY.down:
  114. this.tmpDir.y = -1;
  115. break;
  116. case cc.macro.KEY.a:
  117. case cc.macro.KEY.left:
  118. this.tmpDir.x = -1;
  119. break;
  120. case cc.macro.KEY.d:
  121. case cc.macro.KEY.right:
  122. this.tmpDir.x = 1;
  123. break;
  124. }
  125. this.updateIcon(this.tmpDir);
  126. if(this.callback){
  127. this.callback(this.reviseValue());
  128. }
  129. }
  130. private onKeyReleased(event) {
  131. let keyCode = event.keyCode;
  132. switch(keyCode) {
  133. case cc.macro.KEY.w:
  134. case cc.macro.KEY.up:
  135. this.tmpDir.y = 0;
  136. break;
  137. case cc.macro.KEY.s:
  138. case cc.macro.KEY.down:
  139. this.tmpDir.y = 0;
  140. break;
  141. case cc.macro.KEY.a:
  142. case cc.macro.KEY.left:
  143. this.tmpDir.x = 0;
  144. break;
  145. case cc.macro.KEY.d:
  146. case cc.macro.KEY.right:
  147. this.tmpDir.x = 0;
  148. break;
  149. }
  150. this.updateIcon(this.tmpDir);
  151. if(this.callback){
  152. this.callback(this.reviseValue());
  153. }
  154. }
  155. private reviseValue(){
  156. let pos = {
  157. x:this.tmpDir.x,
  158. y:this.tmpDir.y
  159. };
  160. let ax = Math.abs(pos.x);
  161. let ay = Math.abs(pos.y);
  162. if(ax != ay){
  163. if(ax == 1){
  164. pos.x = pos.x*1.4;
  165. }else if(ay == 1){
  166. pos.y = pos.y*1.4;
  167. }
  168. }
  169. return pos;
  170. }
  171. public stop(){
  172. this.mTouchView.active = false;
  173. this.updateIcon(null);
  174. if(this.callback){
  175. this.callback({x:0,y:0});
  176. }
  177. }
  178. //计算弧度并返回
  179. private _getAngle(p1,p2):number {
  180. return Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI);
  181. }
  182. //计算两点间的距离并返回
  183. private _getDistance(pos1: cc.Vec2, pos2: cc.Vec2) {
  184. return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2));
  185. }
  186. /**
  187. * 根据弧度获取方向
  188. * @param angle
  189. */
  190. private getDir(angle:number){
  191. if(angle >= -30 && angle < 30){
  192. return {x:1.4,y:0}
  193. }else if(angle >= 30 && angle < 60){
  194. return {x:1,y:1}
  195. }else if(angle >= 60 && angle < 120){
  196. return {x:0,y:1.4}
  197. }else if(angle >= 120 && angle < 150){
  198. return {x:-1,y:1}
  199. }else if(angle >= 150 && angle < 180){
  200. return {x:-1.4,y:0}
  201. }else if(angle >= -180 && angle < -150){
  202. return {x:-1.4,y:0}
  203. }else if(angle >= -150 && angle < -120){
  204. return {x:-1,y:-1}
  205. }else if(angle >= -120 && angle < -60){
  206. return {x:0,y:-1.4}
  207. }else if(angle >= -60 && angle < -30){
  208. return {x:1,y:-1}
  209. }
  210. }
  211. private updateIcon(dir){
  212. if(dir){
  213. if(dir.x == 0){
  214. this.mLeft.spriteFrame = this.mTouchOff;
  215. this.mRight.spriteFrame = this.mTouchOff;
  216. }else if(dir.x > 0){
  217. this.mLeft.spriteFrame = this.mTouchOff;
  218. this.mRight.spriteFrame = this.mTouchOn;
  219. }else{
  220. this.mLeft.spriteFrame = this.mTouchOn;
  221. this.mRight.spriteFrame = this.mTouchOff;
  222. }
  223. if(dir.y == 0){
  224. this.mUp.spriteFrame = this.mTouchOff;
  225. this.mDown.spriteFrame = this.mTouchOff;
  226. }else if(dir.y > 0){
  227. this.mUp.spriteFrame = this.mTouchOn;
  228. this.mDown.spriteFrame = this.mTouchOff;
  229. }else{
  230. this.mUp.spriteFrame = this.mTouchOff;
  231. this.mDown.spriteFrame = this.mTouchOn;
  232. }
  233. }else{
  234. this.mLeft.spriteFrame = this.mTouchOff;
  235. this.mRight.spriteFrame = this.mTouchOff;
  236. this.mUp.spriteFrame = this.mTouchOff;
  237. this.mDown.spriteFrame = this.mTouchOff;
  238. }
  239. }
  240. }