超级玛丽HTML5源代码学习------(四)
首先我們需要知道
每一個游戲都是由:
A:獲得用戶輸入
B:更新游戲狀態
C:處理AI
D:播放音樂和音效
E:畫面顯示
這些行為組成。游戲主循環就是用來處理這個行為序列,在javascript中可以用setInterval方法來輪詢。在超級瑪麗中是這個循環
//主循環var mainLoop=setInterval(function(){//距上一次執行相隔的時間.(時間變化量), 目前可近似看作sleep.var deltaTime=sleep;// 更新Animation狀態animation.update(deltaTime);//使用背景覆蓋的方式 清空之前繪制的圖片context.drawImage(ImgCache["bg"],0,0);//繪制Animationanimation.draw(context, x,y);},sleep);
如何去做到讓游戲角色進行移動呢?今天這里只學習讓玩家在原地進行移動,也就是step3_1
實現人物移動的方法就是:將精靈圖片的不同動作圖片,在畫布上同一位置交替顯示,就形成了人物原地移動的動畫。在畫布的不同的位置顯示動作圖片,就形成了人物在畫布上來回移動的動畫。
首先實現炸彈人在畫布上原地移動,顯示移動動畫;
了解精靈圖片含義:所謂精靈圖片就是包含多張小圖片的一張大圖片,使用它可以減少http請求,提升性能。
第一步:實現人物的顯示
首先,要顯示玩家角色。需要創建畫布并獲得上下文,加載緩存圖像,調用StartDemo,然后是清空畫布區域,使用drawImage來繪制圖片。
// 頁面初始化函數 function init(){// 創建canvas,并初始化 (我們也可以直接以標簽形式寫在頁面中,然后通過id等方式取得canvas)canvas=document.createElement("canvas");canvas.width=600;canvas.height=400;document.body.appendChild(canvas);// 取得2d繪圖上下文 context= canvas.getContext("2d");//加載圖片,并存入全局變量 ImgCache, // 加載完成后,調用startDemoImgCache=loadImage( [ { id : "player",url : "../res/player.png"},{ id : "bg",url : "../res/bg.png"}], startDemo );}
第二步:游戲的幀數FPS=30 ? ?
每秒所運行的幀數。游戲主循環每33.3(1000/30)ms輪詢一次
FPS決定游戲畫面更新的頻率,決定主循環的快慢。
主循環中的間隔時間sleep與FPS有一個換算公式:
間隔時間 = 就近最大取整(1000 / FPS),不同于四舍五入,也叫向下取整
// 一些簡單的初始化, var FPS=30;var sleep=Math.floor(1000/FPS);//初始坐標var x=0, y=284;第三步:使用幀動畫
一些基本要理解的知識:
動畫是通過繪制一組幀圖片來實現的。具體實現時有這些關鍵問題:
- 一組幀應該以怎樣的順序來繪制?
- 如何控制每一幀繪制的時間?
- 在畫布的什么位置繪制幀?
- 如何控制繪制的幀的內容、圖片大小?
策略:幀動畫控制類Animation // Animation類.動畫類 // cfg為Object類型的參數集, 其屬性會覆蓋Animation原型中定義的同名屬性. function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];} }Animation.prototype={constructor :Animation ,// Animation 包含的Frame, 類型:數組frames : null,// 包含的Frame數目frameCount : -1 ,// 所使用的圖片id(在ImgCache中存放的Key), 字符串類型. img : null,// 當前播放的 framecurrentFrame : null ,// 當前播放的幀currentFrameIndex : -1 ,// 已經播放的時間currentFramePlayed : -1 ,// 初始化Animationinit : function(){// 根據id取得Image對象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省從第0幀播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},// 更新Animation狀態. deltaTime表示時間的變化量.update : function(deltaTime){//判斷當前Frame是否已經播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一幀if (this.currentFrameIndex >= this.frameCount-1){//當前是最后一幀,則播放第0幀this.currentFrameIndex=0;}else{//播放下一幀this.currentFrameIndex++;}//設置當前幀信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加當前幀的已播放時間.this.currentFramePlayed += deltaTime;}},//繪制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );} };
Animation負責讀取、配置、更新幀數據,控制幀數據的播放
讀取:
創建一個Animation對象:
// 創建一個Animation對象var animation = new Animation({img : "player" ,//該動畫由3幀構成,對應圖片中的第一行.frames : [{x : 0, y : 0, w : 50, h : 60, duration : 100},{x : 50, y : 0, w : 50, h : 60, duration : 100},{x : 100, y : 0, w : 50, h : 60, duration : 100}]} );
function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];} }
// Animation類.動畫類
// cfg為Object類型的參數集, 其屬性會覆蓋Animation原型中定義的同名屬性.
配置:
初始化Animation對象:
// 初始化Animationanimation.init();
初始化函數代碼:
// 初始化Animationinit : function(){// 根據id取得Image對象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省從第0幀播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},
更新幀數據:
// 更新Animation狀態animation.update(deltaTime);
更新函數代碼:
// 更新Animation狀態. deltaTime表示時間的變化量.update : function(deltaTime){//判斷當前Frame是否已經播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一幀if (this.currentFrameIndex >= this.frameCount-1){//當前是最后一幀,則播放第0幀this.currentFrameIndex=0;}else{//播放下一幀this.currentFrameIndex++;}//設置當前幀信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加當前幀的已播放時間.this.currentFramePlayed += deltaTime;}},
播放:
就是繪制幀動畫:
//繪制Animationanimation.draw(context, x,y); //繪制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}
再來看幀動畫播放需要掌握的那些知識點:
1.一組幀應該以怎樣的順序進行播放
// 缺省從第0幀播放this.currentFrameIndex=0;
2.如何控制每一幀的繪制時間:
當 當前幀 播放沒有完成的時候:
//增加當前幀的已播放時間.this.currentFramePlayed += deltaTime;當 當前幀 播放完成的時候:this.currentFramePlayed=0;
3.在畫布的什么位置開始繪制:
//繪制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}
4.如何控制繪制的幀的內容、圖片大小:
幀內容:首先是一個數組 frames[],其次是當前播放的幀?currentFrame : null ,
初始化時控制操作:
this.currentFrame=this.frames[this.currentFrameIndex];
currentFrameIndex : -1 ,可以看作是一個索引
更新的時候:
//設置當前幀信息this.currentFrame=this.frames[ this.currentFrameIndex ];
最后提供源代碼:
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="-1" /> <meta http-equiv="Cache-Control" content="no-cache" /><title>My first Game</title><style type="text/css"> body {border:none 0px;margin:0px;padding:10px;font-size : 16px;background-color : #f3f3f3; }canvas {border : 1px solid blue; } </style><script type="text/javascript">// 加載圖片 function loadImage(srcList,callback){var imgs={};var totalCount=srcList.length;var loadedCount=0;for (var i=0;i<totalCount;i++){var img=srcList[i];var image=imgs[img.id]=new Image(); image.src=img.url;image.οnlοad=function(event){loadedCount++;} }if (typeof callback=="function"){var Me=this;function check(){if (loadedCount>=totalCount){callback.apply(Me,arguments);}else{ setTimeout(check,100);} }check();}return imgs; }//定義全局對象 var ImgCache=null; var canvas=null; var context=null;// 頁面初始化函數 function init(){// 創建canvas,并初始化 (我們也可以直接以標簽形式寫在頁面中,然后通過id等方式取得canvas)canvas=document.createElement("canvas");canvas.width=600;canvas.height=400;document.body.appendChild(canvas);// 取得2d繪圖上下文 context= canvas.getContext("2d");//加載圖片,并存入全局變量 ImgCache, // 加載完成后,調用startDemoImgCache=loadImage( [ { id : "player",url : "../res/player.png"},{ id : "bg",url : "../res/bg.png"}], startDemo );}// Animation類.動畫類 // cfg為Object類型的參數集, 其屬性會覆蓋Animation原型中定義的同名屬性. function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];} }Animation.prototype={constructor :Animation ,// Animation 包含的Frame, 類型:數組frames : null,// 包含的Frame數目frameCount : -1 ,// 所使用的圖片id(在ImgCache中存放的Key), 字符串類型. img : null,// 當前播放的 framecurrentFrame : null ,// 當前播放的幀currentFrameIndex : -1 ,// 已經播放的時間currentFramePlayed : -1 ,// 初始化Animationinit : function(){// 根據id取得Image對象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省從第0幀播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},// 更新Animation狀態. deltaTime表示時間的變化量.update : function(deltaTime){//判斷當前Frame是否已經播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一幀if (this.currentFrameIndex >= this.frameCount-1){//當前是最后一幀,則播放第0幀this.currentFrameIndex=0;}else{//播放下一幀this.currentFrameIndex++;}//設置當前幀信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加當前幀的已播放時間.this.currentFramePlayed += deltaTime;}},//繪制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );} };// Demo的啟動函數 function startDemo(){// 一些簡單的初始化, var FPS=30;var sleep=Math.floor(1000/FPS);//初始坐標var x=0, y=284;// 創建一個Animation對象var animation = new Animation({img : "player" ,//該動畫由3幀構成,對應圖片中的第一行.frames : [{x : 0, y : 0, w : 50, h : 60, duration : 100},{x : 50, y : 0, w : 50, h : 60, duration : 100},{x : 100, y : 0, w : 50, h : 60, duration : 100}]} );// 初始化Animationanimation.init();//主循環var mainLoop=setInterval(function(){//距上一次執行相隔的時間.(時間變化量), 目前可近似看作sleep.var deltaTime=sleep;// 更新Animation狀態animation.update(deltaTime);//使用背景覆蓋的方式 清空之前繪制的圖片context.drawImage(ImgCache["bg"],0,0);//繪制Animationanimation.draw(context, x,y);},sleep);}</script></head> <body οnlοad="init()"> <div align="center"><a href="http://www.linuxidc.com" target="_blank">www.Linuxidc.com</a></div> </body> </html>
總結
以上是生活随笔為你收集整理的超级玛丽HTML5源代码学习------(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「译」开发者如何提升和推销自己
- 下一篇: html5 自动矢量化,HTML5中地圖