用JS實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲
本文實(shí)例為大家分享了JS實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的具體代碼,供大家參考,具體內(nèi)容如下
小的時(shí)候玩的飛機(jī)大戰(zhàn)感覺還蠻神奇,今天自己就學(xué)著做了一個(gè)
先制作好要做好的幾步以及背景樣式
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var start = 0; // 開始階段
var starting = 1; // 開始的加載階段
var running = 2; // 游戲階段
var pause = 3; // 暫停階段
var gameover = 4; // 結(jié)束階段
var state = start; // 目前狀態(tài)
var width = canvas.width; // 獲取畫布的寬度
var height = canvas.height; // 獲取畫布的高度
var score = 0; // 分?jǐn)?shù)
var life = 3; // 我放飛機(jī)生命值
var bg = new Image(); // 創(chuàng)建背景圖片
bg.src = "img/background.png";
var BG = {
imgs: bg,
width: 480,
height: 852,
};
// 創(chuàng)建生成背景圖片的構(gòu)造函數(shù)
function Bg(config) { // 參數(shù)為BG對(duì)象
this.imgs = config.imgs;
this.width = config.width;
this.height = config.height;
// 定義兩張背景圖片,用于動(dòng)畫
this.x1 = 0;
this.y1 = 0;
this.x2 = 0;
//第二張背景圖的初始高度放在背景高度(固定)的上面
this.y2 = -this.height;
// 背景圖片繪制方法
this.paint = function() {
//分別繪制了兩張背景圖
ctx.drawImage(this.imgs, this.x1, this.y1);
ctx.drawImage(this.imgs, this.x2, this.y2);
};
// 背景圖片運(yùn)動(dòng)的方法
this.step = function() {
//背景圖片位置向下移動(dòng)一個(gè),然后利用定時(shí)器讓背景圖動(dòng)起來
this.y1++;
this.y2++;
//判斷圖片高度的臨界點(diǎn),
if (this.y1 == this.height) {
this.y1 = -this.height;
}
if (this.y2 == this.height) {
this.y2 = -this.height;
}
}
};
// 創(chuàng)建背景圖片對(duì)象
var sky = new Bg(BG);
// 生成游戲名文字
var logo = new Image();
logo.src = "img/start.png";
// 游戲加載過程的4張圖片存入一個(gè)數(shù)組中
var loadings = [];
loadings[0] = new Image();
loadings[0].src = "img/game_loading1.png";
loadings[1] = new Image();
loadings[1].src = "img/game_loading2.png";
loadings[2] = new Image();
loadings[2].src = "img/game_loading3.png";
loadings[3] = new Image();
loadings[3].src = "img/game_loading4.png";
var LOADING = {
imges: loadings,
length: loadings.length,
width: 186,
height: 38,
};
// 構(gòu)造函數(shù)
function Loading(config) {
this.imges = config.imges;
this.length = config.length;
this.width = config.width;
this.height = config.height;
this.startIndex = 0; // 用于判斷需要顯示的圖片是哪個(gè)
// 繪制方法
this.paint = function() {
ctx.drawImage(this.imges[this.startIndex], 0, height - this.height)
};
this.time = 0; // 加載時(shí)圖片切換速度
// 圖片切換方法
this.step = function() {
this.time++;
if (this.time % 4 === 0) {
this.startIndex++;
}
if (this.startIndex === this.length) {
// 加載階段結(jié)束,進(jìn)入游戲階段
state = running;
}
}
};
// 創(chuàng)建加載階段的對(duì)象
var loading = new Loading(LOADING);
在制作我方飛機(jī)
// 我方飛機(jī)
var heros = [];
heros[0] = new Image();
heros[0].src = "img/hero1.png";
heros[1] = new Image();
heros[1].src = "img/hero2.png";
heros[2] = new Image();
heros[2].src = "img/hero_blowup_n1.png";
heros[3] = new Image();
heros[3].src = "img/hero_blowup_n2.png";
heros[4] = new Image();
heros[4].src = "img/hero_blowup_n3.png";
heros[5] = new Image();
heros[5].src = "img/hero_blowup_n4.png";
var HEROS = {
imgs: heros,
length: heros.length,
width: 99,
height: 124,
frame: 2
};
// 我方飛機(jī)的構(gòu)造函數(shù)
function Hero(config) {
this.imgs = config.imgs;
this.length = config.length;
this.width = config.width;
this.height = config.height;
this.frame = config.frame;
this.startIndex = 0; // 用于判斷我方飛機(jī)當(dāng)前狀態(tài)
// 定義我方飛機(jī)的位置
this.x = width / 2 - this.width / 2;
this.y = height - this.height;
// 定義飛機(jī)撞擊的標(biāo)志,表示飛機(jī)沒有被撞擊
this.down = false;
// 定義飛機(jī)是否爆破完成,表示飛機(jī)還沒有完全爆炸
this.candel = false;
// 繪制方法
this.paint = function() {
ctx.drawImage(this.imgs[this.startIndex], this.x, this.y)
};
// 我方飛機(jī)運(yùn)動(dòng)方法
this.step = function() {
if (!this.down) { // 飛機(jī)正常狀態(tài)
if (this.startIndex === 0) {
this.startIndex = 1;
} else {
this.startIndex = 0
}
} else { // 爆炸狀態(tài)
this.startIndex++;
if (this.startIndex === this.length) { // 判斷是否炸完了
// 炸完了,命-1
life--;
if (life === 0) { // 判斷是否掛了
state = gameover;
this.startIndex = this.length - 1;
} else { // 重新開始新生命
hero = new Hero(HEROS)
}
}
}
};
// 我方飛機(jī)碰撞
this.bang = function() {
this.down = true;
};
繪制子彈狀態(tài)
var bullet = new Image();
bullet.src = "img/bullet1.png";
// 初始化
var BULLETS = {
imgs: bullet,
width: 9,
height: 21,
};
// 創(chuàng)建子彈的構(gòu)造函數(shù)
function Bullet(config) {
this.imgs = config.imgs;
this.width = config.width;
this.height = config.height;
// 子彈坐標(biāo)
this.x = hero.x + hero.width / 2 - this.width / 2;
this.y = hero.y - this.height;
// 繪制方法
this.paint = function() {
ctx.drawImage(this.imgs, this.x, this.y)
};
// 運(yùn)動(dòng)方法
this.step = function() {
this.y -= 10;
};
this.candel = false; // 用于判斷子彈是否碰撞
// 子彈碰撞方法
this.bang = function() {
this.candel = true;
}
};
// 所有new的子彈對(duì)象放到一個(gè)數(shù)組
var bullets = [];
// 遍歷繪制子彈
function bulletdPaint() {
for (var i = 0; i < bullets.length; i++) {
bullets[i].paint();
}
};
// 遍歷調(diào)用子彈的運(yùn)動(dòng);
function bulletdStep() {
for (var i = 0; i < bullets.length; i++) {
bullets[i].step();
}
};
// 子彈的刪除函數(shù)
function bulletDel() {
// 碰撞的時(shí)候刪除子彈
// 超出畫布的高度,即負(fù)的子彈的高度
for (var i = 0; i < bullets.length; i++) {
if (bullets[i].candel || bullets[i].y < -bullets[i].height) {
bullets.splice(i, 1)
}
}
};
子彈跟隨飛機(jī)的移動(dòng)而移動(dòng)
// 子彈發(fā)射
this.time = 0; // 設(shè)計(jì)速度初始為0
this.shoot = function() {
this.time++;
if (this.time % 2 === 0) { // 每2步移動(dòng)射擊一次
bullets.push(new Bullet(BULLETS))
}
};
};
// 創(chuàng)建我方飛機(jī)的對(duì)象實(shí)例
var hero = new Hero(HEROS);
// 鼠標(biāo)移動(dòng)事件
canvas.onmousemove = function(event) {
// console.log("onmousemove");
var event = event || window.event;
if (state == running) { //判斷當(dāng)前游戲狀態(tài)
//把獲取到的頁面中的鼠標(biāo)橫坐標(biāo)的值賦給飛機(jī)的橫坐標(biāo)(位置)
hero.x = event.offsetX - hero.width / 2;
//把獲取到的頁面中的鼠標(biāo)縱坐標(biāo)的值賦給飛機(jī)的縱坐標(biāo)(位置)
hero.y = event.offsetY - hero.height / 2;
}
};
繪制敵方飛機(jī)
// 敵方飛機(jī)的繪制
var enemy1 = []; //小飛機(jī)
enemy1[0] = new Image();
enemy1[0].src = "img/enemy1.png";
enemy1[1] = new Image();
enemy1[1].src = 'img/enemy1_down1.png';
enemy1[2] = new Image();
enemy1[2].src = 'img/enemy1_down2.png';
enemy1[3] = new Image();
enemy1[3].src = 'img/enemy1_down3.png';
enemy1[4] = new Image();
enemy1[4].src = 'img/enemy1_down4.png';
var enemy2 = []; //中飛機(jī)
enemy2[0] = new Image();
enemy2[0].src = "img/enemy2.png";
enemy2[1] = new Image();
enemy2[1].src = "img/enemy2_down1.png";
enemy2[2] = new Image();
enemy2[2].src = "img/enemy2_down2.png";
enemy2[3] = new Image();
enemy2[3].src = "img/enemy2_down3.png";
enemy2[4] = new Image();
enemy2[4].src = "img/enemy2_down4.png";
var enemy3 = []; //大飛機(jī)
enemy3[0] = new Image();
enemy3[0].src = "img/enemy3_n1.png";
enemy3[1] = new Image();
enemy3[1].src = "img/enemy3_n2.png";
enemy3[2] = new Image();
enemy3[2].src = "img/enemy3_down1.png";
enemy3[3] = new Image();
enemy3[3].src = "img/enemy3_down2.png";
enemy3[4] = new Image();
enemy3[4].src = "img/enemy3_down3.png";
enemy3[5] = new Image();
enemy3[5].src = "img/enemy3_down4.png";
enemy3[6] = new Image();
enemy3[6].src = "img/enemy3_down5.png";
enemy3[7] = new Image();
enemy3[7].src = "img/enemy3_down6.png";
// 初始化數(shù)據(jù)
var ENEMY1 = {
imgs: enemy1,
length: enemy1.length,
width: 57,
height: 51,
type: 1,
frame: 2,
life: 1,
score: 1,
};
var ENEMY2 = {
imgs: enemy2,
length: enemy2.length,
width: 69,
height: 95,
type: 2,
frame: 2,
life: 5,
score: 5,
};
var ENEMY3 = {
imgs: enemy3,
length: enemy3.length,
width: 165,
height: 261,
type: 3,
frame: 2,
life: 15,
score: 20,
};
// 敵方飛機(jī)的構(gòu)造函數(shù)
function Enemy(config) {
this.imgs = config.imgs;
this.length = config.length;
this.width = config.width;
this.height = config.height;
this.type = config.type;
this.frame = config.frame;
this.life = config.life;
this.score = config.score;
// 敵方飛機(jī)的坐標(biāo)
this.x = Math.random() * (width - this.width);
this.y = -this.height;
this.startIndex = 0; // 用于判斷的下標(biāo)
this.down = false; // 用于判斷是否碰撞
this.candel = false; // 用于判斷是否爆炸完成
//繪制方法
this.paint = function() {
ctx.drawImage(this.imgs[this.startIndex], this.x, this.y);
};
//運(yùn)動(dòng)方法
this.step = function() {
if (!this.down) { // 敵方飛機(jī)處于正常狀態(tài)
// 小飛機(jī),中飛機(jī)的下標(biāo)始終都是0
// 大飛機(jī)的下標(biāo)是在0和1之間進(jìn)行切換
this.startIndex++;
this.startIndex = this.startIndex % this.frame;
// 飛機(jī)向下的動(dòng)畫
this.y += 2;
} else { //飛機(jī)發(fā)生碰撞以后
this.startIndex++;
if (this.startIndex == this.length) {
this.candel = true;
this.startIndex = this.length - 1;
}
}
};
// 判斷是否被碰撞
this.checkHit = function(wo) { //判斷四個(gè)邊
return wo.y + wo.height > this.y &&
wo.x + wo.width > this.x &&
wo.y < this.y + this.height &&
wo.x < this.x + this.width;
};
//敵方飛機(jī)碰撞后
this.bang = function() {
this.life--;
if (this.life === 0) {
this.down = true;
score += this.score;
}
}
};
// 數(shù)組存放敵方飛機(jī)
var enemise = [];
// 往敵方飛機(jī)數(shù)組中添加數(shù)據(jù)
function enterEnemise() {
var rand = Math.floor(Math.random() * 100)
if (rand < 10) {
// 添加小飛機(jī)
enemise.push(new Enemy(ENEMY1));
} else if (rand < 55 && rand > 50) {
// 添加中飛機(jī)
enemise.push(new Enemy(ENEMY2));
} else if (rand === 88) {
// 添加大飛機(jī)
if (enemise[0].type !== 3 && enemise.length > 0) {
enemise.splice(0, 0, new Enemy(ENEMY3));
}
}
};
// 繪制敵方飛機(jī)函數(shù)
function enemyPaint() {
for (var i = 0; i < enemise.length; i++) {
enemise[i].paint();
}
};
// 敵方飛機(jī)的運(yùn)動(dòng)函數(shù)
function enemyStep() {
for (var i = 0; i < enemise.length; i++) {
enemise[i].step();
}
};
// 刪除敵方飛機(jī)函數(shù)
function delenemy() {
for (var i = 0; i < enemise.length; i++) {
// console.log(enemise[i].candel)
if (enemise[i].y > height || enemise[i].candel) {
enemise.splice(i, 1)
}
}
};
// 碰撞以后的函數(shù)
function hitEnemise() {
for (var i = 0; i < enemise.length; i++) {
// 如果我放飛機(jī)撞到了敵方飛機(jī)以后
if (enemise[i].checkHit(hero)) {
// 敵方飛機(jī)碰撞后,碰撞狀態(tài)改變
enemise[i].bang();
// 我方飛機(jī)碰撞后,碰撞狀態(tài)改變
hero.bang();
};
// 子彈碰到敵方飛機(jī)
for (var j = 0; j < bullets.length; j++) {
if (enemise[i].checkHit(bullets[j])) {
enemise[i].bang();
// 子彈的碰撞后,碰撞狀態(tài)改變
bullets[j].bang();
}
}
}
};
最后的收尾階段
// 繪制分?jǐn)?shù)和生命值
function scoreText() {
ctx.font = "30px bold"
ctx.fillText("score:" + score, 10, 30);
ctx.fillText("life:" + life, 300, 30);
};
// 游戲暫停的階段
canvas.onmouseout = function() {
if (state === running) {
state = pause;
}
};
// 調(diào)用畫布的鼠標(biāo)移入事件
canvas.onmouseover = function() {
if (state === pause) {
state = running;
}
};
// 暫停圖片
var pause = new Image()
pause.src = "img/game_pause_nor.png";
// 游戲結(jié)束
function gameoverfn() {
ctx.font = "50px bold"
ctx.fillText("GAME OVER !!!", 80, 300);
ctx.fillText("ONCE MORE !!!", 80, 400);
};
// 畫布點(diǎn)擊事件
canvas.addEventListener("click", function(e) {
p = getEventPosition(e);
// 點(diǎn)擊畫布時(shí),判斷游戲是否開始
if (state === start) {
state = starting;
}
console.log(123);
// 重新開始游戲有問題???
if (state === gameover) {
if (p.y >= 350 && p.y < 450) {
console.log('你點(diǎn)擊了ONCE MORE !!!');
state = running;
}
}
});
function getEventPosition(e) {
var x, y;
if (e.layerX || ev.layerX === 0) {
x = e.layerX;
y = e.layerY;
} else if (e.offsetX || ev.offsetX === 0) {
x = e.offsetX;
y = e.offsetY;
}
return {
x: x,
y: y
};
};
后面就是基本的每個(gè)階段的調(diào)用問題叻
setInterval(function() {
//背景圖片無論在哪個(gè)狀態(tài)都有背景圖片以及它的動(dòng)態(tài)效果
sky.paint(); // 繪制背景
sky.step(); // 背景動(dòng)畫
if (state === start) { // 第一階段
ctx.drawImage(logo, 35, 0)
} else if (state === starting) { // 第二階段
loading.paint(); // 繪制背景
loading.step(); // 背景動(dòng)畫
} else if (state === running) { // 第三狀態(tài)
// 繪制我放飛機(jī)
hero.paint();
// 我方飛機(jī)的運(yùn)動(dòng)
hero.step();
// 我方飛機(jī)的射擊方法
hero.shoot();
// 子彈的繪制
bulletdPaint();
// 子彈的運(yùn)動(dòng)
bulletdStep();
// 子彈的刪除
bulletDel();
// 創(chuàng)建敵方飛機(jī)
enterEnemise();
// 繪制敵方飛機(jī)
enemyPaint();
// 繪制敵方飛機(jī)的運(yùn)動(dòng)
enemyStep();
// 刪除敵方飛機(jī)
delenemy();
// 判斷是否撞擊
hitEnemise();
// 繪制分?jǐn)?shù)和生命值
scoreText()
} else if (state === pause) { // 第四狀態(tài)
sky.paint(); // 繪制背景
sky.step(); // 背景動(dòng)畫
// 繪制我放飛機(jī)
hero.paint();
// 子彈的繪制
bulletdPaint();
// 繪制敵方飛機(jī)
enemyPaint();
// 繪制分?jǐn)?shù)和生命值
scoreText();
ctx.drawImage(pause, 220, 300)
} else if (state === gameover) { // 第五狀態(tài)
sky.paint(); // 繪制背景
sky.step(); // 背景動(dòng)畫
hero.paint();
// 子彈的繪制
bulletdPaint();
// 繪制敵方飛機(jī)
enemyPaint();
// 繪制分?jǐn)?shù)和生命值
scoreText();
// 游戲結(jié)束
gameoverfn();
}
}, 10)
})()
這個(gè)也就是飛機(jī)大戰(zhàn)的全部源碼了,僅供參考。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js canvas實(shí)現(xiàn)放大鏡查看圖片功能
這篇文章主要為大家詳細(xì)介紹了js canvas實(shí)現(xiàn)放大鏡查看圖片功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
淺談Webpack4 Tree Shaking 終極優(yōu)化指南
這篇文章主要介紹了淺談Webpack4 Tree Shaking 終極優(yōu)化指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
JS實(shí)現(xiàn)圖片延遲加載并淡入淡出效果的簡單方法
我們大家都知道,對(duì)于一個(gè)網(wǎng)站最占用帶寬,最影響頁面顯示速度的東西就是圖片。圖片是很重要的,作為一個(gè)站長我們是千方百計(jì)的使用各種技巧來優(yōu)化圖片,但其實(shí)有一種簡單的方法,只需要幾行代碼就能達(dá)到這種效果。同時(shí)還附加一種淡入淡出的顯示效果,下面一起來看看。2016-08-08
js實(shí)現(xiàn)鼠標(biāo)切換圖片(無定時(shí)器)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)鼠標(biāo)切換圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
JavaScript事件循環(huán)及宏任務(wù)微任務(wù)原理解析
這篇文章主要介紹了JavaScript事件循環(huán)及宏任務(wù)微任務(wù)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
JS事件Event元素(兼容IE,Firefox,Chorme)
今天,想聊聊JS事件對(duì)象。相信大家對(duì)于獲得激發(fā)JS事件的原對(duì)象的理解,有的人可能簡單停留在IE上。也就是window.event這個(gè)對(duì)象2012-11-11

