Cocos2d-js3.3虚拟摇杆的实现

2015-04-03 09:51
虚拟摇杆是在手机格斗游戏中经常看到的一个东西,今天就来了解一下如何在cocos2d-js实现一个虚拟摇杆...

首先,先来看一下这个虚拟摇杆的效果

默认类型(Default):

Cocos2d-js3.3虚拟摇杆的实现_第1张图片

跟随类型(Follow):

Cocos2d-js3.3虚拟摇杆的实现_第2张图片

下面,来看一下我实现的这个虚拟摇杆的创建方法:

[javascript]  view plain copy
  1. var joystick = new Joystick(res.JoystickBG_png,   
  2.                             res.Joystick_png,   
  3.                             50,   
  4.                             TouchType.DEFAULT,   
  5.                             DirectionType.ALL,   
  6.                             sprite);  
  7. joystick.setPosition(cc.p(100, 100));  
  8. joystick.setSpeedwithLevel1(1);  
  9. joystick.setSpeedwithLevel2(2);  
  10. //joystick.setOpacity(128);  
  11. //joystick.setEnable(true);  
  12. joystick.callback = this.onCallback.bind(this);  
  13. this.addChild(joystick, 0, 101);  

可以看到,构造函数中传进了6个参数,分别是:

遥控杆的背景(底盘)图、遥控杆图、底盘半径、触摸类型、方向类型和要控制的目标

其中,触摸类型分为:默认(DEFAULT) 和跟随(FOLLOW)

方向类型分为:四方位(上下左右)八方位(上下左右、左上左下、右上右下)全方位

然后,我们可以设置摇杆的位置、速度1、速度2、透明度、是否可用、绑定回调函数。

这里解释一下,速度1和速度2,当控杆中心在底盘边缘,目标移动速度为速度2,否则移动速度为速度1

而绑定回调函数,是为了在控杆的角度变化时,能反馈过来,是否需要改变目标的朝向等。


最后,来看一下这个虚拟控杆类

[javascript]  view plain copy
  1. var TouchType = {  
  2.     DEFAULT: "DEFAULT",  
  3.     FOLLOW: "FOLLOW"  
  4. };  
  5.   
  6. var DirectionType = {  
  7.     FOUR: "FOUR",  
  8.     EIGHT: "EIGHT",  
  9.     ALL: "ALL"  
  10. };  
  11.   
  12. var Joystick = cc.Node.extend({  
  13.     _stick: null,       //控杆  
  14.     _stickBG: null,     //控杆背景  
  15.     _listener: null,    //监听器  
  16.     _radius: 0,         //半径  
  17.     _angle: null,       //角度  
  18.     _radian: null,      //弧度  
  19.     _target: null,      //操控的目标  
  20.     _speed: 0,          //实际速度  
  21.     _speed1: 1,         //一段速度  
  22.     _speed2: 2,         //二段速度  
  23.     _touchType: null,   //触摸类型  
  24.     _directionType: null,   //方向类型  
  25.     _opacity: 0,        //透明度  
  26.     callback: null,     //回调函数  
  27.     ctor: function(stickBG, stick, radius, touchType, directionType, target)  
  28.     {  
  29.         this._super();  
  30.         this._target = target;  
  31.         this._touchType = touchType;  
  32.         this._directionType = directionType;  
  33.   
  34.         //创建摇杆精灵  
  35.         this._createStickSprite(stickBG, stick, radius);  
  36.   
  37.         //初始化触摸事件  
  38.         this._initTouchEvent();  
  39.     },  
  40.   
  41.     _createStickSprite: function(stickBG, stick, radius)  
  42.     {  
  43.         this._radius = radius;  
  44.   
  45.         if(this._touchType == TouchType.FOLLOW)  
  46.             this.setVisible(false);  
  47.   
  48.         //摇杆背景精灵  
  49.         this._stickBG = new cc.Sprite(stickBG);  
  50.         this._stickBG.setPosition(cc.p(radius, radius));  
  51.         this.addChild(this._stickBG);  
  52.   
  53.         //摇杆精灵  
  54.         this._stick = new cc.Sprite(stick);  
  55.         this._stick.setPosition(cc.p(radius, radius));  
  56.         this.addChild(this._stick);  
  57.   
  58.         //根据半径设置缩放比例  
  59.         var scale = radius / (this._stickBG.getContentSize().width / 2);  
  60.         this._stickBG.setScale(scale);  
  61.         this._stick.setScale(scale);  
  62.   
  63.         //设置大小  
  64.         this.setContentSize(this._stickBG.getBoundingBox());  
  65.   
  66.         //设置锚点  
  67.         this.setAnchorPoint(cc.p(0.5, 0.5));  
  68.     },  
  69.   
  70.     _initTouchEvent: function()  
  71.     {  
  72.         this._listener = cc.EventListener.create({  
  73.             event: cc.EventListener.TOUCH_ONE_BY_ONE,  
  74.             swallowTouches: false,  
  75.             onTouchBegan: this.onTouchBegan,  
  76.             onTouchMoved: this.onTouchMoved,  
  77.             onTouchEnded: this.onTouchEnded  
  78.         });  
  79.   
  80.         //如果存在相同的对象,将被移除  
  81.         this.setUserObject(this._listener);  
  82.   
  83.         //添加触摸监听  
  84.         cc.eventManager.addListener(this._listener, this._stickBG);  
  85.     },  
  86.   
  87.     //计算角度并返回  
  88.     _getAngle: function(point)  
  89.     {  
  90.         var pos = this._stickBG.getPosition();  
  91.         this._angle = Math.atan2(point.y-pos.y, point.x-pos.x) * (180/cc.PI);  
  92.         return this._angle;  
  93.     },  
  94.   
  95.     //计算弧度并返回  
  96.     _getRadian: function(point)  
  97.     {  
  98.         this._radian = cc.PI / 180 * this._getAngle(point);  
  99.         return this._radian;  
  100.     },  
  101.   
  102.     //计算两点间的距离并返回  
  103.     _getDistance: function(pos1, pos2)  
  104.     {  
  105.         return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) +  
  106.         Math.pow(pos1.y - pos2.y, 2));  
  107.     },  
  108.   
  109.     onTouchBegan: function(touch, event)  
  110.     {  
  111.         //触摸监听目标  
  112.         var target = event.getCurrentTarget();  
  113.   
  114.         //如果触摸类型为FOLLOW,则摇控杆的位置为触摸位置,触摸开始时候现形  
  115.         if(target.getParent()._touchType == TouchType.FOLLOW)  
  116.         {  
  117.             target.getParent().setPosition(touch.getLocation());  
  118.             target.getParent().setVisible(true);  
  119.             target.getParent().scheduleUpdate();  
  120.             return true;  
  121.         }  
  122.         else  
  123.         {  
  124.             //把触摸点坐标转换为相对与目标的模型坐标  
  125.             var touchPos = target.convertToNodeSpace(touch.getLocation());  
  126.   
  127.             //点与圆心的距离  
  128.             var distance = target.getParent()._getDistance(touchPos, target);  
  129.   
  130.             //圆的半径  
  131.             var radius = target.getBoundingBox().width / 2;  
  132.   
  133.             //如果点与圆心距离小于圆的半径,返回true  
  134.             if(radius > distance)  
  135.             {  
  136.                 target.getParent()._stick.setPosition(touchPos);  
  137.                 target.getParent().scheduleUpdate();  
  138.                 return true;  
  139.             }  
  140.         }  
  141.         return false;  
  142.     },  
  143.   
  144.     onTouchMoved: function(touch, event)  
  145.     {  
  146.         //触摸监听目标  
  147.         var target = event.getCurrentTarget();  
  148.   
  149.         //把触摸点坐标转换为相对与目标的模型坐标  
  150.         var touchPos = target.convertToNodeSpace(touch.getLocation());  
  151.   
  152.         //点与圆心的距离  
  153.         var distance = target.getParent()._getDistance(touchPos, target);  
  154.   
  155.         //圆的半径  
  156.         var radius = target.getBoundingBox().width / 2;  
  157.   
  158.         //如果点与圆心距离小于圆的半径,控杆跟随触摸点  
  159.         if(radius > distance)  
  160.         {  
  161.             target.getParent()._stick.setPosition(touchPos);  
  162.         }  
  163.         else  
  164.         {  
  165.             var x = target.getPositionX() + Math.cos(target.getParent()._getRadian(touchPos)) * target.getParent()._radius;  
  166.             var y = target.getPositionY() + Math.sin(target.getParent()._getRadian(touchPos)) * target.getParent()._radius;  
  167.             target.getParent()._stick.setPosition(cc.p(x, y));  
  168.         }  
  169.   
  170.         //更新角度  
  171.         target.getParent()._getAngle(touchPos);  
  172.   
  173.         //设置实际速度  
  174.         target.getParent()._setSpeed(touchPos);  
  175.   
  176.         //更新回调  
  177.         target.getParent()._updateCallback();  
  178.     },  
  179.   
  180.     onTouchEnded: function(touch, event)  
  181.     {  
  182.         //触摸监听目标  
  183.         var target = event.getCurrentTarget();  
  184.   
  185.         //如果触摸类型为FOLLOW,离开触摸后隐藏  
  186.         if(target.getParent()._touchType == TouchType.FOLLOW)  
  187.             target.getParent().setVisible(false);  
  188.   
  189.         //摇杆恢复位置  
  190.         target.getParent()._stick.setPosition(target.getPosition());  
  191.   
  192.         target.getParent().unscheduleUpdate();  
  193.     },  
  194.   
  195.     //设置实际速度  
  196.     _setSpeed: function(point)  
  197.     {  
  198.         //触摸点和遥控杆中心的距离  
  199.         var distance = this._getDistance(point, this._stickBG.getPosition());  
  200.   
  201.         //如果半径  
  202.         if(distance < this._radius)  
  203.         {  
  204.             this._speed = this._speed1;  
  205.         }  
  206.         else  
  207.         {  
  208.             this._speed = this._speed2;  
  209.         }  
  210.     },  
  211.   
  212.     //更新回调  
  213.     _updateCallback: function()  
  214.     {  
  215.         if(this.callback && typeof(this.callback) === "function")  
  216.         {  
  217.             this.callback();  
  218.         }  
  219.     },  
  220.   
  221.     //更新移动目标  
  222.     update: function(dt)  
  223.     {  
  224.         switch (this._directionType)  
  225.         {  
  226.             case DirectionType.FOUR:  
  227.                 this._fourDirectionsMove();  
  228.                 break;  
  229.             case DirectionType.EIGHT:  
  230.                 this._eightDirectionsMove();  
  231.                 break;  
  232.             case DirectionType.ALL:  
  233.                 this._allDirectionsMove();  
  234.                 break;  
  235.             default :  
  236.                 break;  
  237.         }  
  238.     },  
  239.   
  240.     //四个方向移动(上下左右)  
  241.     _fourDirectionsMove: function()  
  242.     {  
  243.         if(this._angle > 45 && this._angle < 135)  
  244.         {  
  245.             this._target.y += this._speed;  
  246.         }  
  247.         else if(this._angle > -135 && this._angle < -45)  
  248.         {  
  249.             this._target.y -= this._speed;  
  250.         }  
  251.         else if(this._angle < -135 && this._angle > -180 || this._angle > 135 && this._angle < 180)  
  252.         {  
  253.             this._target.x -= this._speed;  
  254.         }  
  255.         else if(this._angle < 0 && this._angle > -45 || this._angle > 0 && this._angle < 45)  
  256.         {  
  257.             this._target.x += this._speed;  
  258.         }  
  259.     },  
  260.   
  261.     //八个方向移动(上下左右、左上、右上、左下、右下)  
  262.     _eightDirectionsMove: function()  
  263.     {  
  264.         if(this._angle > 67.5 && this._angle < 112.5)  
  265.         {  
  266.             this._target.y += this._speed;  
  267.         }  
  268.         else if(this._angle > -112.5 && this._angle < -67.5)  
  269.         {  
  270.             this._target.y -= this._speed;  
  271.         }  
  272.         else if(this._angle < -157.5 && this._angle > -180 || this._angle > 157.5 && this._angle < 180)  
  273.         {  
  274.             this._target.x -= this._speed;  
  275.         }  
  276.         else if(this._angle < 0 && this._angle > -22.5 || this._angle > 0 && this._angle < 22.5)  
  277.         {  
  278.             this._target.x += this._speed;  
  279.         }  
  280.         else if(this._angle > 112.5 && this._angle < 157.5)  
  281.         {  
  282.             this._target.x -= this._speed / 1.414;  
  283.             this._target.y += this._speed / 1.414;  
  284.         }  
  285.         else if(this._angle > 22.5 && this._angle < 67.5)  
  286.         {  
  287.             this._target.x += this._speed / 1.414;  
  288.             this._target.y += this._speed / 1.414;  
  289.         }  
  290.         else if(this._angle > -157.5 && this._angle < -112.5)  
  291.         {  
  292.             this._target.x -= this._speed / 1.414;  
  293.             this._target.y -= this._speed / 1.414;  
  294.         }  
  295.         else if(this._angle > -67.5 && this._angle < -22.5)  
  296.         {  
  297.             this._target.x += this._speed / 1.414;  
  298.             this._target.y -= this._speed / 1.414;  
  299.         }  
  300.     },  
  301.   
  302.     //全方向移动  
  303.     _allDirectionsMove: function()  
  304.     {  
  305.         this._target.x += Math.cos(this._angle * (Math.PI/180)) * this._speed;  
  306.         this._target.y += Math.sin(this._angle * (Math.PI/180)) * this._speed;  
  307.     },  
  308.   
  309.     //设置透明度  
  310.     setOpacity: function(opacity)  
  311.     {  
  312.         this._opacity = opacity;  
  313.         this._stick.setOpacity(opacity);  
  314.         this._stickBG.setOpacity(opacity);  
  315.     },  
  316.   
  317.     //设置一段速度  
  318.     setSpeedwithLevel1: function(speed)  
  319.     {  
  320.         this._speed1 = speed;  
  321.     },  
  322.   
  323.     //设置二段速度  
  324.     setSpeedwithLevel2: function(speed)  
  325.     {  
  326.         if(this._speed1 < speed)  
  327.         {  
  328.             this._speed2 = speed;  
  329.         }  
  330.         else  
  331.         {  
  332.             this._speed2 = this._speed2;  
  333.         }  
  334.     },  
  335.   
  336.     //设置遥控杆开关  
  337.     setEnable: function(enable)  
  338.     {  
  339.         if(this._listener != null)  
  340.         {  
  341.             if(enable)  
  342.             {  
  343.                 cc.eventManager.addListener(this._listener, this._stickBG);  
  344.             }  
  345.             else  
  346.             {  
  347.                 cc.eventManager.removeListener(this._listener);  
  348.             }  
  349.         }  
  350.     },  
  351.   
  352.     //获取角度  
  353.     getAngle: function()  
  354.     {  
  355.         return this._angle;  
  356.     },  
  357.   
  358.     onExit: function()  
  359.     {  
  360.         this._super();  
  361.         //移除触摸监听  
  362.         if(this._listener != null)  
  363.         {  
  364.             cc.eventManager.removeListener(this._listener);  
  365.         }  
  366.     }  
  367. });  
源码下载: 点击打开链接

你可能感兴趣的:(Cocos2d-js3.3虚拟摇杆的实现)