《Cocos Creator游戏实战》滚动数字

滚动数字

创建节点

滚动原理

编写脚本


本节我们来实现数字滚动的效果。

运行效果如下:

Cocos Creator版本:2.2.0

公众号后台回复"滚动数字",获取完整项目源码:

创建节点

层级管理器中我们创建以下节点:

  1. esitbox即EditBox控件,用于输入数字。
  2. ok_btn即一个按钮控件,当玩家输完数字,点击按钮后,数字滚动。
  3. all_layout是一个横向布局节点,具体用处之后会介绍。
  4. number_layout是本节教程的核心,它是一个垂直布局节点,其中放入值为0-9以及"."符号的这些Label控件。

number_layout节点:

注:水平和垂直布局的缩放模式(Resize Mode)都为CONTAINER。

此时场景编辑器显示如下:

注:节点的坐标大家可以自己摆放,或者打开笔者的项目查看,这里就不再截图。

滚动原理

其实数字滚动的原理非常简单,就是改变number_layout节点的y坐标。

我们先给all_layout加上Mask组件,把其余的数字或"."符号先遮住:

注:若要添加Mask节点,须将节点上的Sprite组件先移除。

那现在笔者把number_layout节点的y坐标变大,也就是让整个节点往上走,显示出来的就是比5大的数字了:

同理,如果笔者把y坐标变小,显示的就会是比5小的数字。

number_layout代表的就是数字上某一位,如果要表示多位数,那么我们只用多创建几个number_layout就行了(自然而然想到应该把number_layout变为预制)。

编写脚本

我们创建一个名称为Roll.js的脚本,在properties中添加如下属性:

// Roll.js
properties: {        
    numLayoutPrefab: cc.Prefab,
    allLayoutNode: cc.Node,
    editNode: cc.Node,
    rollTime: 2,
},
  1. numLayoutPrefab就是number_layout变成的预制。
  2. allLayoutNode就是all_layout节点。
  3. editNode就是editbox节点。
  4. rollTime为滚动动作所需时间。

在onLoad方法中我们编写如下代码:

// Roll.js
onLoad () {
    // 节点池
    this.prefabPool = new cc.NodePool();
    // 预制数组,方便管理
    this.prefabArray = [];
    // 获取每个数字长度,用于获取y坐标
    let numLayout = cc.instantiate(this.numLayoutPrefab);
    this.eachHeight = numLayout.height / 11;
    this.prefabPool.put(numLayout);
},
  1. 节点池用来提高性能。
  2. 这里的prefabArray挺重要的,我们之后会讲到它的用法。
  3. 为了准确地显示出数字,我们需要求出number_layout中每个数字的高度(即每个Label控件的高度),这样就可以求出number_layout目标坐标点的y值了。

现在我们实现getNumStr方法来获取输入框文本:

// Roll.js
getNumStr () {
    // 获取编辑框中输入的数字(字符串)
    let numStr = this.editNode.getComponent(cc.EditBox).string;
    return numStr;
},

接着在okBtn方法中判断玩家输入的字符串是否可以转为数字(记得给ok_btn按钮绑上该方法):

// Roll.js
okBtn () {
    // 首先获取数字(字符串)
    let numStr = this.getNumStr();
    
    // 再判断是否可以转换为数字
    let num = Number(numStr);
    if (!isNaN(num)) {
        console.log('是数字!');
    }
    else {
        console.log('非数字!');
    }
},

当确认玩家输入的是数字后,我们就可以生成相应位数的数字,并执行滚动效果。

数字的位数可以直接通过numStr的长度来判断,有多少位我们就生成多少个预制:

// Roll.js
okBtn () {
    // 首先获取数字(字符串)
    let numStr = this.getNumStr();
    
    // 再判断是否可以转换为数字
    let num = Number(numStr);
    if (!isNaN(num)) {
        // 根据numStr长度生成相应数量的预制
        for(let i=0; i<numStr.length; i++) {
            // 将生成的预制放入数组中
            this.prefabArray.push(this.getNewPrefab());
        }
    }
    else {
        console.log('非数字!');
    }
},

我们注意到每个通过getNewPrefab()生成的预制都被放到了prefabArray数组中。其实该数组变量的作用就是为了更好地管理各个预制(比如后期删除)。在这里我们还可以通过该数组控制数字上的各个位数——数组的第一个元素就是数字的最高位。

生成预制的getNewPrefab方法实现如下:

// Roll.js
getNewPrefab () {
    // 生成预制
    let numLayout = null;
    // 根据节点池大小判断是从预制池中获取还是新生成一个
    if (this.prefabPool.size() > 0) 
        numLayout = this.prefabPool.get();
    else 
        numLayout = cc.instantiate(this.numLayoutPrefab);
    // 添加到总布局中
    this.allLayoutNode.addChild(numLayout);
    return numLayout;
},

预制生成后就是执行滚动效果了:

// Roll.js
okBtn () {
    ...

    if (!isNaN(num)) {
        // 根据numStr长度生成相应数量的预制
        for(let i=0; i<numStr.length; i++) {
            // 将生成的预制放入数组中
            this.prefabArray.push(this.getNewPrefab());
        }

        // 执行滚动效果
        for(let i=0; i<numStr.length; i++) {
            this.roll(numStr[i], this.prefabArray[i])
        }
    }
    else {
        console.log('非数字!');
    }
},

roll方法实现如下:

// Roll.js
roll (num, prefab) {
    // 关键是获取y坐标
    let y = null;

    if (num != '.') 
        y = (Number(num)-5)*this.eachHeight;
    else 
        y = (10-5)*this.eachHeight;

    let moveTo = cc.moveTo(this.rollTime, cc.v2(0, y)).easing(cc.easeCubicActionOut());
    prefab.runAction(moveTo);
}

该方法有两个参数,一个是num,一个是 prefab。前者就是要显示的数字或"."符号,后者即相应位数上的number_layout预制。

我们首先判断num值,如果不是"."符号的话,那我们将调用Number()将该字符转为数字,减去5(5的y坐标为0),再乘以每个数字的高度;是"."符号的话就用直接用10减去5再乘以数字高度("."符号排在最后个)。这样我们就得出了目标点的y坐标,接着将number_layout移到相应位置就可以了。

最后我们还要对okBtn()进行完善。每次点击ok按钮后,我们应当对之前生成的各个预制进行回收:

// Roll.js
okBtn () {
    // 恢复坐标,回收预制,清空数组
    for(let i=0; i<this.prefabArray.length; i++) {
        this.prefabArray[i].setPosition(0, 0);
        this.prefabPool.put(this.prefabArray[i]);
    }
    this.prefabArray = [];

    ...
},

注意要将prefabArray数组清空,各个预制回收前也要恢复坐标(可以自行考虑下为什么)。

现在将Roll.js脚本挂到Canvas节点上,拖入相应节点,然后就可以运行项目啦:

那本期教程就到这,希望大家有所收获!

欢迎关注我的微信公众号,发现更多有趣内容:

发布了83 篇原创文章 · 获赞 157 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/La_vie_est_belle/article/details/103639182