由於整個遊戲都在一個遊戲循環中進行,所以遊戲循環可以說是遊戲的核心部分。 每次迴圈時,更新遊戲物件的屬性,以及繪製遊戲元素。
在先前的資源載入篇已經提到過,在資源載入完成後,啟動遊戲的同時會啟動一個遊戲循環,現在再來回顧這部分程式碼:
/** *图像加载完毕的处理程序 **/ 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; });
以上是HTML5遊戲框架cnGameJS開發實錄-遊戲循環篇的詳細內容。更多資訊請關注PHP中文網其他相關文章!