JavaScript實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲
更新時(shí)間:2021年09月14日 10:38:45 作者:山與小島
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
本文實(shí)例為大家分享了canvas ,js 實(shí)現(xiàn)一個(gè)簡單的飛機(jī)大戰(zhàn),供大家參考,具體內(nèi)容如下
預(yù)覽圖:
代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> canvas { display: block; margin: 0 auto; border: 1px solid #000; } </style> </head> <body> <canvas></canvas> <script> // 獲取 canvas元素 var canvas = document.getElementsByTagName('canvas')[0]; // 獲取畫筆 var ctx = canvas.getContext('2d'); // 畫布信息 var canvasParam = { width: 480, height: 852 } canvas.width = canvasParam.width; canvas.height = canvasParam.height; // 初始化游戲狀態(tài) var ready = 0; // 準(zhǔn)備中 var loading = 1; // 載入中 var running = 2; // 游戲中 var pause = 3; // 暫停 var gameOver = 4; // 結(jié)束 // 判斷當(dāng)前游戲狀態(tài) var gameState = ready; // 初始化生命值 var life = 3; // 初始化游戲得分 var score = 0; // 背景 / // 創(chuàng)建背景圖片 var bgSrc = new Image(); bgSrc.src = 'img/background.png'; // 背景圖片信息 var bgParam = { bgSrc: bgSrc, x: 0, y: 0, width: 480, height: 852 } // 構(gòu)造函數(shù): 背景 function Bg(param) { this.bgSrc = param.bgSrc; this.x = param.x; this.y = param.y; this.y1 = param.y1; this.width = param.width; this.height = param.height; // 交替圖片的坐標(biāo) this.y1 = -this.height; // 繪制背景圖 this.paint = function() { ctx.drawImage(this.bgSrc, this.x, this.y, this.width, this.height); ctx.drawImage(this.bgSrc, this.x, this.y1, this.width, this.height); } // 背景圖片交替移動(dòng) this.sport = function() { this.y += 5; this.y1 += 5; if (this.y >= this.height) { this.y = -this.height; } if (this.y1 >= this.height) { this.y1 = -this.height; } } } // 實(shí)例化背景圖片 var bgObj = new Bg(bgParam); // 創(chuàng)建logo var logoSrc = new Image(); logoSrc.src = 'img/start.png'; // logo信息 var logoParam = { logoSrc: logoSrc, x: 0, y: 0, width: 480, height: 852 } // 構(gòu)造函數(shù) Logo function Logo(param) { this.logoSrc = param.logoSrc; this.x = param.x; this.y = param.y; this.width = param.width; this.height = param.height; // 繪制logo this.paint = function() { ctx.drawImage(this.logoObj, this.x, this.y, this.width, this.height); } } // 實(shí)例化logo對象 var logoObj = new Logo(logoParam); // 點(diǎn)擊畫布,進(jìn)入下一階段 loading canvas.onclick = function() { if (gameState === ready) { gameState = loading; } } // 游戲加載階段 loading // 飛機(jī)進(jìn)場 // 飛機(jī)進(jìn)場圖片 var loadImgArr = ['img/game_loading1.png', 'img/game_loading2.png', 'img/game_loading3.png', 'img/game_loading4.png'] // 一個(gè)空數(shù)組,用來存放飛機(jī)進(jìn)場的圖片 var loadingImg = []; // 循環(huán)創(chuàng)建飛機(jī)進(jìn)場圖片,將其存入數(shù)組loadingImg中 for (var i = 0; i < loadImgArr.length; i++) { loadingImg[i] = new Image(); loadingImg[i].src = loadImgArr[i]; } // 飛機(jī)進(jìn)場圖片信息 var loadingParam = { loadingImg: loadingImg, x: 0, width: 186, height: 38 } // 構(gòu)造函數(shù):飛機(jī)進(jìn)場信息 function Loading(param) { this.loadingImg = loadingImg; this.width = param.width; this.height = param.height; this.x = param.x; this.y = canvasParam.height - param.height; // 定義載入中圖片下標(biāo) this.index = 0; // 定義 num 判斷定時(shí)器的執(zhí)行次數(shù) this.num = 0; // 繪制載入中圖片 this.paint = function() { ctx.drawImage(this.loadingImg[this.index], this.x, this.y, this.width, this.height); } // 改變載入中圖片 this.sport = function() { this.num++; if (this.num % 5 == 0) { this.index++; if (this.index === this.loadingImg.length) { gameState = running; } } } } // 實(shí)例化 載入中飛機(jī)對象 var loadingObj = new Loading(loadingParam); // 我方飛機(jī) /// // 我方飛機(jī)各個(gè)狀態(tài)的圖片 var heroImgs = [ 'img/hero1.png', 'img/hero2.png', 'img/hero1.png', 'img/hero_blowup_n1.png', 'img/hero_blowup_n2.png', 'img/hero_blowup_n3.png', 'img/hero_blowup_n4.png' ] // 創(chuàng)建一個(gè)空數(shù)組,存放我方飛機(jī)各個(gè)狀態(tài)的圖片 var heroRunning = []; // 循環(huán)創(chuàng)建我方飛機(jī)圖片,存入數(shù)組heroRunning中 for (var i = 0; i < heroImgs.length; i++) { heroRunning[i] = new Image(); heroRunning[i].src = heroImgs[i]; } // 我方飛機(jī)信息 var heroParam = { haroRunning: heroRunning, width: 99, height: 124 } // 我方飛機(jī) 構(gòu)造函數(shù) function Hero(param) { this.heroRunning = heroRunning; this.x = canvasParam.width / 2 - param.width / 2; this.y = canvasParam.height - param.height * 1.2; this.width = param.width; this.height = param.height; // 我方飛機(jī)圖片下標(biāo) this.index = 0; // 判斷飛機(jī)是否被撞擊 this.down = false; // 間隔觸發(fā) this.num = 0; // 繪制我方飛機(jī) this.paint = function() { ctx.drawImage(this.heroRunning[this.index], this.x, this.y, this.width, this.height); } // 交替繪制我方飛機(jī)執(zhí)行時(shí)的圖片 this.sport = function() { if (!this.down) { this.num++; // 定時(shí)器每執(zhí)行3次,我方飛機(jī)飛行圖片交替一次 if (this.num % 3 === 0) { if (this.index === 0) { this.index = 1; } else { this.index = 0; } } } else { // 我方飛機(jī)被撞擊了 this.index++; // 圖片數(shù)組下標(biāo)+1,顯示被撞擊的圖片 if (this.index === this.heroRunning.length) { life--; // 生命值-1 if (life == 0) { // 游戲狀態(tài)變?yōu)?結(jié)束 gamerState = gameOver; // 游戲結(jié)束之后 讓飛機(jī)停留在冒煙狀態(tài) this.index = this.heroRunning.length - 1; } else { // 創(chuàng)建一個(gè)新的我方飛機(jī) heroObj = new Hero(heroParam); } } } } // 創(chuàng)建子彈間隔 this.bulletTime = 0; // 創(chuàng)建子彈 this.newBullet = function() { this.bulletTime++; // 定時(shí)器執(zhí)行3次,創(chuàng)建一個(gè)子彈 if (this.bulletTime % 2 === 0) { bullets.push(new Bullet(bulletParam)); } } } // 實(shí)例化 我方飛機(jī) var heroObj = new Hero(heroParam); // 給畫布綁定移動(dòng)事件我方飛機(jī)隨鼠標(biāo)移動(dòng) canvas.onmousemove = function(e) { if (gameState === running) { heroObj.x = e.offsetX - heroObj.width / 2; heroObj.y = e.offsetY - heroObj.height / 2; } } // 子彈 // var bulletImg = new Image(); bulletImg.src = 'img/bullet1.png'; var bulletParam = { bulletImg: bulletImg, width: 9, height: 21 } // 構(gòu)造函數(shù):子彈 function Bullet(param) { this.bulletImg = param.bulletImg; this.x = heroObj.x + heroObj.width / 2 - param.width / 2; this.y = heroObj.y - param.height; this.width = param.width; this.height = param.height; // 繪制子彈 this.paint = function() { ctx.drawImage(this.bulletImg, this.x, this.y, this.width, this.height); } // 判斷子彈是否碰到敵機(jī) this.down = false; // 子彈移動(dòng)速度 this.sport = function() { this.y -= 50; } } // 彈夾 var bullets = []; // 制造子彈 function bulletsPaint() { for (var i = 0; i < bullets.length; i++) { bullets[i].paint(); } } // 發(fā)射子彈 function bulletsSport() { for (var i = 0; i < bullets.length; i++) { bullets[i].sport(); } } // 子彈飛出屏幕外面 // 子彈與敵機(jī)碰撞 function bulletsDelete() { for (var i = 0; i < bullets.length; i++) { if (bullets[i].y < -this.height || bullets[i].down) { bullets.splice(i, 1); } } } // 敵方飛機(jī) // 小型敵機(jī) var enemy1Arr = [ 'img/enemy1.png', 'img/enemy1_down1.png', 'img/enemy1_down2.png', 'img/enemy1_down3.png', 'img/enemy1_down4.png' ]; var enemy1Img = []; for (var i = 0; i < enemy1Arr.length; i++) { enemy1Img[i] = new Image(); enemy1Img[i].src = enemy1Arr[i]; } // 中型敵機(jī) var enemy2Arr = [ 'img/enemy2.png', 'img/enemy2_down1.png', 'img/enemy2_down2.png', 'img/enemy2_down3.png', 'img/enemy2_down4.png' ]; var enemy2Img = []; for (var i = 0; i < enemy2Arr.length; i++) { enemy2Img[i] = new Image(); enemy2Img[i].src = enemy2Arr[i]; } // 大型敵機(jī) var enemy3Arr = [ 'img/enemy3_n1.png', 'img/enemy3_n2.png', 'img/enemy3_hit.png', 'img/enemy3_down1.png', 'img/enemy3_down2.png', 'img/enemy3_down3.png', 'img/enemy3_down4.png', 'img/enemy3_down5.png', 'img/enemy3_down6.png' ]; var enemy3Img = []; for (var i = 0; i < enemy3Arr.length; i++) { enemy3Img[i] = new Image(); enemy3Img[i].src = enemy3Arr[i]; } // 小型敵機(jī)信息 var enemy1Param = { enemyImg: enemy1Img, width: 57, height: 51, life: 3, score: 1 } // 中型敵機(jī)信息 var enemy2Param = { enemyImg: enemy2Img, width: 69, height: 95, life: 10, score: 3 } // 大型敵機(jī)信息 var enemy3Param = { enemyImg: enemy3Img, width: 169, height: 258, life: 20, score: 10 } // 構(gòu)造函數(shù):敵機(jī) function Enemy(param) { this.enemyImg = param.enemyImg; this.width = param.width; this.height = param.height; this.life = param.life; this.score = param.score; this.x = Math.random() * (canvasParam.width - this.width); this.y = -this.height; // 圖片下標(biāo) this.index = 0; // 判斷敵機(jī)是否發(fā)生碰撞 this.down = false; // 是否完成爆炸 this.bang = false; // 繪制敵機(jī) this.paint = function() { ctx.drawImage(this.enemyImg[this.index], this.x, this.y, this.width, this.height); } // 敵機(jī)移動(dòng) this.sport = function() { if (!this.down) { // 當(dāng)前敵機(jī)未被碰撞時(shí) this.y += 3; } else { // 敵機(jī)碰后生命值-1 this.life--; // 生命值-1后,碰撞變?yōu)閒alse this.down = false; // 生命值變?yōu)?時(shí),變?yōu)閿硻C(jī)爆炸圖片 if (this.life <= 0) { this.index++; this.down = true; if (this.index === this.enemyImg.length) { this.index = this.enemyImg.length - 1; this.bang = true; } } } } // 判斷是否被碰撞 this.hit = function(obj) { return obj.x + obj.width >= this.x && obj.x <= this.x + this.width && obj.y <= this.y + this.height && obj.y + obj.height >= this.y; } } // 創(chuàng)建一個(gè)空數(shù)組,存放敵機(jī) var enemies = []; // 隨機(jī)創(chuàng)建小型、中型、大型敵機(jī) function pushEnemy() { var random = Math.random(); if (random < 0.65) { enemies.push(new Enemy(enemy1Param)); } else if (random < 0.9) { // 中號飛機(jī) enemies.push(new Enemy(enemy2Param)); } else { // 大號飛機(jī) enemies.push(new Enemy(enemy3Param)); } } // 繪制、運(yùn)動(dòng)敵機(jī)對象 function enemyPaint() { for (var i = 0; i < enemies.length; i++) { enemies[i].paint(); enemies[i].sport(); } } // 繪制暫停時(shí)的敵機(jī) function enemyPaint1() { for (var i = 0; i < enemies.length; i++) { enemies[i].paint(); } } // 刪除敵機(jī) 和增加分?jǐn)?shù) function enemyDelete() { for (var i = 0; i < enemies.length; i++) { if (enemies[i].bang) { score += enemies[i].score; } if (enemies[i].y >= canvasParam.height || enemies[i].bang) { enemies.splice(i, 1); // score += enemies[i].score; } } } // 如何檢測每一個(gè)敵機(jī)是否被 子彈或我方飛機(jī) 碰撞 function checkHit() { for (var i = 0; i < enemies.length; i++) { // 子彈和敵機(jī)撞擊 for (var j = 0; j < bullets.length; j++) { if (enemies[i].hit(bullets[j])) { enemies[i].down = true; bullets[j].down = true; } } // 敵機(jī)和hero if (enemies[i].hit(heroObj)) { enemies[i].down = true; heroObj.down = true; } } } // 分?jǐn)?shù) function scoreText() { ctx.font = '20px bold'; ctx.fillText('得分: ' + score, 20, 30); ctx.fillText('生命值:' + life, 360, 30) } // 鼠標(biāo)移出游戲暫停 canvas.onmouseout = function() { if (gameState === running) { gameState = pause; } }; // 鼠標(biāo)移入游戲開始 canvas.onmouseover = function() { if (gameState === pause) { gameState = running; } }; // 游戲暫停界面 function pausePanit() { var pauseImg = new Image() pauseImg.src = "img/game_pause_nor.png"; heroObj.paint(); // 繪制子彈 bulletsPaint(); // 繪制敵機(jī) enemyPaint1(); scoreText(); ctx.drawImage(pauseImg, 220, 420); } // 游戲結(jié)束 function gameOverText() { ctx.font = '50px bold'; ctx.fillText('game over', 120, 420); ctx.font = '30px bold'; ctx.fillText('點(diǎn)擊重新開始', 160, 520); } // 點(diǎn)擊事件,重新開始游戲 canvas.addEventListener("click", function(e) { if (gameState === gameOver) { gameState = ready; loadingObj.num = 0; loadingObj.index = 0; enemies = []; bullets = []; life = 3; score = 0; heroObj.down = false; } }); // 創(chuàng)建敵機(jī)的時(shí)間間隔 var enemyNum = 0; // 開啟定時(shí)器, 繪制圖片 setInterval(function() { bgObj.paint(); bgObj.sport(); if (gameState === ready) { ctx.drawImage(logoSrc, 0, 0, 480, 852); // logoObj.paint(); } else if (gameState === loading) { loadingObj.paint(); loadingObj.sport(); } else if (gameState === running) { canvas.style.cursor = 'none'; heroObj.paint(); heroObj.sport(); heroObj.newBullet(); // 繪制子彈 bulletsPaint(); bulletsSport(); // 刪除子彈 bulletsDelete(); // 繪制敵機(jī) enemyNum++; if (enemyNum % 20 === 0) { pushEnemy(); } enemyPaint(); checkHit(); enemyDelete(); scoreText(); if (life === 0) { gameState = gameOver; } } else if (gameState === pause) { pausePanit(); } else if (gameState === gameOver) { canvas.style.cursor = 'pointer'; gameOverText(); heroObj.paint(); } }, 60) </script> </body> </html>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實(shí)現(xiàn)簡單Tip提示框效果
這篇文章主要介紹了JavaScript實(shí)現(xiàn)簡單Tip提示框效果,涉及JavaScript響應(yīng)鼠標(biāo)事件針對頁面元素動(dòng)態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2016-04-04JavaScript async&await方法中的異常處理方案
在 async/await 方法中,可以使用 try-catch 塊來處理異常,通過使用 try-catch,可以捕獲異步操作中拋出的異常,并在 catch 塊中進(jìn)行適當(dāng)?shù)奶幚?本文給大家詳細(xì)介紹了async&await方法中異常如何處理,需要的朋友可以參考下2023-08-08JavaScript canvas實(shí)現(xiàn)代碼雨效果
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)代碼雨效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06js判斷瀏覽器的環(huán)境(pc端,移動(dòng)端,還是微信瀏覽器)
這篇文章主要介紹了js判斷瀏覽器的環(huán)境(pc端,移動(dòng)端,還是微信瀏覽器),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01深入JS函數(shù)中默認(rèn)參數(shù)的使用詳解
本文主要介紹了深入JS函數(shù)中默認(rèn)參數(shù)的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07