cocos2d-js 越來越慢的定時器schedule 制作不變慢的定時器


對於動畫控制,可能一點誤差,大家不會察覺,但如果多次循環累積或網絡同步等,大家就會很清楚意識到schedule的誤差問題。

 

首先做一個例子證明一下:

var InaccuracyTestLayer = cc.Layer.extend({

    ctor: function () {
        this._super();
        var startTime = new Date().getTime();
        var count = 0;
        this.schedule(function(){
            var timePass = new Date().getTime() - startTime;
            count++;
            var delta = timePass - (count*100);
            trace("time pass", timePass, "total delta", delta, "count", count);
        }, 0.1);

        this.scheduleUpdate();
    },

    update: function () {
        for (var i = 0; i < 100000; i++) {
            b = 1/0.22222;
        }
    }
});

 

幀頻越低,變慢得越快。

time pass, 1481, total delta, 381, count, 11 CCDebugger.js:334
time pass, 1608, total delta, 408, count, 12 CCDebugger.js:334
time pass, 1735, total delta, 435, count, 13 CCDebugger.js:334
time pass, 1861, total delta, 461, count, 14 CCDebugger.js:334

 

那么嘗試一下解決問題?

定時器原理:cocos2d-js底層在每一幀計算中,遍歷所有定時器,看是否達到觸發時間。如果達到則觸發該定時器,並把時間重置為當前時間。好了,問題就在於此,“重置為當前時間”。

 

看看一個新的定時器:

    schedule2: function (callback, interval) {
        var then = Date.now();
        interval = interval*1000;
        this.schedule(function(){
            var now = Date.now();
            var delta = now - then;
            if(delta > interval){
                then = now - (delta % interval);
                callback.call(this);
            }
        }.bind(this), 0);
    }

這里核心是then=now-(delta%interval),每一次觸發的時候,把誤差算到下次觸發的控制中。

例如60fps,那么schedule2每16ms觸發一次,用戶設定了100ms的interval,那么將有16*7=112>100,7幀才觸發1次用戶的定時器。這里累積了12ms誤差,把12ms算到then中。

那么下次將有12+16*6=108>100,只需要96ms就觸發第2次用戶的定時器,這次提前了4ms,彌補了第1次的誤差。

 

這個定時器經得起考驗,即使在低幀頻情況下,仍然保持穩定。

var BetterScheduleLayer = cc.Layer.extend({

    ctor: function () {
        this._super();

        var startTime = Date.now();
        var count = 0;
        this.schedule2(function(){
            var timePass = Date.now() - startTime;
            count++;
            var delta = timePass - (count*100);
            trace("time pass", timePass, "total delta", delta, "count", count);
        }, 0.1);
        this.scheduleUpdate();
    },

    schedule2: function (callback, interval) {
        var then = Date.now();
        interval = interval*1000;
        this.schedule(function(){
            var now = Date.now();
            var delta = now - then;
            if(delta > interval){
                then = now - (delta % interval);
                callback.call(this);
            }
        }.bind(this), 0);
    },

    update: function () {
        for (var i = 0; i < 10000000; i++) {
            b = 1/0.22222;
        }
    }
});

輸出:

time pass, 3447, total delta, 47, count, 34 CCDebugger.js:334
time pass, 3510, total delta, 10, count, 35 CCDebugger.js:334
time pass, 3637, total delta, 37, count, 36 CCDebugger.js:334
time pass, 3701, total delta, 1, count, 37 CCDebugger.js:334
time pass, 3828, total delta, 28, count, 38 CCDebugger.js:334
time pass, 3955, total delta, 55, count, 39 CCDebugger.js:334

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM