虚拟摇杆是在手机格斗游戏中经常看到的一个东西,今天就来了解一下如何在cocos2d-js实现一个虚拟摇杆...
首先,先来看一下这个虚拟摇杆的效果
默认类型(Default):
跟随类型(Follow):
下面,来看一下我实现的这个虚拟摇杆的创建方法:
var joystick = new Joystick(res.JoystickBG_png,res.Joystick_png,50,TouchType.DEFAULT,DirectionType.ALL,sprite); joystick.setPosition(cc.p(100,100)); joystick.setSpeedwithLevel1(1); joystick.setSpeedwithLevel2(2); //joystick.setOpacity(128); //joystick.setEnable(true); joystick.callback = this.onCallback.bind(this); this.addChild(joystick,101);
可以看到,构造函数中传进了6个参数,分别是:
遥控杆的背景(底盘)图、遥控杆图、底盘半径、触摸类型、方向类型和要控制的目标
其中,触摸类型分为:默认(DEFAULT) 和跟随(FOLLOW)
方向类型分为:四方位(上下左右)、八方位(上下左右、左上左下、右上右下)、全方位
然后,我们可以设置摇杆的位置、速度1、速度2、透明度、是否可用、绑定回调函数。
这里解释一下,速度1和速度2,当控杆中心在底盘边缘,目标移动速度为速度2,否则移动速度为速度1
而绑定回调函数,是为了在控杆的角度变化时,能反馈过来,是否需要改变目标的朝向等。
最后,来看一下这个虚拟控杆类
var TouchType = { DEFAULT: "DEFAULT",FOLLOW: "FOLLOW" }; var DirectionType = { FOUR: "FOUR",EIGHT: "EIGHT",ALL: "ALL" }; var Joystick = cc.Node.extend({ _stick: null,//控杆 _stickBG: null,//控杆背景 _listener: null,//监听器 _radius: 0,//半径 _angle: null,//角度 _radian: null,//弧度 _target: null,//操控的目标 _speed: 0,//实际速度 _speed1: 1,//一段速度 _speed2: 2,//二段速度 _touchType: null,//触摸类型 _directionType: null,//方向类型 _opacity: 0,//透明度 callback: null,//回调函数 ctor: function(stickBG,stick,radius,touchType,directionType,target) { this._super(); this._target = target; this._touchType = touchType; this._directionType = directionType; //创建摇杆精灵 this._createStickSprite(stickBG,radius); //初始化触摸事件 this._initTouchEvent(); },_createStickSprite: function(stickBG,radius) { this._radius = radius; if(this._touchType == TouchType.FOLLOW) this.setVisible(false); //摇杆背景精灵 this._stickBG = new cc.Sprite(stickBG); this._stickBG.setPosition(cc.p(radius,radius)); this.addChild(this._stickBG); //摇杆精灵 this._stick = new cc.Sprite(stick); this._stick.setPosition(cc.p(radius,radius)); this.addChild(this._stick); //根据半径设置缩放比例 var scale = radius / (this._stickBG.getContentSize().width / 2); this._stickBG.setScale(scale); this._stick.setScale(scale); //设置大小 this.setContentSize(this._stickBG.getBoundingBox()); //设置锚点 this.setAnchorPoint(cc.p(0.5,0.5)); },_initTouchEvent: function() { this._listener = cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY_ONE,swallowTouches: false,onTouchBegan: this.onTouchBegan,onTouchMoved: this.onTouchMoved,onTouchEnded: this.onTouchEnded }); //如果存在相同的对象,将被移除 this.setUserObject(this._listener); //添加触摸监听 cc.eventManager.addListener(this._listener,this._stickBG); },//计算角度并返回 _getAngle: function(point) { var pos = this._stickBG.getPosition(); this._angle = Math.atan2(point.y-pos.y,point.x-pos.x) * (180/cc.PI); return this._angle; },//计算弧度并返回 _getRadian: function(point) { this._radian = cc.PI / 180 * this._getAngle(point); return this._radian; },//计算两点间的距离并返回 _getDistance: function(pos1,pos2) { return Math.sqrt(Math.pow(pos1.x - pos2.x,2) + Math.pow(pos1.y - pos2.y,2)); },onTouchBegan: function(touch,event) { //触摸监听目标 var target = event.getCurrentTarget(); //如果触摸类型为FOLLOW,则摇控杆的位置为触摸位置,触摸开始时候现形 if(target.getParent()._touchType == TouchType.FOLLOW) { target.getParent().setPosition(touch.getLocation()); target.getParent().setVisible(true); target.getParent().scheduleUpdate(); return true; } else { //把触摸点坐标转换为相对与目标的模型坐标 var touchPos = target.convertToNodeSpace(touch.getLocation()); //点与圆心的距离 var distance = target.getParent()._getDistance(touchPos,target); //圆的半径 var radius = target.getBoundingBox().width / 2; //如果点与圆心距离小于圆的半径,返回true if(radius > distance) { target.getParent()._stick.setPosition(touchPos); target.getParent().scheduleUpdate(); return true; } } return false; },onTouchMoved: function(touch,event) { //触摸监听目标 var target = event.getCurrentTarget(); //把触摸点坐标转换为相对与目标的模型坐标 var touchPos = target.convertToNodeSpace(touch.getLocation()); //点与圆心的距离 var distance = target.getParent()._getDistance(touchPos,target); //圆的半径 var radius = target.getBoundingBox().width / 2; //如果点与圆心距离小于圆的半径,控杆跟随触摸点 if(radius > distance) { target.getParent()._stick.setPosition(touchPos); } else { var x = target.getPositionX() + Math.cos(target.getParent()._getRadian(touchPos)) * target.getParent()._radius; var y = target.getPositionY() + Math.sin(target.getParent()._getRadian(touchPos)) * target.getParent()._radius; target.getParent()._stick.setPosition(cc.p(x,y)); } //更新角度 target.getParent()._getAngle(touchPos); //设置实际速度 target.getParent()._setSpeed(touchPos); //更新回调 target.getParent()._updateCallback(); },onTouchEnded: function(touch,event) { //触摸监听目标 var target = event.getCurrentTarget(); //如果触摸类型为FOLLOW,离开触摸后隐藏 if(target.getParent()._touchType == TouchType.FOLLOW) target.getParent().setVisible(false); //摇杆恢复位置 target.getParent()._stick.setPosition(target.getPosition()); target.getParent().unscheduleUpdate(); },//设置实际速度 _setSpeed: function(point) { //触摸点和遥控杆中心的距离 var distance = this._getDistance(point,this._stickBG.getPosition()); //如果半径 if(distance < this._radius) { this._speed = this._speed1; } else { this._speed = this._speed2; } },//更新回调 _updateCallback: function() { if(this.callback && typeof(this.callback) === "function") { this.callback(); } },//更新移动目标 update: function(dt) { switch (this._directionType) { case DirectionType.FOUR: this._fourDirectionsMove(); break; case DirectionType.EIGHT: this._eightDirectionsMove(); break; case DirectionType.ALL: this._allDirectionsMove(); break; default : break; } },//四个方向移动(上下左右) _fourDirectionsMove: function() { if(this._angle > 45 && this._angle < 135) { this._target.y += this._speed; } else if(this._angle > -135 && this._angle < -45) { this._target.y -= this._speed; } else if(this._angle < -135 && this._angle > -180 || this._angle > 135 && this._angle < 180) { this._target.x -= this._speed; } else if(this._angle < 0 && this._angle > -45 || this._angle > 0 && this._angle < 45) { this._target.x += this._speed; } },//八个方向移动(上下左右、左上、右上、左下、右下) _eightDirectionsMove: function() { if(this._angle > 67.5 && this._angle < 112.5) { this._target.y += this._speed; } else if(this._angle > -112.5 && this._angle < -67.5) { this._target.y -= this._speed; } else if(this._angle < -157.5 && this._angle > -180 || this._angle > 157.5 && this._angle < 180) { this._target.x -= this._speed; } else if(this._angle < 0 && this._angle > -22.5 || this._angle > 0 && this._angle < 22.5) { this._target.x += this._speed; } else if(this._angle > 112.5 && this._angle < 157.5) { this._target.x -= this._speed / 1.414; this._target.y += this._speed / 1.414; } else if(this._angle > 22.5 && this._angle < 67.5) { this._target.x += this._speed / 1.414; this._target.y += this._speed / 1.414; } else if(this._angle > -157.5 && this._angle < -112.5) { this._target.x -= this._speed / 1.414; this._target.y -= this._speed / 1.414; } else if(this._angle > -67.5 && this._angle < -22.5) { this._target.x += this._speed / 1.414; this._target.y -= this._speed / 1.414; } },//全方向移动 _allDirectionsMove: function() { this._target.x += Math.cos(this._angle * (Math.PI/180)) * this._speed; this._target.y += Math.sin(this._angle * (Math.PI/180)) * this._speed; },//设置透明度 setOpacity: function(opacity) { this._opacity = opacity; this._stick.setOpacity(opacity); this._stickBG.setOpacity(opacity); },//设置一段速度 setSpeedwithLevel1: function(speed) { this._speed1 = speed; },//设置二段速度 setSpeedwithLevel2: function(speed) { if(this._speed1 < speed) { this._speed2 = speed; } else { this._speed2 = this._speed2; } },//设置遥控杆开关 setEnable: function(enable) { if(this._listener != null) { if(enable) { cc.eventManager.addListener(this._listener,this._stickBG); } else { cc.eventManager.removeListener(this._listener); } } },//获取角度 getAngle: function() { return this._angle; },onExit: function() { this._super(); //移除触摸监听 if(this._listener != null) { cc.eventManager.removeListener(this._listener); } } });
源码下载: 点击打开链接