日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一個HTML5躲避游戲的實(shí)現(xiàn)

前段時間BrowserQuest激起了我對html5的樂趣,接下來記下一個小型html5躲避游戲的實(shí)現(xiàn)。

中山網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),中山網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為中山上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的中山做網(wǎng)站的公司定做!

先上圖

游戲很簡單,鍵盤控制人物上下左右移動,躲開怪物,時間越長越牛x。

主要是兩部分組成:一部分就是人物、地圖的結(jié)構(gòu)搭建,另一部分就是讓英雄、怪物相應(yīng)地動起來。

HTML5寫游戲和傳統(tǒng)的游戲思路完全一樣,同樣也是不停刷新屏幕,游戲?qū)嶋H上也就是圖片的適時擺放問題,HTML5無非就只用到了一個canvas(畫布)的性質(zhì)用來擺放圖片。

Step 1 做好準(zhǔn)備

新建一個html文件,命名為index.html,用作游戲的容器。代碼如下:

 
 
 
 
  1.    
  2.    
  3.    
  4. html5 game   
  5.    
  6.    
  7. html5 game

       
  8.    
  9.    
  10.  

ps:script的引用最好放在body里放在body會有問題。

再新建個文件,move.js

 
 
 
 
  1. var canvas = document.createElement("canvas"); //創(chuàng)建元素canvas,即我們要用的畫布   
  2. var ctx = canvas.getContext("2d");//說明我們要用的畫布是2d,因?yàn)閏anvas也有WebGL支持3d   
  3. canvas.width = 512;//設(shè)置畫布的長寬   
  4. canvas.height = 480;   
  5. document.body.appendChild(canvas);//前面基本信息都設(shè)置好了之后,將這個元素添加到body標(biāo)簽下。 

這樣畫布就算是搭建好了。

順帶在下面加幾個和圖片有關(guān)的函數(shù)。

 
 
 
 
  1. var bgReady = false;   
  2. var bgImage = new Image();   
  3. bgImage.src = "move/background.png";   
  4. bgImage.onload = function(){   
  5. bgReady = true;   
  6. }   
  7.     
  8. var heroReady = false;   
  9. var heroImage = new Image();   
  10. heroImage.src = "move/hero.png";   
  11. heroImage.onload = function(){   
  12. heroReady = true;   
  13. }   
  14.     
  15. var monsterReady = false;   
  16. var monsterImage = new Image();   
  17. monsterImage.src = "move/monster.png";   
  18. monsterImage.onload = function(){   
  19. monsterReady = true;   

這個游戲用了三張圖片,依次為背景、英雄、怪物。這段代碼很容易理解,為了不在圖片沒有加載完成的時候就draw圖片。

#p#

Step 2 定義原型

接下來定義一下英雄的原型。

 
 
 
 
  1. var hero = {   
  2. speed: 256,   
  3. x: canvas.width/2,   
  4. y: canvas.height/2   

這個原型也很好理解,每秒鐘英雄可以移動256個像素,英雄初始的位置為畫布中央(x,y分別為坐標(biāo))。

接下來輪到怪物了。: )

 
 
 
 
  1. function monster() {   
  2. this.x = Math.random() * canvas.width;//初始為止隨機(jī)   
  3. this.y = Math.random() * canvas.height;   
  4. this.speed = 100;   
  5. this.xDirection = 1;//默認(rèn)移動方向?yàn)閤軸正方向(以左上角為零點(diǎn),下方和右方為正)   
  6. this.yDirection = 1;//同樣也為y軸正方向   
  7. this.move = function (modifier) {//移動函數(shù)   
  8. this.x += this.xDirection * this.speed * modifier;   
  9. this.y += this.yDirection * this.speed * modifier;   
  10. if (this.x >= canvas.width - 32)//碰撞返回部分   
  11. {   
  12. this.x = canvas.width - 32;   
  13. this.xDirection = -1;   
  14. }else if (this.x <= 0)   
  15. {   
  16. this.x = 0;   
  17. this.xDirection = 1;   
  18. }else if (this.y >= canvas.height - 32)   
  19. {   
  20. this.y = canvas.height - 32;   
  21. this.yDirection = -1;   
  22. }else if (this.y <= 0)   
  23. {   
  24. this.y = 0;   
  25. this.yDirection = 1;   
  26. }   
  27. };   

怪物比英雄的定義要復(fù)雜得多。首先,怪物每隔五秒會增加一個(為增加難度),故不能單純創(chuàng)建一個數(shù)組,而是需要一個類,再用類創(chuàng)建怪物對象。js當(dāng)中只有類的半實(shí)現(xiàn),具體使用function來創(chuàng)建。然后,怪物需要有撞墻返回的性質(zhì)。

怪物的速度比英雄略慢,為100像素/秒。默認(rèn)坐標(biāo)在畫布當(dāng)中隨機(jī)。怪物以45度移動。xDirection,yDirection合起來表示左上、左下、右上、右下4個方向。然后monster這個類有個move的動作,modifier表示兩次刷新的時間間隔,可以計(jì)算出經(jīng)過時間間隔后怪物的坐標(biāo)。下面4個if函數(shù)用來判斷,是否超越邊界,超越則馬上轉(zhuǎn)向,以實(shí)現(xiàn)碰撞的效果。

 
 
 
 
  1. var monsterSum = 0;   
  2. var monsterList = new Array();   
  3. monsterList[monsterSum] = new monster(); 

前面用var已經(jīng)創(chuàng)建了英雄的實(shí)例,但是monster我們只建立了類而已,接下來要實(shí)例化。monsterSum表示怪物的數(shù)量,為方便,按照c的習(xí)慣,從0開始技術(shù),即0表示有一個怪物。monsterList用來表示一個存怪物對象的數(shù)組,然后順帶新建一個怪物。

#p#

Step 3 游戲動起來!

先添加一個事件來接收鍵盤的動作,上下左右用對應(yīng)的ascii碼。因?yàn)橛螒虿⒉皇寝粢幌路较蜴I,就移動一段距離。而是,判斷一個時間間隔內(nèi)的動作(最后的動作,中間有可能會變化,故用數(shù)組保存最后結(jié)果)。

 
 
 
 
  1. var keysDown = {};   
  2. addEventListener("keydown", function (e) {   
  3. keysDown[e.keyCode] = true;//如果有"keydown"這個動作,即摁下某鍵,就會存進(jìn)keysDown數(shù)組   
  4. }, false);   
  5. addEventListener("keyup", function (e) {   
  6. delete keysDown[e.keyCode];   
  7. }); 

下面上主函數(shù)

 
 
 
 
  1. var main = function () {   
  2. var now = Date.now();   
  3. var delta = now - then;   
  4. Move(delta / 1000);//每次間隔時間根本不是1ms,比1ms要大得多   
  5. Draw();   
  6. Check();   
  7. then = now;   

main函數(shù)就是主函數(shù),就是一個刷新所執(zhí)行的函數(shù)。now、then兩個變量記錄兩次刷新的時間間隔,這個時間間隔并不是固定的,一般為幾百毫秒。delta 是兩者之差,單位為毫秒。下面依次解釋各個函數(shù):Move()用來計(jì)算英雄和怪物的新位置。Draw()用來畫背景、人物、文字。Check()用來檢查,怪物和英雄是否相撞。

Move():

 
 
 
 
  1. var Move = function (modifier) {   
  2. if (38 in keysDown) {   
  3. hero.y -= hero.speed * modifier;   
  4. }   
  5. if (40 in keysDown) {   
  6. hero.y += hero.speed * modifier;   
  7. }   
  8. if (37 in keysDown) {   
  9. hero.x -= hero.speed * modifier;   
  10. }   
  11. if (39 in keysDown) {   
  12. hero.x += hero.speed * modifier;   
  13. }   
  14. if (hero.x >= canvas.width - 32) {   
  15. hero.x = 0;   
  16. }else if (hero.x <= 0) {   
  17. hero.x = canvas.width - 32;   
  18. }   
  19. if (hero.y >= canvas.height - 32) {   
  20. hero.y = 0;   
  21. }else if (hero.y <= 0) {   
  22. hero.y = canvas.height - 32;   
  23. }   
  24. for (var i = 0; i <= monsterSum; i++) {   
  25. monsterList[i].move(modifier);   
  26. }   

這里很好理解,判斷這段時間間隔英雄的動作。算出新位置后,判斷英雄是否跑出了畫布,跑出了就從另一頭出來(感謝 @昭曈 的創(chuàng)意)。接下來依次調(diào)用各個怪物的move函數(shù),計(jì)算他們的新位置。

Draw():

 
 
 
 
  1. var Draw = function () {   
  2. if (bgReady) {   
  3. ctx.drawImage(bgImage, 0 ,0);   
  4. }   
  5. if (heroReady) {   
  6. ctx.drawImage(heroImage, hero.x, hero.y);   
  7. }   
  8. if (monsterReady) {   
  9. for (var i = 0; i <= monsterSum; i++)   
  10. ctx.drawImage(monsterImage, monsterList[i].x, monsterList[i].y);   
  11. }   
  12. ctx.fillStyle = "rgb(250, 250, 250)";   
  13. ctx.font = "24px Helvetica";   
  14. ctx.textAlign = "left";   
  15. ctx.textBaseline = "top";   
  16. last = Date.now() - start;   
  17. ctx.fillText(last/1000, 32, canvas.height - 64);   

前三個函數(shù)類似,就是如果準(zhǔn)備好了圖片就畫東西上去(前面的三個ready函數(shù)派上了用場)。下面先定義了文字的style,然后計(jì)算出時間間隔last,然后畫上去。

Check():

 
 
 
 
  1. var Check = function () {   
  2. if (monsterSum != Math.floor(last / 5000)){//如果時間經(jīng)過5秒就增加一個怪獸實(shí)例   
  3. monsterSum ++;   
  4. monsterList[monsterSum] = new monster();   
  5. }   
  6. for (var i = 0; i <= monsterSum; i++) {   
  7. if (   
  8. (monsterList[i].x - 32) <= hero.x   
  9. && hero.x <= (monsterList[i].x + 32)   
  10. && (monsterList[i].y - 32) <= hero.y   
  11. && hero.y <= (monsterList[i].y + 32)   
  12. ) {   
  13. end = Date.now();   
  14. alert("你堅(jiān)持了" + (end - start)/1000 + "秒");   
  15. End();   
  16. }   
  17. }   

第一步是 如果經(jīng)過5秒就增加一個怪獸,然后下面一個個判斷怪獸與英雄是否接觸。(這里用的是矩形,@小樟 說可以用圓心,感興趣的可以試試: ) )

大家注意到了下面用到了一個end函數(shù)。下面補(bǔ)充,如果不停止一直刷新就瀏覽器就一直動了,故要有個結(jié)束函數(shù)。

End():

 
 
 
 
  1. var End = function () {   
  2. if (bgReady) {   
  3. ctx.drawImage(bgImage, 0 ,0); //留住背景   
  4. }   
  5. window.clearInterval(timer);   
  6. return;   

用到的clearInterval()稍后會說到。

#p#

Step 4 程序入口

 
 
 
 
  1. var then = Date.now();   
  2. var start = then;   
  3. timer = setInterval(main, 1); 

定義了初始的then和start,接下里用了setInterval(),意為每隔1ms就執(zhí)行一次main函數(shù)。1ms是虛指,就是立即執(zhí)行的意思。要想停止就用前面的clearInterval()函數(shù)。

到這里為止一個完整的游戲就寫好了~ : )

后來 @志謙 實(shí)踐出了一個bug,就是窗口如果最小化后,會一直計(jì)時,但不會被撞。問題在于高級的瀏覽器(當(dāng)然沒在說IE : ) ),默認(rèn)如果最小化后,會終止interval、timeout這類函數(shù)的執(zhí)行,以節(jié)約資源。但我們計(jì)時的方法是結(jié)束時間減去開始時間,所以就造成這個刷分的bug。感謝 @小樟 提供了main函數(shù)遞歸,全局變量表示是否停止的辦法。

哦,第一次就那么沒了~

源碼下載地址:html5game


網(wǎng)頁名稱:一個HTML5躲避游戲的實(shí)現(xiàn)
URL鏈接:http://www.dlmjj.cn/article/dhhddgp.html