旋转循环页视图实现

设置节点

编写代码


在这一节中我们实现一个类似旋转门的页视图(PageView)。

运行效果如下:

Cocos Creator版本:2.2.0

后台回复"旋转页视图",获取该项目完整文件:

设置节点

首先创建以下节点:

1. cardsNode为一个空节点,大小跟Canvas一样(我们之后会在该节点上设置触摸监听)。

2. card1-card6为cardNode的子节点,类型为Sprite,图片都在textures文件夹中:

现在我们把card1-card6节点的x坐标设置一下,将他们摆放在不同位置:

card1和card4是重叠的,其他card节点朝两边摆开。

注:因为节点顺序zIndex的关系,所以我们发现这里的遮挡关系其实不正确,之后需要在代码中调整。

编写代码

创建一个Revolve.js脚本文件,挂到cardsNode节点上,在onLoad方法中设置在各个位置上的card节点应有的属性:

// Revolve.js
onLoad () {this.attrArray = [JSON.stringify({zIndex: 3,scale: 1,opacity: 255,pos: this.node.children[0].position}),JSON.stringify({zIndex: 2,scale: 0.8,opacity: 180,pos: this.node.children[1].position}),JSON.stringify({zIndex: 1,scale: 0.5,opacity: 100,pos: this.node.children[2].position}),JSON.stringify({zIndex: 0,scale: 0.2,opacity: 30,pos: this.node.children[3].position}),JSON.stringify({zIndex: 1,scale: 0.5,opacity: 100,pos: this.node.children[4].position}),JSON.stringify({zIndex: 2,scale: 0.8,opacity: 180,pos: this.node.children[5].position}),];
},

attrArray变量是一个数组,其中的元素都为JSON类型。

我们拿第一个元素来讲解:第一个元素指的是在正当中(C位),玩家当前正在观看的那张card节点(注意不一定是card1,因为玩家会滑动屏幕,card节点会更换)。

zIndex:此时该节点的zIndex值应该是最大的,不能被其他节点所遮挡。

scale和opacity:节点大小和透明度为原始状态,所以scale值和opacity值为1。

pos:因为我们最开始摆放时,card1节点在正当中,所以card1最开始的位置就是C位卡片应有的位置。由于card1节点位置会在玩家滑动后发生改变,所以我们这里需要调用JSON.stringfy方法对元素进行字符串化。

其余的元素代表其他位置上card节点应有的属性状态。

现在在onLoad方法中添加如下代码对各个节点进行初始化:

// Revolve.js
onLoad () {...// 将cardsNode子节点的各个属性初始化this.cardsArray = this.node.children;for (let i=0; i<this.cardsArray.length; i++) {this.cardsArray[i].num = i;let initAttr = JSON.parse(this.attrArray[i]);this.cardsArray[i].zIndex = initAttr['zIndex'];this.cardsArray[i].scale = initAttr['scale'];this.cardsArray[i].opacity = initAttr['opacity'];// this.cardsArray[i].pos = initAttr['pos'];}
},

笔者这里给各个card节点加了一个num属性值,该值用来判断它们各自所处的位置,也就知道它们当前所应该呈现的属性状态。比如某节点num等于2的话,那么该节点的属性状态就对应为attrArray数组中的第3个元素。当然num值在玩家滑动后会发生改变。

运行后,效果如下:

接着我们要做的就是处理玩家滑动事件。在onLoad方法中添加触摸监听代码(只用监听touchmove就可以了):

// Revolve.js
onLoad () {...// 触摸监听this.node.on('touchmove', this.onTouchMove, this);
},

onTouchMove方法编写如下:

// Revolve.js
onTouchMove (event) {let deltaX = event.getDelta().x;if (deltaX > this.node.parent.width / 40) {// 说明是往右滑动this.revolve2Right();}else if (deltaX < -this.node.parent.width / 40) {// 说明是向左滑动this.revolve2Left();}
},

通过判断玩家横向滑动的距离来执行相应代码(this.node.parent就是Canvas)。

revolve2Right方法编写如下:

// Revolve.js
revolve2Right () {// 往右旋转for (let i=0; i<this.cardsArray.length; i++) {// 所有节点编号+1if (this.cardsArray[i].num < this.cardsArray.length-1)this.cardsArray[i].num += 1;elsethis.cardsArray[i].num = 0;// 获取目标属性let nextAttr = JSON.parse(this.attrArray[this.cardsArray[i].num]);// 改变z值this.cardsArray[i].zIndex = nextAttr['zIndex'];// 改变大小、透明度、位置let scaleAction = cc.scaleTo(this.revolveTime, nextAttr['scale']);let fadeAction = cc.fadeTo(this.revolveTime, nextAttr['opacity']);let moveAction = cc.moveTo(this.revolveTime, nextAttr['pos']);let spawnAction = cc.spawn(scaleAction, fadeAction, moveAction);spawnAction.setTag(1);      // 设置动作标签this.cardsArray[i].runAction(spawnAction);}
}

如果向右滑动的话,那么所有card节点的num值加1,但注意num值最大如果超过cardsArray数组长度减1的话,就要归0(不然就超过数组下标临界值,获取不到元素了)。设置好num值后,我们就可以设置各个card节点的zIndex,scale,opacity和pos值了。revolveTime在properties中创建:

properties: {revolveTime: 0.8            // 旋转所需时间
},

大家可以发现笔者给spawnAction设置了一个tag,这个稍后会讲到。

rovolve2Left方法同理:

// Revolve.js
revolve2Left () {// 往左旋转for (let i=0; i<this.cardsArray.length; i++) {// 所有节点编号-1if (this.cardsArray[i].num > 0)this.cardsArray[i].num -= 1;elsethis.cardsArray[i].num = this.cardsArray.length-1;// 获取目标属性let nextAttr = JSON.parse(this.attrArray[this.cardsArray[i].num]);// 改变z值this.cardsArray[i].zIndex = nextAttr['zIndex'];// 改变大小、透明度、位置let scaleAction = cc.scaleTo(this.revolveTime, nextAttr['scale']);let fadeAction = cc.fadeTo(this.revolveTime, nextAttr['opacity']);let moveAction = cc.moveTo(this.revolveTime, nextAttr['pos']);let spawnAction = cc.spawn(scaleAction, fadeAction, moveAction);spawnAction.setTag(1);      // 设置动作标签this.cardsArray[i].runAction(spawnAction);}
},

现在大家运行项目,滑动后发现界面变成了下面这个混乱的样子:

那是因为我们每次滑动,onTouchMove方法都被调用了好几次,而每次调用时各个card节点都会执行相应动作。问题是之前的动作都还没执行完毕,新的执行就又来了,所以才会导致以上情况出现。

解决办法就是在onTouchMove中先判断动作是否执行完毕。如果不是的话,直接return。

// Revolve.js
onTouchMove (event) {// 首先判断动作是否执行完for (let i=0; i<this.cardsArray.length; i++) {if (this.cardsArray[i].getActionByTag(1))return;}let deltaX = event.getDelta().x;if (deltaX > this.node.parent.width / 40) {// 说明是往右滑动this.revolve2Right();}else if (deltaX < -this.node.parent.width / 40) {// 说明是向左滑动this.revolve2Left();}
},

这里的重点就是getActionByTag方法。我们在revolve2Right和revolve2Left方法中给spawnAction设置了一个标签,如果spawnAction没有在执行(或者执行完毕),那么getActionByTag(1)就会返回null;而如果正在执行的话,就会返回一个object。

现在运行项目,旋转就正常了:

好,那今天的教程就到这,希望大家有所收获~

《Cocos Creator游戏实战》旋转循环页视图实现相关推荐

  1. 《Cocos Creator游戏实战》实现下拉框按钮ComboBox控件

    实现下拉框按钮ComboBox控件 创建节点 编写脚本 该功能已收录在Many Widgets插件中,使用Cocos Creator 3.x版本的小伙伴可以用该插件快速生成下拉框ComboBox控件. ...

  2. 《Cocos Creator游戏实战》贪吃蛇平滑移动

    贪吃蛇平滑移动 贪吃蛇平滑移动 初始化蛇头和蛇身 调整蛇头方向 贪吃蛇移动 蛇头和蛇身的节点顺序 添加食物 添加碰撞逻辑代码 从pointsArray中剔除无用的坐标点(更新) 在本教程中我们重点来学 ...

  3. 《Cocos Creator游戏实战》棋类游戏中的棋子摆放逻辑

    棋类游戏中的棋子摆放逻辑 创建节点 代码编写 其实要点就一句话:我们看到的不应是棋盘,而是坐标. 现在通过下面的五子棋(或围棋)实例来看下如何理解这句话. 运行效果如下: Cocos Creator版 ...

  4. 《Cocos Creator游戏实战》摘星星进阶版

    摘星星进阶版 添加开始按钮 实现按钮功能 显示"Game Over" 限制主角移动范围 让跳跃动作更加细腻 加入星星收集动画 编写动画脚本 加入触屏控制 添加游戏提示 Cocos ...

  5. 《Cocos Creator游戏实战》关卡功能实现

    关卡功能实现 创建节点 设置关卡信息 实现关卡界面 为预制添加脚本 完善Game.js逻辑 在上一节教程中我们讲解了打砖块的主要功能与逻辑实现,在这一篇教程中,笔者会在它的基础上增加关卡功能(建议先阅 ...

  6. 《Cocos Creator游戏实战》老虎机抽奖效果实现思路

    在线体验地址 Cocos Creator | SlotMachine Cocos Store 购买地址(如果没有显示,那就是还在审核): https://store.cocos.com/app/det ...

  7. 《Cocos Creator游戏实战》游戏转场时如何保留节点信息

    游戏转场时如何保留节点信息 使用常驻节点 使用全局变量 使用本地存储 引擎同时只会运行一个场景,当切换场景时,默认会将场景内所有节点和其他实例销毁(本句来自Cocos Creator文档). 在这一节 ...

  8. 《Cocos Creator游戏实战》虚拟摇杆实现

    虚拟摇杆实现 摇杆布局实现 摇杆功能实现 用摇杆控制主角 该功能已收录在Many Widgets插件中,使用Cocos Creator 3.x版本的小伙伴可以用该插件快速生成摇杆. 插件地址:http ...

  9. 《Cocos Creator游戏实战》新手引导实现

    新手引导实现 新建节点 完成代码 该功能已收录在Many Widgets插件中,使用Cocos Creator 3.x版本的小伙伴可以用该插件快速生成新手引导. 插件地址:https://store. ...

最新文章

  1. java 冒泡排序和快速排序 实现
  2. 【斗医】【13】Web应用开发20天
  3. 春节后面试别人的经历总结之一,好岗位分享给还在找工作中的软件开发爱好者们【转】...
  4. django 不用自带的mysql_python笔记二 django自带后台管理系统、模版渲染以及使用mysql数据库...
  5. JavaScript 中 JSON.parse()和JSON.stringify()
  6. java之写接口回调编程经验改进
  7. oracle创建用户名了,oracle创建用户名
  8. .NET开发Silverlight程序:界面和对象模型
  9. asp.net文本编辑器FCKeditor使用方法详解 - 橙色大地 - 博客园
  10. es6之模块化(module)--绝对能看懂
  11. Mapreduce执行过程分析(基于Hadoop2.4)——(三)
  12. 【DB笔试面试1-100】
  13. 利用感应加热原理,3秒即可烧红铁棒!
  14. windows命令行工具
  15. 后端程序员福音 -- TellMe 推送助手
  16. python第一次作业
  17. ValueError: The view XXXView didn't return an HttpResponse object. It returned None
  18. 一个神奇的下载按钮css实现
  19. Openjudge:鸡尾酒疗法
  20. java基本语法实验体会_Java基本语法实验报告

热门文章

  1. 嵌入式学习(二)——刷机和led实验(看门狗、c语言、icache、重定位、SDRAM)
  2. java测试开发工程师,必须要明白的几处知识(附面试问题)
  3. H3C服务器安装Windows Server2012R2
  4. linux常用命令操作
  5. MyBatis的核心对象
  6. 什么是JPA(Java persistence API)?
  7. 绿色家居新革命 变频技术让你聪明节电
  8. C++继承和派生笔记
  9. 成都传智播客java培训中心
  10. SSH-远程连接文件传输