首页 > 代码库 > 【cocos2d-x 3.2 - JS -横版摇杆八方向移动】

【cocos2d-x 3.2 - JS -横版摇杆八方向移动】

花了少许时间利用了一下cocos2dx 3.2Js版本+cocosstiduo2.0.6做了一个横版摇杆八方向的demo;

目前到今天为止,Js版本为3.2稳定版本,官网下载传送门:

http://www.cocos2d-x.org/filedown/cocos2d-js-v3.2.zip

 

Js环境搭载传送门:

【cocos2d-x 3.0 - JS -Mac配置篇】

 

轻松搭建完后,开始用JS写一个横版摇杆动作游戏的Demo,听起来貌似很高大上~~。

首先要做好几个准备:

1,角色精灵,我准备了一个骨骼动画精灵1个,cocosstiduo2.0.6制作的;

2,地图,也是用cocosstiduo2.0.6制作,生成出MainScene.csb 文件;

技术分享

3,摇杆的PNG素材;

技术分享 技术分享

 

下面开始创建一个新的工程GoFighting,创建主场景MainLayer.js文件;

MainLayer继承BaseLayer.js,BaseLayer中处理这个层基本的页面处理,包括弹出的新层的遮罩处理;

 

BaseLayer.js:

技术分享
 1 var BaseLayer=cc.Layer.extend({ 2     _bgFrame:null, 3     _notShowAnimation:null, 4     _directorSteps:null, 5     _showAnied:false, 6     init:function(notShowAnimation){ 7         var bret=false; 8         if(this._super()){ 9             //不可删除10             var bgFrame = cc.LayerColor(cc.color(0,0,0,200));11             this.addChild(bgFrame);12             this._bgFrame=bgFrame;13             this._notShowAnimation=notShowAnimation;14             this.setAnchorPoint(cc.p(0.5,0.5));15             this.ignoreAnchorPointForPosition(false);16             if(!this._notShowAnimation){17                 this.setScale(0.8);18             }19             this.setContentSize(winSize);20             this.setPosition(cc.p(winSize.width/2,winSize.height/2));21 22             cc.eventManager.addListener({23                 event: cc.EventListener.TOUCH_ONE_BY_ONE,24                 swallowTouches: true,25                 //onTouchMoved: this.onTouchMoved,26                 onTouchBegan: function(){return true;}27             }, this);28 29             bret=true;30         }31         return bret;32     },33     setBgColor:function(color){34         this._bgFrame.setColor(color);35     },36 37     onEnter:function(){38         this._super();39         if(!this._notShowAnimation&&!this._showAnied){40             var sl=cc.EaseIn.create(cc.ScaleTo.create(0.15,1.1),2);41             var sl2=cc.ScaleTo.create(0.15,1);42             var seq=cc.Sequence.create(sl,sl2);43             this.runAction(seq);44             this._showAnied=true;45         }46     },47 48     onExit:function(){49         this._super();50         MemoryManager.getInstance().releaseMeoryFromOther();51     }52 });53 54 BaseLayer.OpenActionFs=function(obj){55     obj.setScale(0.8);56     if(obj!=null){57         var sl=cc.EaseIn.create(cc.ScaleTo.create(0.15,1.1),2);58         var sl2=cc.ScaleTo.create(0.15,1);59         var seq=cc.Sequence.create(sl,sl2);60         obj.runAction(seq);61     }62 };
View Code

 

首先我们加载主场景必须得背景图片,而主场景背景图片由cocosstiduo2.0.6制作,如何绑定呢?

在3.2引擎终目前还不支持直接使用widgetFromBinaryFile方法加载CSB,那么换成另外一种加载创建Node的方式:

ccs.csLoader.createNode(res.MainScene_CSB);

使用该方法需要自己去添加全路径

 /*        cocostidio制作的CSB文件加载,注:        在3.2引擎终目前还不支持直接使用widgetFromBinaryFile方法加载CSB         */        var baseroot = ccs.csLoader.createNode(res.MainScene_CSB);        baseroot.setAnchorPoint(cc.p(0.5,0.5));        baseroot.setPosition(this.getContentSize().width/2,this.getContentSize().height/2);        this.baseroot=baseroot;        this.addChild(baseroot,1,9001);        BaseLayer.OpenActionFs(baseroot);

 

然后Run看一下效果:

技术分享

 

然后继续加载角色的骨骼动画

        //角色骨骼动画加载        var charname = "Char_014_1";        var nowcharurl = resRole+charname+".ExportJson";        if(jsb.fileUtils.isFileExist(nowcharurl)==true) {            cc.log("nowcharurl =" + nowcharurl);            ccs.ArmatureDataManager.getInstance().addArmatureFileInfo(nowcharurl);            var hero = ccs.Armature.create(charname);            this._hero_donghua = hero;            hero.setPosition(cc.p(330, 260));            hero.getAnimation().play("stand");            hero.getAnimation().setMovementEventCallFunc(this.overStand, this);           baseroot.addChild(hero, 3,99999);        }

 

角色hero有回调,如跑动后停下来的回调:

    //移动完后回调    overStand:function() {        if(this._hero_donghua.getAnimation().getCurrentMovementID()=="")        {            this._hero_donghua.getAnimation().play("stand");        }    },

 

单单一个角色植入场景是否显得逻辑太单调,我们可以拖动这个精灵岂不更好,加一个简单的事件,让精灵活一点吧!!

//主角监听var listener_Role = cc.EventListener.create({    event: cc.EventListener.TOUCH_ONE_BY_ONE,    swallowTouches: true,    onTouchBegan: function (touch, event) {        var target = event.getCurrentTarget();        var locationInNode = target.convertToNodeSpace(touch.getLocation());        var s = target.getContentSize();        var rect = cc.rect(0, 0, s.width, s.height);        if (cc.rectContainsPoint(rect, locationInNode)) {            cc.log("sprite began... x = " + locationInNode.x + ", y = " + locationInNode.y);            target.setOpacity(180);            target.getAnimation().play("move");            return true;        }        return false;    },    onTouchMoved: function (touch, event) {        var target = event.getCurrentTarget();        var delta = touch.getDelta();        target.x += delta.x;        target.y += delta.y;    },    onTouchEnded: function (touch, event) {        var target = event.getCurrentTarget();        cc.log("sprite onTouchesEnded.. ");        target.setOpacity(255);        target.getAnimation().play("stand");    }});

在ctor构造中添加角色事件的注册方法:

//人物cc.eventManager.addListener(listener_Role, this._hero_donghua);

 

OK,我们再Run起来看看效果:

技术分享

还可以拖动的呢!

 

然后,我们继续实现摇杆模式:

摇杆与事件有关,JS中摇杆须继承cc.EventListener去创建事件,事件类型cc.EventListener.TOUCH_ONE_BY_ONE(单点触摸方式);

看代码:

//摇杆监听var listener_YaoGan = cc.EventListener.create({    event: cc.EventListener.TOUCH_ONE_BY_ONE,    swallowTouches: true,    onTouchBegan: function (touch, event) {        var target = event.getCurrentTarget();        var locationInNode = target.convertToNodeSpace(touch.getLocation());        //创建摇杆        this.sprite_yaogan = new cc.Sprite(res.YaoGan_png);        this.sprite_yaogan.attr({            x: locationInNode.x,            y: locationInNode.y        });        target.addChild(this.sprite_yaogan, 4,90099);        //创建摇杆点        this.sprite_yaogan_dian = new cc.Sprite(res.YaoGan_Dian_png);        this.sprite_yaogan_dian.attr({            x: locationInNode.x,            y: locationInNode.y        });        target.addChild(this.sprite_yaogan_dian, 4,90999);        return true;    },    onTouchMoved: function (touch, event) {        //摇杆点        var target = event.getCurrentTarget();        var sp_dian = target.getChildByTag(90999);        var sp_yaoganbd = target.getChildByTag(90099);        var sp_hero = target.getChildByTag(99999);        //摇起来        if(sp_dian!=null&&sp_yaoganbd!=null)        {            var p_dian =  sp_yaoganbd.getPosition();            var bd_width =sp_yaoganbd.getContentSize().width*0.5;            cc.log("bd_width>>=="+bd_width);            var point = touch.getLocation();            var p_rad = this.getRad(p_dian,point);            cc.log("p_rad>>=="+p_rad);            //计算两个圆心之间距离            var juli =Math.sqrt(Math.pow((p_dian.x - point.x),2) + Math.pow((p_dian.y - point.y),2));            //距离不超过半径            if(juli>=bd_width)            {                cc.log("go111>>>");                sp_dian.setPosition(cc.pAdd(this.getAngelePosition(bd_width,p_rad),cc.p(p_dian.x,p_dian.y)));            }            else            {                cc.log("go2222>>>");                var delta = touch.getDelta();                sp_dian.x += delta.x;                sp_dian.y += delta.y;            }//            //判断方向---四方向//            if(p_rad>=-PI/4&&p_rad<PI/4)//            {//                R_Direction="right";//            }//            else if(p_rad>=PI/4&&p_rad<3*PI/4)//            {//                R_Direction="up";//            }//            else if((p_rad>=3*PI/4&&p_rad<=PI)||(p_rad>=-PI&&p_rad<-3*PI/4))//            {//                R_Direction="left";//            }//            else if(p_rad>=-3*PI/4&&p_rad<-PI/4)//            {//                R_Direction="down";//            }            //判断方向---八方向            var move_x =  parseInt(p_dian.x -point.x);            var move_y =  parseInt(p_dian.y -point.y);            if(move_x>=10&&move_y<=-10)            {                //左上                R_Direction = "left_up";            }            else if(move_x>=10&&move_y>=10)            {                //左下                R_Direction = "left_down";            }            else if(move_x<=-10&&move_y<=-10)            {                //右上                R_Direction = "rigth_up";            }            else if(move_x<=-10&&move_y>=10)            {                //右下                R_Direction = "rigth_down";            }            else if(move_x>-10&&move_x<10&&move_y>0)            {                //                R_Direction = "down";            }            else if(move_x>-10&&move_x<10&&move_y<0)            {                //                R_Direction = "up";            }            else if(move_x>0&&move_y>-10&&move_y<10)            {                //                R_Direction = "left";            }            else if(move_x<0&&move_y>-10&&move_y<10)            {                //                R_Direction = "right";            }            R_Action="move";            cc.log("R_Direction>>>"+R_Direction);        }    },    //获取半径坐标    getAngelePosition:function(r,angle){        return cc.p(r*Math.cos(angle),r*Math.sin(angle));    },    //判断两点之间夹角    getRad:function(pos1,pos2)    {        var px1 = pos1.x;        var py1 = pos1.y;        var px2 = pos2.x;        var py2 = pos2.y;        //得到两点x的距离        var x = px2 - px1;        //得到两点y的距离        var y = py1 - py2;        //算出斜边长度        var xie = Math.sqrt(Math.pow(x,2) + Math.pow(y,2));        //得到这个角度的余弦值(通过三角函数中的店里:角度余弦值=斜边/斜边)        var cosAngle = x / xie;        //通过反余弦定理获取到期角度的弧度        var rad = Math.acos(cosAngle);        //注意:当触屏的位置Y坐标<摇杆的Y坐标,我们要去反值-0~-180        if (py2 < py1)        {            rad = -rad;        }        return rad;    },    onTouchEnded: function (touch, event) {        var target = event.getCurrentTarget();        if(target.getChildByTag(90099)!=null)        {            target.removeChildByTag(90099);        }        if(target.getChildByTag(90999)!=null)        {            target.removeChildByTag(90999);        }        R_Action="stand";        var sp_hero = target.getChildByTag(99999);        sp_hero.getAnimation().play("stand");    }});

在上面这个Js类中,包含了几个方法如,两点之间夹角的计算公式和最大半径坐标的计算公式;

因为我们需要在摇杆和摇杆点上面去做坐标处理,计算出夹角来对角色进行坐标位移操作,达到我们所需要的效果

跑起来的摇杆效果如下:

技术分享

摇杆可以活动了,并且不能超过底下的背景半径,达到了我们需要的效果,下面就继续实现摇杆操控精灵移动的功能

可以继续在onTouchMoved: function (touch, event)事件终写方法获取一些判定参数:

//方向var R_Direction = "";//动作var R_Action = "stand";//移动速度var R_speed = 4;

继续看listener_YaoGan类中的方向判断,我写了2种角色移动方法:

1,根据PI=3.1415 来计算 ,做了4方向的标识判断

2,根据坐标差值来计算,做了8方向的标识判断

OK,两种方法都可以行,可以自己拓展。

有了标识我们需要启动一个定时器来执行人物的操作

下面是定时器部分的代码:

//更新状态    runGame:function(){        if(R_Action=="move")        {            if(this._hero_donghua!=null)            {                if(this._hero_donghua.getAnimation().getCurrentMovementID()!="move")                {                    this._hero_donghua.getAnimation().play("move");                }                var p_hero_old = this._hero_donghua.getPosition();                if(R_Direction=="right")                {                    this._hero_donghua.setScaleX(-1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y));                }                else if(R_Direction=="up")                {                    this._hero_donghua.setPosition(cc.p(p_hero_old.x,p_hero_old.y+R_speed));                }                else if(R_Direction=="left")                {                    this._hero_donghua.setScaleX(1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y));                }                else if(R_Direction=="down")                {                    this._hero_donghua.setPosition(cc.p(p_hero_old.x,p_hero_old.y-R_speed));                }                else if(R_Direction=="left_up")                {                    this._hero_donghua.setScaleX(1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y+R_speed));                }                else if(R_Direction=="left_down")                {                    this._hero_donghua.setScaleX(1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y-R_speed));                }                else if(R_Direction=="rigth_up")                {                    this._hero_donghua.setScaleX(-1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y+R_speed));                }                else if(R_Direction=="rigth_down")                {                    this._hero_donghua.setScaleX(-1);                    this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y-R_speed));                }            }        }    }

OK,人物可以根据摇杆八方向的跑动起来了,我们Run起来看看效果,应该很赞!

技术分享

 

嗯,该Demo就开发完毕了,下面是整个DEMO的下载地址,希望能大家对大家起到帮助;

cocos2d-x 3.2 - JS -横版摇杆八方向移动DEMO下载地址

自己创建一个新的工程,将ZIP解压文件拷贝到工程根目录就可以Run起来,替换main.js和project.json;

 

【cocos2d-x 3.2 - JS -横版摇杆八方向移动】