PHP前端开发

HTML5游戏框架cnGameJS开发实录-游戏循环篇

百变鹏仔 2个月前 (10-18) #H5教程
文章标签 游戏

由于整个游戏都在一个游戏循环中进行,所以游戏循环可以说是游戏的核心部分。每次循环时,更新游戏对象的属性,以及绘制游戏元素。

在之前的资源加载篇已经提到过,在资源加载完成后,启动游戏的同时会启动一个游戏循环,现在再来回顾这部分代码:

/**     *图像加载完毕的处理程序    **/        var imgLoad=function(self){        return function(){            self.loadedCount+=1;            self.loadedImgs[this.srcPath]=this;            this.onLoad=null;                    //保证图片的onLoad执行一次后销毁            self.loadedPercent=Math.floor(self.loadedCount/self.sum*100);            self.onLoad&&self.onLoad(self.loadedPercent);            if(self.loadedPercent===100){                self.loadedCount=0;                self.loadedPercent=0;                loadingImgs={};                if(self.gameObj&&self.gameObj.initialize){                    self.gameObj.initialize();                    if(cg.loop&&!cg.loop.stop){//结束上一个循环                        cg.loop.end();                    }                    cg.loop=new cg.GameLoop(self.gameObj);//开始新游戏循环                    cg.loop.start();                }                            }                            }    }

图像资源加载完毕后,调用游戏对象的initialize方法,并且判断游戏循环对象是否存在,如果存在,则结束上一个循环(这种情况一般在切换关卡,传入新的游戏对象时出现),否则建立并开始游戏循环。

好了,现在正式来看看游戏循环的实现代码:

var gameLoop=function(gameObj,options){            if(!(this instanceof arguments.callee)){            return new arguments.callee(gameObj,options);        }        this.init(gameObj,options);        }

首先游戏循环函数也必须保证是以构造函数的形式调用,在调用之后,为对象初始化:

立即学习“前端免费学习笔记(深入)”;

/**         *初始化        **/        init:function(gameObj,options){            /**             *默认对象            **/                var defaultObj={                fps:30            };            options=options||{};                        options=cg.core.extend(defaultObj,options);            this.gameObj=gameObj;            this.fps=options.fps;            interval=1000/this.fps;                        this.pause=false;            this.stop=true;        },

用户需要设置的参数只有一个,就是fps(frame per second),该参数是每秒钟执行的帧的次数,根据该参数,我们可以计算出多少毫秒执行一次游戏循环(interval参数)。另外循环支持暂停和停止两种模式。

/**         *开始循环        **/            start:function(){            if(this.stop){        //如果是结束状态则可以开始                this.stop=false;                                this.now=new Date().getTime();                this.startTime=new Date().getTime();                this.duration=0;                    loop.call(this)();                }            },

当循环开始,我们可以保存开始的时间,这样就可以不断更新循环所经历的时间(duration)。之后调用loop这个似有函数,实现循环。

var timeId;    var interval;    /**    *循环方法    **/        var loop=function(){        var self=this;        return function(){            if(!self.pause&&!self.stop){                                self.now=new Date().getTime();                self.duration=self.startTime-self.now;                                if(self.gameObj.update){                    self.gameObj.update();                }                if(self.gameObj.draw){                    cg.context.clearRect(0,0,cg.width,cg.height);                    self.gameObj.draw();                }            }            timeId=window.setTimeout(arguments.callee,interval);        }    }

如果不是暂停或停止,则调用游戏对象的update和draw(注意游戏对象的update负责调用该关卡所有元素的update,draw也一样)。之后调用setTimeout递归调用自己,实现循环。

游戏循环所有源码:

/** * *游戏循环 ***/cnGame.register("cnGame",function(cg){    var timeId;    var interval;    /**    *循环方法    **/        var loop=function(){        var self=this;        return function(){            if(!self.pause&&!self.stop){                                self.now=new Date().getTime();                self.duration=self.startTime-self.now;                                if(self.gameObj.update){                    self.gameObj.update();                }                if(self.gameObj.draw){                    cg.context.clearRect(0,0,cg.width,cg.height);                    self.gameObj.draw();                }            }            timeId=window.setTimeout(arguments.callee,interval);        }    }        var gameLoop=function(gameObj,options){            if(!(this instanceof arguments.callee)){            return new arguments.callee(gameObj,options);        }        this.init(gameObj,options);        }    gameLoop.prototype={        /**         *初始化        **/        init:function(gameObj,options){            /**             *默认对象            **/                var defaultObj={                fps:30            };            options=options||{};                        options=cg.core.extend(defaultObj,options);            this.gameObj=gameObj;            this.fps=options.fps;            interval=1000/this.fps;                        this.pause=false;            this.stop=true;        },                    /**         *开始循环        **/            start:function(){            if(this.stop){        //如果是结束状态则可以开始                this.stop=false;                                this.now=new Date().getTime();                this.startTime=new Date().getTime();                this.duration=0;                    loop.call(this)();                }            },        /**         *继续循环        **/            run:function(){            this.pause=false;            },        /**         *暂停循环        **/            pause:function(){            this.pause=true;            },        /**         *停止循环        **/            end:function(){            this.stop=true;            window.clearTimeout(timeId);        }                    }    this.GameLoop=gameLoop;});