JavaScript實現(xiàn)飛機大戰(zhàn)游戲
更新時間:2021年09月14日 10:38:45 作者:山與小島
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)飛機大戰(zhàn)游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了canvas ,js 實現(xiàn)一個簡單的飛機大戰(zhàn),供大家參考,具體內(nèi)容如下
預覽圖:

代碼:
<!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; // 準備中
var loading = 1; // 載入中
var running = 2; // 游戲中
var pause = 3; // 暫停
var gameOver = 4; // 結(jié)束
// 判斷當前游戲狀態(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;
// 交替圖片的坐標
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);
}
// 背景圖片交替移動
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;
}
}
}
// 實例化背景圖片
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);
}
}
// 實例化logo對象
var logoObj = new Logo(logoParam);
// 點擊畫布,進入下一階段 loading
canvas.onclick = function() {
if (gameState === ready) {
gameState = loading;
}
}
// 游戲加載階段 loading
// 飛機進場
// 飛機進場圖片
var loadImgArr = ['img/game_loading1.png', 'img/game_loading2.png', 'img/game_loading3.png', 'img/game_loading4.png']
// 一個空數(shù)組,用來存放飛機進場的圖片
var loadingImg = [];
// 循環(huán)創(chuàng)建飛機進場圖片,將其存入數(shù)組loadingImg中
for (var i = 0; i < loadImgArr.length; i++) {
loadingImg[i] = new Image();
loadingImg[i].src = loadImgArr[i];
}
// 飛機進場圖片信息
var loadingParam = {
loadingImg: loadingImg,
x: 0,
width: 186,
height: 38
}
// 構(gòu)造函數(shù):飛機進場信息
function Loading(param) {
this.loadingImg = loadingImg;
this.width = param.width;
this.height = param.height;
this.x = param.x;
this.y = canvasParam.height - param.height;
// 定義載入中圖片下標
this.index = 0;
// 定義 num 判斷定時器的執(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;
}
}
}
}
// 實例化 載入中飛機對象
var loadingObj = new Loading(loadingParam);
// 我方飛機 ///
// 我方飛機各個狀態(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)建一個空數(shù)組,存放我方飛機各個狀態(tài)的圖片
var heroRunning = [];
// 循環(huán)創(chuàng)建我方飛機圖片,存入數(shù)組heroRunning中
for (var i = 0; i < heroImgs.length; i++) {
heroRunning[i] = new Image();
heroRunning[i].src = heroImgs[i];
}
// 我方飛機信息
var heroParam = {
haroRunning: heroRunning,
width: 99,
height: 124
}
// 我方飛機 構(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;
// 我方飛機圖片下標
this.index = 0;
// 判斷飛機是否被撞擊
this.down = false;
// 間隔觸發(fā)
this.num = 0;
// 繪制我方飛機
this.paint = function() {
ctx.drawImage(this.heroRunning[this.index], this.x, this.y, this.width, this.height);
}
// 交替繪制我方飛機執(zhí)行時的圖片
this.sport = function() {
if (!this.down) {
this.num++;
// 定時器每執(zhí)行3次,我方飛機飛行圖片交替一次
if (this.num % 3 === 0) {
if (this.index === 0) {
this.index = 1;
} else {
this.index = 0;
}
}
} else {
// 我方飛機被撞擊了
this.index++; // 圖片數(shù)組下標+1,顯示被撞擊的圖片
if (this.index === this.heroRunning.length) {
life--; // 生命值-1
if (life == 0) {
// 游戲狀態(tài)變?yōu)?結(jié)束
gamerState = gameOver;
// 游戲結(jié)束之后 讓飛機停留在冒煙狀態(tài)
this.index = this.heroRunning.length - 1;
} else {
// 創(chuàng)建一個新的我方飛機
heroObj = new Hero(heroParam);
}
}
}
}
// 創(chuàng)建子彈間隔
this.bulletTime = 0;
// 創(chuàng)建子彈
this.newBullet = function() {
this.bulletTime++;
// 定時器執(zhí)行3次,創(chuàng)建一個子彈
if (this.bulletTime % 2 === 0) {
bullets.push(new Bullet(bulletParam));
}
}
}
// 實例化 我方飛機
var heroObj = new Hero(heroParam);
// 給畫布綁定移動事件我方飛機隨鼠標移動
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);
}
// 判斷子彈是否碰到敵機
this.down = false;
// 子彈移動速度
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();
}
}
// 子彈飛出屏幕外面
// 子彈與敵機碰撞
function bulletsDelete() {
for (var i = 0; i < bullets.length; i++) {
if (bullets[i].y < -this.height || bullets[i].down) {
bullets.splice(i, 1);
}
}
}
// 敵方飛機
// 小型敵機
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];
}
// 中型敵機
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];
}
// 大型敵機
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];
}
// 小型敵機信息
var enemy1Param = {
enemyImg: enemy1Img,
width: 57,
height: 51,
life: 3,
score: 1
}
// 中型敵機信息
var enemy2Param = {
enemyImg: enemy2Img,
width: 69,
height: 95,
life: 10,
score: 3
}
// 大型敵機信息
var enemy3Param = {
enemyImg: enemy3Img,
width: 169,
height: 258,
life: 20,
score: 10
}
// 構(gòu)造函數(shù):敵機
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;
// 圖片下標
this.index = 0;
// 判斷敵機是否發(fā)生碰撞
this.down = false;
// 是否完成爆炸
this.bang = false;
// 繪制敵機
this.paint = function() {
ctx.drawImage(this.enemyImg[this.index], this.x, this.y, this.width, this.height);
}
// 敵機移動
this.sport = function() {
if (!this.down) {
// 當前敵機未被碰撞時
this.y += 3;
} else {
// 敵機碰后生命值-1
this.life--;
// 生命值-1后,碰撞變?yōu)閒alse
this.down = false;
// 生命值變?yōu)?時,變?yōu)閿硻C爆炸圖片
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)建一個空數(shù)組,存放敵機
var enemies = [];
// 隨機創(chuàng)建小型、中型、大型敵機
function pushEnemy() {
var random = Math.random();
if (random < 0.65) {
enemies.push(new Enemy(enemy1Param));
} else if (random < 0.9) {
// 中號飛機
enemies.push(new Enemy(enemy2Param));
} else {
// 大號飛機
enemies.push(new Enemy(enemy3Param));
}
}
// 繪制、運動敵機對象
function enemyPaint() {
for (var i = 0; i < enemies.length; i++) {
enemies[i].paint();
enemies[i].sport();
}
}
// 繪制暫停時的敵機
function enemyPaint1() {
for (var i = 0; i < enemies.length; i++) {
enemies[i].paint();
}
}
// 刪除敵機 和增加分數(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;
}
}
}
// 如何檢測每一個敵機是否被 子彈或我方飛機 碰撞
function checkHit() {
for (var i = 0; i < enemies.length; i++) {
// 子彈和敵機撞擊
for (var j = 0; j < bullets.length; j++) {
if (enemies[i].hit(bullets[j])) {
enemies[i].down = true;
bullets[j].down = true;
}
}
// 敵機和hero
if (enemies[i].hit(heroObj)) {
enemies[i].down = true;
heroObj.down = true;
}
}
}
// 分數(shù)
function scoreText() {
ctx.font = '20px bold';
ctx.fillText('得分: ' + score, 20, 30);
ctx.fillText('生命值:' + life, 360, 30)
}
// 鼠標移出游戲暫停
canvas.onmouseout = function() {
if (gameState === running) {
gameState = pause;
}
};
// 鼠標移入游戲開始
canvas.onmouseover = function() {
if (gameState === pause) {
gameState = running;
}
};
// 游戲暫停界面
function pausePanit() {
var pauseImg = new Image()
pauseImg.src = "img/game_pause_nor.png";
heroObj.paint();
// 繪制子彈
bulletsPaint();
// 繪制敵機
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('點擊重新開始', 160, 520);
}
// 點擊事件,重新開始游戲
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)建敵機的時間間隔
var enemyNum = 0;
// 開啟定時器, 繪制圖片
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();
// 繪制敵機
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)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
利用weixin-java-miniapp生成小程序碼并直接返回圖片文件流的方法
這篇文章主要介紹了利用weixin-java-miniapp生成小程序碼并直接返回圖片文件流的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-03-03
使用TypeScript實現(xiàn)一個類型安全的EventBus示例詳解
EventBus是工作中常用的工具,本文用Typescript實現(xiàn)一個具備基礎功能且類型安全的EventBus,是我近期學習Typescript的知識總結(jié),對TypeScript實現(xiàn)EventBus相關知識感興趣的朋友一起看看吧2022-06-06
JS switch判斷 三目運算 while 及 屬性操作代碼
這篇文章主要介紹了JS switch判斷 三目運算 while 及 屬性操作代碼,需要的朋友可以參考下2017-09-09

