《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 () {
    // 刪除節點
    this.allLayoutNode.removeAllChildren();
    
    // 恢復座標,回收預製,清空數組
    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節點上,拖入相應節點,然後就可以運行項目啦:

 

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

 

歡迎關注我的微信公衆號,發現更多有趣內容:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章