Cocos 2d-js 虚拟摇杆

虚拟摇杆是在手机格斗游戏中经常看到的一个东西,用来控制人物的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);
    }
})
至此摇杆已经封装完毕,在屏幕上可以实现有色方块根据摇杆的方向去移动。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值