本教程主要通过搭建一个横版摇杆八方向移动的实例,让大家如何用Cocos2dx-Js来做一款
游戏,从基础了解Cocos2dx-Js的基本实现原理,从创建工程,到各个知识点的梳理。

教程分为上下两讲:

上讲有2个小节:

1,工程的创建;

2,Cocos2dx-Js目录及Cocos2dx运行原理;

下讲有2个小节:

1,Cocos2dx-Js的事件处理机制;

2,摇杆的、八方向、精灵移动的实现;

Js环境搭载传送门:

【Cocos2d-Js基础教学(1)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. };

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

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

ccs.csLoader.createNode(res.MainScene_CSB);

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

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

然后Run看一下效果:

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

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

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

  1. //移动完后回调
  2. overStand:function() {
  3. if(this._hero_donghua.getAnimation().getCurrentMovementID()=="")
  4. {
  5. this._hero_donghua.getAnimation().play("stand");
  6. }
  7. },

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

  1. //主角监听
  2. var listener_Role = cc.EventListener.create({
  3. event: cc.EventListener.TOUCH_ONE_BY_ONE,
  4. swallowTouches: true,
  5. onTouchBegan: function (touch, event) {
  6. var target = event.getCurrentTarget();
  7.  
  8. var locationInNode = target.convertToNodeSpace(touch.getLocation());
  9. var s = target.getContentSize();
  10. var rect = cc.rect(0, 0, s.width, s.height);
  11.  
  12. if (cc.rectContainsPoint(rect, locationInNode)) {
  13. cc.log("sprite began... x = " + locationInNode.x + ", y = " + locationInNode.y);
  14. target.setOpacity(180);
  15. target.getAnimation().play("move");
  16. return true;
  17. }
  18. return false;
  19. },
  20. onTouchMoved: function (touch, event) {
  21. var target = event.getCurrentTarget();
  22. var delta = touch.getDelta();
  23. target.x += delta.x;
  24. target.y += delta.y;
  25.  
  26. },
  27. onTouchEnded: function (touch, event) {
  28. var target = event.getCurrentTarget();
  29. cc.log("sprite onTouchesEnded.. ");
  30. target.setOpacity(255);
  31. target.getAnimation().play("stand");
  32.  
  33. }
  34. });

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

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

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

还可以拖动的呢!

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

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

看代码:

  1. //摇杆监听
  2. var listener_YaoGan = cc.EventListener.create({
  3. event: cc.EventListener.TOUCH_ONE_BY_ONE,
  4. swallowTouches: true,
  5. onTouchBegan: function (touch, event) {
  6. var target = event.getCurrentTarget();
  7. var locationInNode = target.convertToNodeSpace(touch.getLocation());
  8. //创建摇杆
  9. this.sprite_yaogan = new cc.Sprite(res.YaoGan_png);
  10. this.sprite_yaogan.attr({
  11. x: locationInNode.x,
  12. y: locationInNode.y
  13. });
  14. target.addChild(this.sprite_yaogan, 4,90099);
  15.  
  16. //创建摇杆点
  17. this.sprite_yaogan_dian = new cc.Sprite(res.YaoGan_Dian_png);
  18. this.sprite_yaogan_dian.attr({
  19. x: locationInNode.x,
  20. y: locationInNode.y
  21. });
  22. target.addChild(this.sprite_yaogan_dian, 4,90999);
  23.  
  24. return true;
  25. },
  26.  
  27. onTouchMoved: function (touch, event) {
  28. //摇杆点
  29. var target = event.getCurrentTarget();
  30. var sp_dian = target.getChildByTag(90999);
  31. var sp_yaoganbd = target.getChildByTag(90099);
  32. var sp_hero = target.getChildByTag(99999);
  33.  
  34. //摇起来
  35. if(sp_dian!=null&&sp_yaoganbd!=null)
  36. {
  37. var p_dian = sp_yaoganbd.getPosition();
  38. var bd_width =sp_yaoganbd.getContentSize().width*0.5;
  39. cc.log("bd_width>>=="+bd_width);
  40. var point = touch.getLocation();
  41. var p_rad = this.getRad(p_dian,point);
  42. cc.log("p_rad>>=="+p_rad);
  43. //计算两个圆心之间距离
  44. var juli =Math.sqrt(Math.pow((p_dian.x - point.x),2) + Math.pow((p_dian.y - point.y),2));
  45. //距离不超过半径
  46. if(juli>=bd_width)
  47. {
  48. cc.log("go111>>>");
  49. sp_dian.setPosition(cc.pAdd(this.getAngelePosition(bd_width,p_rad),cc.p(p_dian.x,p_dian.y)));
  50. }
  51. else
  52. {
  53. cc.log("go2222>>>");
  54. var delta = touch.getDelta();
  55. sp_dian.x += delta.x;
  56. sp_dian.y += delta.y;
  57. }
  58.  
  59. // //判断方向---四方向
  60. // if(p_rad>=-PI/4&&p_rad<PI/4)
  61. // {
  62. // R_Direction="right";
  63. // }
  64. // else if(p_rad>=PI/4&&p_rad<3*PI/4)
  65. // {
  66. // R_Direction="up";
  67. // }
  68. // else if((p_rad>=3*PI/4&&p_rad<=PI)||(p_rad>=-PI&&p_rad<-3*PI/4))
  69. // {
  70. // R_Direction="left";
  71. // }
  72. // else if(p_rad>=-3*PI/4&&p_rad<-PI/4)
  73. // {
  74. // R_Direction="down";
  75. // }
  76.  
  77. //判断方向---八方向
  78. var move_x = parseInt(p_dian.x -point.x);
  79. var move_y = parseInt(p_dian.y -point.y);
  80.  
  81. if(move_x>=10&&move_y<=-10)
  82. {
  83. //左上
  84. R_Direction = "left_up";
  85. }
  86. else if(move_x>=10&&move_y>=10)
  87. {
  88. //左下
  89. R_Direction = "left_down";
  90. }
  91. else if(move_x<=-10&&move_y<=-10)
  92. {
  93. //右上
  94. R_Direction = "rigth_up";
  95. }
  96. else if(move_x<=-10&&move_y>=10)
  97. {
  98. //右下
  99. R_Direction = "rigth_down";
  100. }
  101. else if(move_x>-10&&move_x<10&&move_y>0)
  102. {
  103. //下
  104. R_Direction = "down";
  105. }
  106. else if(move_x>-10&&move_x<10&&move_y<0)
  107. {
  108. //上
  109. R_Direction = "up";
  110. }
  111. else if(move_x>0&&move_y>-10&&move_y<10)
  112. {
  113. //左
  114. R_Direction = "left";
  115. }
  116. else if(move_x<0&&move_y>-10&&move_y<10)
  117. {
  118. //右
  119. R_Direction = "right";
  120. }
  121.  
  122. R_Action="move";
  123. cc.log("R_Direction>>>"+R_Direction);
  124. }
  125. },
  126.  
  127. //获取半径坐标
  128. getAngelePosition:function(r,angle){
  129. return cc.p(r*Math.cos(angle),r*Math.sin(angle));
  130. },
  131.  
  132. //判断两点之间夹角
  133. getRad:function(pos1,pos2)
  134. {
  135. var px1 = pos1.x;
  136. var py1 = pos1.y;
  137. var px2 = pos2.x;
  138. var py2 = pos2.y;
  139.  
  140. //得到两点x的距离
  141. var x = px2 - px1;
  142. //得到两点y的距离
  143. var y = py1 - py2;
  144. //算出斜边长度
  145. var xie = Math.sqrt(Math.pow(x,2) + Math.pow(y,2));
  146. //得到这个角度的余弦值(通过三角函数中的店里:角度余弦值=斜边/斜边)
  147. var cosAngle = x / xie;
  148. //通过反余弦定理获取到期角度的弧度
  149. var rad = Math.acos(cosAngle);
  150. //注意:当触屏的位置Y坐标<摇杆的Y坐标,我们要去反值-0~-180
  151. if (py2 < py1)
  152. {
  153. rad = -rad;
  154. }
  155. return rad;
  156. },
  157.  
  158. onTouchEnded: function (touch, event) {
  159. var target = event.getCurrentTarget();
  160. if(target.getChildByTag(90099)!=null)
  161. {
  162. target.removeChildByTag(90099);
  163. }
  164. if(target.getChildByTag(90999)!=null)
  165. {
  166. target.removeChildByTag(90999);
  167. }
  168.  
  169. R_Action="stand";
  170.  
  171. var sp_hero = target.getChildByTag(99999);
  172. sp_hero.getAnimation().play("stand");
  173. }
  174.  
  175. });

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

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

跑起来的摇杆效果如下:

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

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

  1. //方向
  2. var R_Direction = "";
  3. //动作
  4. var R_Action = "stand";
  5. //移动速度
  6. var R_speed = 4;

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

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

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

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

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

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

  1. //更新状态
  2. runGame:function(){
  3.  
  4. if(R_Action=="move")
  5. {
  6. if(this._hero_donghua!=null)
  7. {
  8. if(this._hero_donghua.getAnimation().getCurrentMovementID()!="move")
  9. {
  10. this._hero_donghua.getAnimation().play("move");
  11. }
  12.  
  13. var p_hero_old = this._hero_donghua.getPosition();
  14. if(R_Direction=="right")
  15. {
  16. this._hero_donghua.setScaleX(-1);
  17. this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y));
  18.  
  19. }
  20. else if(R_Direction=="up")
  21. {
  22. this._hero_donghua.setPosition(cc.p(p_hero_old.x,p_hero_old.y+R_speed));
  23.  
  24. }
  25. else if(R_Direction=="left")
  26. {
  27. this._hero_donghua.setScaleX(1);
  28. this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y));
  29.  
  30. }
  31. else if(R_Direction=="down")
  32. {
  33. this._hero_donghua.setPosition(cc.p(p_hero_old.x,p_hero_old.y-R_speed));
  34.  
  35. }
  36. else if(R_Direction=="left_up")
  37. {
  38. this._hero_donghua.setScaleX(1);
  39. this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y+R_speed));
  40.  
  41. }
  42. else if(R_Direction=="left_down")
  43. {
  44. this._hero_donghua.setScaleX(1);
  45. this._hero_donghua.setPosition(cc.p(p_hero_old.x-R_speed,p_hero_old.y-R_speed));
  46.  
  47. }
  48. else if(R_Direction=="rigth_up")
  49. {
  50. this._hero_donghua.setScaleX(-1);
  51. this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y+R_speed));
  52. }
  53. else if(R_Direction=="rigth_down")
  54. {
  55. this._hero_donghua.setScaleX(-1);
  56. this._hero_donghua.setPosition(cc.p(p_hero_old.x+R_speed,p_hero_old.y-R_speed));
  57.  
  58. }
  59. }
  60. }
  61. }

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

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

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

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

 
 
 
 
 
 

【Cocos2d-Js实战教学(1)横版摇杆八方向移动】的更多相关文章

  1. unity3d easytouch计算摇杆旋转角度以及摇杆八方向控制角色

    在写第三人称控制的时候,一开始在电脑测试是用WASD控制角色 后来需要发布到手机上,于是就加了一个摇杆 键盘控制角色的代码已经写好了,角色八方向移动 如果按照传统的大众思路来控制的话,是达不到我想要的 ...

  2. iKcamp团队制作|基于Koa2搭建Node.js实战项目教学(含视频)☞ 环境准备

    安装搭建项目的开发环境 视频地址:https://www.cctalk.com/v/15114357764004 文章 Koa 起手 - 环境准备 由于 koa2 已经开始使用 async/await ...

  3. Linux实战教学笔记03:操作系统发展历程及系统版本选择

    标签(空格分隔): Linux实战教学笔记-陈思齐 第1章 Linux简介 1.1 什么是操作系统? 简单讲:操作系统就是一个人与计算机硬件的中介. 操作系统,英文名称Operating System ...

  4. 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)

    轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...

  5. 《Node.js实战(双色)》作者之一——吴中骅访谈录

  6. 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程:简介及目录》(附上完整工程文件)

    介绍:讲述如何使用Genesis-3D来制作一个横版格斗游戏,涉及如何制作连招系统,如何使用包围盒实现碰撞检测,软键盘的制作,场景切换,技能读表,简单怪物AI等等,并为您提供这个框架的全套资源,源码以 ...

  7. 如何让格斗游戏的横版过关(2) Cocos2d-x 2.0.4

    在第一章<如何使横版格戏>基础上.添加角色运动.碰撞.敌人.AI和音乐音效,原文<How To Make A Side-Scrolling Beat 'Em Up Game Like ...

  8. 微信小程序横版日历,tab栏

    代码地址如下:http://www.demodashi.com/demo/14243.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...

  9. cocos2d js jsb XMLHttpRequest 中文乱码

    1.首先讲下怎样使用XMLHttpRequest 下面所说的是在cocos2d-x 2.2.2 或者 2.3 版本号中. 首先要明确cocos2d js事实上分两个版本号,一个是html5的版本号,另 ...

随机推荐

  1. tp中引入js、css、img的问题

    方法一: 直接把js.css.img放到网站公共目录/Public/下. 然后直接在模板文件中使用__PUBLIC__进行替换. 方法二: 在模块配置文件config.php中配置指定的路径,如下: ...

  2. nginx 反向代理 apache 服务

    反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时 ...

  3. WPF之数据触发器 改变控件背景色或闪烁

    需求,很多矩形表示桶,其中:空桶=红色,满桶=绿色,使用中=红绿闪烁. <Window x:Class="FlickerDemo.MainWindow" xmlns=&quo ...

  4. SpringBoot集成篇(二) 异步调用Async

    什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 如何实现异步调用? 多线程, ...

  5. 构造函数constructor 与析构函数destructor(二)

    (1)转换构造函数 转换构造函数的定义:转换构造函数就是把普通的内置类型转换成类类型的构造函数,这种构造函数只有一个参数.只含有一个参数的构造函数,可以作为两种构造函数,一种是普通构造函数用于初始化对 ...

  6. 2018.08.18 NOIP模拟 travel(贪心)

    Travel 题目背景 SOURCE:NOIP2015-SHY4 题目描述 小 A 要进行一次旅行.这回他要在序号为 1 到 n 的 n 个城市之间旅行.这 n 个城市之间共有 m 条连接两个城市的单 ...

  7. gj2 python中一切皆对象

    2.1 python中一切皆是对象 动态语言和静态语言的区别,Python的面向对象更彻底 同时动态语言,代码的灵活性高 没有编译(检查)的过程,错误只有在运行起来后才会发现 函数和类也是对象,属于p ...

  8. js 验证input 输入框

    <h1>js验证输入框内容</h1><br /><br /> 只能输入英文<input type="text" onkeyup ...

  9. TabHost实现通话记录界面

    //MainActivity.java   public class MainActivity extends TabActivity   {       @Override       public ...

  10. BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8112  Solved: 2569[Submit] ...