coco2d-x-html5之Director解析

上一讲我们讲了为什么调用了cc.game.run后,会执行cc.game.onStart函数。这一讲,我们通过分析一下 CCDirector.js的代码,来了解一下游戏是怎么渲染的。

上一讲中,我们看到,在cc.game.prepare方法里面,在加载引擎代之后,执行了 cc.game._setAnimFrame()和cc.game._runMainLoop()。
在这里插入图片描述

接下来我们看下这两个函数到底做了什么。

    //  @Time ticker section
    // 设置帧率
    _setAnimFrame: function () {
        // 预计下一帧执行后的时间
        this._lastTime = new Date();
        // 帧率
        var frameRate = cc.game.config[cc.game.CONFIG_KEY.frameRate];
        // 每帧的时间
        this._frameTime = 1000 / frameRate;
        // 如果帧率不是60或30的时候,使用window.setTimeout来控制执行频率
        if (frameRate !== 60 && frameRate !== 30) {
            window.requestAnimFrame = this._stTime;
            window.cancelAnimationFrame = this._ctTime;
        } else {
            // 60或者30帧的时候,使用默认的,30时通过 skip 跳过一帧的方式
            // 使用默认比setTimeout速度快
            // 疑问 不是30帧的时候,为什么不使用跳过的方式来实现?
            window.requestAnimFrame = window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                this._stTime;
            window.cancelAnimationFrame = window.cancelAnimationFrame ||
                window.cancelRequestAnimationFrame ||
                window.msCancelRequestAnimationFrame ||
                window.mozCancelRequestAnimationFrame ||
                window.oCancelRequestAnimationFrame ||
                window.webkitCancelRequestAnimationFrame ||
                window.msCancelAnimationFrame ||
                window.mozCancelAnimationFrame ||
                window.webkitCancelAnimationFrame ||
                window.oCancelAnimationFrame ||
                this._ctTime;
        }
    },
    
    // 定时函数
    _stTime: function (callback) {
        // 当前时间戳
        var currTime = new Date().getTime();
        // cc.game._fameTime 值为 1000 / 帧率 单位为毫秒
        // cc.game._lastTime 值为上次预计 执行到这里的时间戳

        // timeToCall下次执行callback间隔时间,正常时每帧的时间cc.game._frameTime
        // currTime-cc.game._lastTime 就是预计和实际时间的差值
        // 如果性能不好,currTime - cc.game._lastTime大于0,那下一帧的时间就要少一些
        var timeToCall = Math.max(0, cc.game._frameTime - (currTime - cc.game._lastTime));
        var id = window.setTimeout(function () {
                callback();
            },
            timeToCall);
        // 下一帧执行的预计时间,如果性能好的话,下次执行到_stTime函数时,这个值等你
        cc.game._lastTime = currTime + timeToCall;
        return id;
    }, 
    // 取消定时
    _ctTime: function (id) {
        window.clearTimeout(id);
    },

通过上面的代码我们可以看到,如果帧率为60或30的时候,使用window.requestAnimationFrame的方式来定时执行函数。其他值时,使用window.setTimeout来实现。其中使用window.setTimeout的时候,通过记录预计下次执行的时间 cc.game._lastTime的值,来动态计算下次执行 回调的时间。

接下来看下

    // 运行主循环
    _runMainLoop: function () {
        var self = this,
            callback, config = self.config,
            // projection.json的值
            CONFIG_KEY = self.CONFIG_KEY,
            // 导演
            director = cc.director,
            // 是否跳过渲染。帧率为30帧的时候 用
            skip = true,
            // 帧率
            frameRate = config[CONFIG_KEY.frameRate];

        // 设置FPS显示状态 为true的时候,左下角显示帧率等信息
        director.setDisplayStats(config[CONFIG_KEY.showFPS]);

        // 每帧回调的函数
        callback = function () {
            // 没有暂停的时候,继续执行
            if (!self._paused) {
                // 如果帧率是30
                if (frameRate === 30) {
                    // 因为 帧率是30和60的时候,调用的是window.requestAnimationFrame,默认是60帧 (原因见cc.game._setAnimFrame方法)
                    // 所以每隔一帧跳过不执行
                    if (skip = !skip) {
                        self._intervalId = window.requestAnimFrame(callback);
                        return;
                    }
                }
                // 每帧执行导演类的 主循环 
                director.mainLoop();
                self._intervalId = window.requestAnimFrame(callback);
            }
        };
        // 间隔id,可通过该值来取消要执行的函数
        self._intervalId = window.requestAnimFrame(callback);
        // 是否暂停
        self._paused = false;
    },

可以看出,在cc.game._runMainLoop里面,通过调用window.requestAnimFrame来实现循环执行callback。在callback里面调用director.mainLoop(),来实现每一帧的更新。

下一讲,我们将通过分析CCDirector.js这个类来了解整个游戏渲染的流程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值