虚拟摇杆是在手机格斗游戏中经常看到的一个东西,用来控制人物的8个方向的行走,今天就来了解一下如何在cocos2d-js实现一个虚拟摇杆...
// 虚拟摇杆类型
var ROCKER_TYPE = ROCKER_TYPE || {};
ROCKER_TYPE.DEFAULT = "DEFAULT";// 默认类型
ROCKER_TYPE.AUTO = "AUTO"; // 自动类型
ROCKER_TYPE.HIDE = "HIDE"; // 隐藏类型
ROCKER_TYPE.OPACITY = 255; // 不透明类型
// 方向(0表示原点,从1开始,顺时针方向定义出方向)
var ROCKER_DIRECTION = ROCKER_DIRECTION || {};
ROCKER_DIRECTION.RIGHT = "RIGHT"; // 向右
ROCKER_DIRECTION.RIGHT_UP = "RIGHT_UP"; // 右上
ROCKER_DIRECTION.UP = "UP"; // 向上
ROCKER_DIRECTION.LEFT_UP = "LEFT_UP"; // 左上
ROCKER_DIRECTION.LEFT = "LEFT"; // 向左
ROCKER_DIRECTION.LEFT_DOWN = "LEFT_DOWN"; // 左下
ROCKER_DIRECTION.DOWN = "DOWN"; // 向下
ROCKER_DIRECTION.RIGHT_DOWN = "RIGHT_DOWN"; // 右下
ROCKER_DIRECTION.ORIGIN = "ORIGIN"; // 原点
// 方向数组
var ROCKER_DIRECTION_ARRAY = [
ROCKER_DIRECTION.RIGHT,
ROCKER_DIRECTION.RIGHT_UP,
ROCKER_DIRECTION.UP,
ROCKER_DIRECTION.LEFT_UP,
ROCKER_DIRECTION.LEFT,
ROCKER_DIRECTION.LEFT_DOWN,
ROCKER_DIRECTION.DOWN,
ROCKER_DIRECTION.RIGHT_DOWN,
ROCKER_DIRECTION.ORIGIN
];
// 8个方向的角度数组
var ROCKER_ANGLE_ARRAY = [22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5];
// 摇杆精灵
var Rocker = cc.Sprite.extend({
_baseNode : null, // 底盘[节点]
_knobNode : null, // 把手[节点]
_touchListener : null, // 触摸事件[监听器]
_radius : 0, // 摇杆的可移动半径
_angle : 0, // 角度
_velocity : cc.p(0, 0),// 速度
_callback : null, // 回调函数
_direction : ROCKER_DIRECTION.ORIGIN, // 方向
_type : ROCKER_TYPE.DEFAULT, // 摇杆类型
ctor: function(baseTexture, knobTexture, type){
this._super();
// 加载[底盘和摇杆精灵]
this.loadBaseAndKnob(baseTexture, knobTexture);
// 加载[配置]
this.loadConfig(type);
// 注册[监听器]
this.registerEvent();
// 调度器[触发callback回调函数]
this.scheduleUpdate();
return true;
},
onExit : function(){
this.unRegisterEvent();
this._super();
},
// 注册[触摸事件监听器]
registerEvent : function(){
this._touchListener = cc.EventListener.create({
event : cc.EventListener.TOUCH_ONE_BY_ONE,
target : this,
swallowTouches : true,
onTouchBegan : this.onTouchBegan,
onTouchMoved : this.onTouchMoved,
onTouchEnded : this.onTouchEnded
});
cc.eventManager.addListener(this._touchListener, this);
},
// 卸载[触摸事件监听器]
unRegisterEvent : function(){
cc.eventManager.removeListener(this._touchListener);
},
update : function(dt){
if (this._direction != ROCKER_DIRECTION.ORIGIN) {
this.onCallback(); // 触发回调函数
}
},
// 加载精灵[_baseNode和_knobNode]
loadBaseAndKnob : function(baseTexture, knobTexture){
this._baseNode = new cc.Sprite(baseTexture);
this._knobNode = new cc.Sprite(knobTexture);
this.addChild(this._baseNode);
this.addChild(this._knobNode);
},
// 加载配置[半径_radius和类型type等]
loadConfig : function(type){
this._radius = this._baseNode.getContentSize().width / 2;
if (type !== undefined){
if (isNaN(type)){
this._type = type;
if (this._type == ROCKER_TYPE.HIDE){
this.setVisible(false);
}
}else{
this._type = ROCKER_TYPE.OPACITY;
this.setCascadeOpacityEnabled(true); // 开启子节点透明度关联
this.setOpacity(type);
}
}
},
onTouchBegan: function (touch, event) {
var target = this.target;
var knob = target._knobNode; // 获取把手
var locationInNode = knob.convertToNodeSpace(touch.getLocation());
var size = knob.getContentSize();
var rect = cc.rect(0, 0, size.width, size.height);
if (target._type == ROCKER_TYPE.DEFAULT){ // 默认类型
if (!cc.rectContainsPoint(rect, locationInNode)) {
return false;
}
}else { // 非默认类型
if (target._type == ROCKER_TYPE.AUTO){
target.setVisible(true);
}
target.setPosition(touch.getLocation());
}
return true;
},
onTouchMoved: function (touch, event) {
// 节点获取
var target = this.target;
touch.getDelta()
var knob = target._knobNode;
// 触摸点转为摇杆的本地坐标
var locationInNode = target.convertToNodeSpace(touch.getLocation());
target.onUpdate(locationInNode); // 角度、方向、速度等更新
// 长度获取[当前触摸点相对摇杆中心点]
var length = cc.pLength(locationInNode);
var radians = cc.degreesToRadians(target._angle);
// 限制把手和原点的距离不能超过摇杆的半径
if ( length > target._radius){
var x = Math.cos(radians) * target._radius;
var y = Math.sin(radians) * target._radius;
knob.setPosition(cc.p(x, y));
}else{
knob.setPosition(locationInNode);
}
},
onTouchEnded: function (touch, event) {
var target = this.target;
if (target._type == ROCKER_TYPE.AUTO){
target.setVisible(false);
}
target.reset(); // 重置
target.onCallback(); // 触发回调函数
},
// 更新[角度、方向、速度]
onUpdate : function(pos){
// 更新[角度]
this.onUpdateAngle(pos);
// 更新[方向]
this.onUpdateDirection(pos);
// 更新[速度]
this.onUpdateVelocity();
},
// 更新[角度]
onUpdateAngle: function(pos){
this._angle = cc.radiansToDegrees(cc.pToAngle(pos));
if (this._angle < 0) {
this._angle += 360;
}
},
// 更新[方向]
onUpdateDirection : function(){
for (var i = 1; i < ROCKER_ANGLE_ARRAY.length; i++) {
this._direction = ROCKER_DIRECTION_ARRAY[0]; // 默认向右
if (this._angle >= ROCKER_ANGLE_ARRAY[i - 1] && this._angle < ROCKER_ANGLE_ARRAY[i]) {
this._direction = ROCKER_DIRECTION_ARRAY[i];
break;
}
}
},
// 更新[速度]
onUpdateVelocity : function(){
this._velocity.x = this._knobNode.getPositionX() / this._radius;
this._velocity.y = this._knobNode.getPositionY() / this._radius;
},
// 重置
reset : function(){
this._knobNode.setPosition(0, 0);
this._angle = 0;
this._velocity = cc.p(0, 0);
this._direction = ROCKER_DIRECTION.ORIGIN;
},
// 触发[回调函数]
onCallback : function(){
(this._callback && typeof(this._callback) === "function") && this._callback(this._velocity);
},
setCallback : function(callback){
this._callback = callback;
},
});
var testLayer = cc.Layer.extend({
rocker:null,
cocosIcon:null,
ctor:function(){
this._super(cc.color(150,150,150));
this.loadCocosIcon();
this._init();
return true;
},
loadCocosIcon(){
var node = new cc.Sprite(res.cyan_block);
this.addChild(node);
this.cocosIcon = node;
node.setPosition(cc.winSize.width/2,cc.winSize.height/2);
},
_init(){
var node = new Rocker(res.control_base,res.control_knob,ROCKER_TYPE.DEFAULT);
this.addChild(node);
node.setCallback(function(vec){
this.cocosIcon.x+=vec.x*5;
this.cocosIcon.y+=vec.y*5;
}.bind(this));
node.setPosition(100,100);
}
})
var testScene = cc.Scene.extend({
onEnter:function(){
this._super();
var layer = new testLayer();
this.addChild(layer);
}
})
至此摇杆已经封装完毕,在屏幕上可以实现有色方块根据摇杆的方向去移动。