您好,登錄后才能下訂單哦!
小編給大家分享一下js如何實(shí)現(xiàn)坦克大戰(zhàn)游戲,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
具體內(nèi)容如下
<!DOCTYPE html> <html> <head> <title>tank</title> <style type="text/css"> body { margin: 0px; padding: 0px; border: 0px; } .map { position: absolute; top: 30px; width: 390px; height: 390px; left: 50%; margin-left: -200px; border: 9px solid orange; background-color: #8B8989; } .mapchild { position: absolute; background-size: cover; } #ifo { position: absolute; top: 30px; width: 418px; height: 418px; left: 50%; margin-left: -200px; color: green; text-align: center; background-color: #FAEBD7; z-index: 10; } </style> </head> <body> <div id="ifo"> <h2 id="ifo_title"></h2> <h4>按鍵說(shuō)明:</h4> T:開(kāi)始游戲(游戲開(kāi)始后無(wú)效)<br/> P:暫停游戲<br/> W、S、A、D:上、下、左、右<br/> ENTER:發(fā)射子彈<br/> </div> </body> <script type="text/javascript"> //常量及全局變量的定義-------------------------------------------- const TANK_W = 30; const TANK_H = 30; const MAP_W = TANK_W * 13; const MAP_H = TANK_H * 13; const BULLENT_W = 7.5; const BULLENT_H = 7.5; const WALL_W = 15; const WALL_H = 15; const BULLENT_FREQ = 30; const TANK_FREQ = 200; const TANK_STEP = 7.5; //當(dāng)前文件同目錄 const IMG_PATH = "tankImage/"; const MUSIC_PATH = "tankMusic/"; // 87=W;83=S;65=A;68=D const KEYCODE_U = 87; const KEYCODE_D = 83; const KEYCODE_L = 65; const KEYCODE_R = 68; //坦克移動(dòng)不響應(yīng)時(shí)間 const NORESPONSEFIRETIME = 200; const NORESPONSETANKMOVETIME = TANK_FREQ + 100; //我方坦克開(kāi)火、移動(dòng)狀態(tài) noresponseFire = false; noresponseTankMove = false; //游戲狀態(tài) state = "READY"; //frequency頻率 //對(duì)象id var tank_id = 0; var bullent_id = 0; var wall_id = 0; //敵方坦克總數(shù) var emTankNum = 20; var meTankNum = 3; //我方坦克對(duì)象 var mytank = null; var tankArray = new Array(); var bullentArray = new Array(); //因?yàn)楣δ苄源u塊會(huì)與普通靜態(tài)磚塊重疊所以必須另外存儲(chǔ) var functionWallArray = new Array(); //地圖width=390,地圖中最小的靜物wall寬度高度=15,所以數(shù)組的一維二維均為390/15=26 //先聲明一維 var noMoveArray = new Array(4); for (var i = 0; i < MAP_W / WALL_W; i++) { //一維長(zhǎng)度 noMoveArray[i] = new Array(); //再聲明二維 for (var j = 0; j < MAP_H / WALL_H; j++) { //二維長(zhǎng)度 noMoveArray[i][j] = null; } } //常量及全局變量完-------------------------------------------------------------------------------- //對(duì)象的定義------------------------------------------------------------------------------------- //坦克對(duì)象 tank = function(selfType, x, y, belongs, dir) { //共有屬性 this.id = "tank_" + tank_id++; this.type = "tank"; //selfType可取1、2、3表示一類(lèi)坦克,二類(lèi)坦克,三類(lèi)坦克 this.selfType = selfType; this.x = x; this.y = y; this.belongs = belongs; this.dir = dir; this.width = TANK_W; this.height = TANK_H; this.life = this.selfType; //因?yàn)樘箍说膇mg與方向有關(guān),每一次改變dir都會(huì)影響img,所以設(shè)置一個(gè)對(duì)象函數(shù)用于獲取 this.getImg = function() { return img = this.belongs + "Tank" + this.selfType + this.dir; } //敵方坦克的自移動(dòng)函數(shù)的setInterval的值t this.t; createDOM(this.id, this.width, this.height, this.x, this.y, this.getImg(), 2); //把生成的坦克對(duì)象存入移動(dòng)對(duì)象數(shù)組 tankArray.push(this); if (belongs == "me") { mytank = this; meTankNum--; } //敵方坦克調(diào)用自移動(dòng)函數(shù) if (this.belongs == "em") { emTankNum--; //檢測(cè)是否需要生成功能磚塊 createFunctionWall(); autoMove(this); } } //子彈對(duì)象 bullent = function(selfType, x, y, belongs, dir) { //播放發(fā)射子彈音樂(lè) playMusic("fire"); //共有屬性 this.id = "bullent_" + bullent_id++; this.type = "bullent"; this.selfType = selfType; this.x = x; this.y = y; this.belongs = belongs; this.dir = dir; this.width = BULLENT_W; this.height = BULLENT_H; //為了與坦克的img保持一致,同樣設(shè)置一個(gè)對(duì)象函數(shù)用于獲取 this.getImg = function() { return img = this.type; } //子彈與敵方坦克特有屬性,自移動(dòng)的定時(shí)器 this.t; createDOM(this.id, this.width, this.height, this.x, this.y, this.getImg(), 1); //把生成的子彈對(duì)象存入移動(dòng)對(duì)象數(shù)組 bullentArray.push(this); autoMove(this); } //墻對(duì)象 wall = function(selfType, x, y, belongs) { //共有屬性 this.id = "wall_" + wall_id++; this.type = "wall"; //wall、steel、star、timer分別表示普通磚塊、子彈不可打破磚塊、我方老巢、定時(shí)器 this.selfType = selfType; this.x = x; this.y = y; //belongs取值home、ordinary、function分別表示老巢的磚塊、一般磚塊、功能性磚塊 this.belongs = belongs; this.width; this.height; if (this.selfType == "star") { //設(shè)置全局變量star star = this; this.width = TANK_W; this.height = TANK_H; } else if (this.selfType != "star") { this.width = WALL_W; this.height = WALL_H; } //為了與坦克的img保持一致,同樣設(shè)置一個(gè)對(duì)象函數(shù)用于獲取 this.getImg = function() { return img = this.selfType; } var zIndex = belongs == "function" ? 3 : 2; createDOM(this.id, this.width, this.height, this.x, this.y, this.getImg(), zIndex); // if(n==13)console.log(this) //地圖中所有的靜物都是wall類(lèi)型的,分為長(zhǎng)寬15的wall、steel和長(zhǎng)寬30的star;我們只需要存儲(chǔ)15規(guī)格的,star只有一個(gè)不需要存儲(chǔ) if (this.belongs != "function") { noMoveArray[x / 15][y / 15] = this; } else { functionWallArray.push(this); } } //對(duì)象的定義完------------------------------------------------------------------------------------ //DOM對(duì)象創(chuàng)建與顯示------------------------------------------------------------------------------- //總體說(shuō)明:1、為了便于計(jì)算所有對(duì)象的width、height、x、y均不帶px單位 // 創(chuàng)建DOM對(duì)象函數(shù) function createDOM(id, width, height, x, y, img, zIndex) { var map = document.getElementById("map"); var it = document.createElement("div"); it.id = id; it.style.zIndex = zIndex; map.appendChild(it); showDOM(id, width, height, x, y, img); } //刪除DOM對(duì)象函數(shù) function delDOM(id) { var it = document.getElementById(id); map.removeChild(it); } //展示函數(shù),根據(jù)obj的屬性刷新對(duì)應(yīng)的DOM function showDOM(id, width, height, x, y, img) { var it = document.getElementById(id); it.className = "mapchild"; it.style.cssText = "width:" + width + "px;height:" + height + "px;left:" + x + "px;top:" + y + "px;background-image:url('" + IMG_PATH + img + ".gif');"; } //DOM對(duì)象創(chuàng)建與顯示完------------------------------------------------------------------------------- //對(duì)象的創(chuàng)建與銷(xiāo)毀函數(shù)群----------------------------------------------------------------------------- //創(chuàng)建坦克函數(shù) //因?yàn)樘箍顺霈F(xiàn)有一個(gè)動(dòng)畫(huà),不能直接new tank生成 //new tank(3,15 * 8,15 * 24,"me","U") function createTank(selfType, belongs, x, y) { //先讓創(chuàng)建動(dòng)畫(huà)顯示 var emTank_x1 = 0 , emTank_x2 = 180; emTank_x3 = 360; var emTank_y = 0; var meTank_x = 15 * 8; var meTank_y = 15 * 24; //因?yàn)閯?chuàng)建動(dòng)畫(huà)顯示3s+銷(xiāo)毀1s,所以需要在4s后創(chuàng)建坦克 //這里需要對(duì)出生的位置進(jìn)行檢測(cè),防止坦克重疊 if (belongs == "me" && meTankNum != 0) { animation("born", 15 * 8, 15 * 24); //我方坦克顯示位置固定 setTimeout(function() { var mytank = new tank(3,15 * 8,15 * 24,"me","U"); flickerObj(mytank.id); }, 4500); } if (belongs == "em" && emTankNum != 0) { animation("born", x, y); //我方坦克顯示位置固定 setTimeout(function() { var emtank = new tank(1,x,y,"em","U"); flickerObj(emtank.id); }, 4500); } //判斷指定位置是否有坦克 function isThereHaveTank(x, y) { if (tankArray.length == 0) { return false; } for (var i = 0; i < tankArray.length; i++) { return tankArray[i].x == x && tankArray[i].y == y; } } } //發(fā)射子彈函數(shù) //根據(jù)發(fā)射子彈坦克位置和方向,生成一個(gè)子彈 function createBullent(obj) { var x, y; switch (obj.dir) { case "U": x = obj.x + 0.5 * obj.width - 0.5 * BULLENT_W; y = obj.y; break; case "D": x = obj.x + 0.5 * obj.width - 0.5 * BULLENT_W; y = obj.y + obj.height - BULLENT_H; break; case "L": x = obj.x; y = obj.y + 0.5 * obj.height - 0.5 * BULLENT_H; break; case "R": x = obj.x + obj.width - BULLENT_W; y = obj.y + 0.5 * obj.height - 0.5 * BULLENT_H; break; } new bullent("speed",x,y,obj.belongs,obj.dir); } //刪除對(duì)象函數(shù) //在html中刪除元素,并將數(shù)組中的值賦值為null function delObj(obj) { if (obj.t != undefined) { clearInterval(obj.t); } switch (obj.type) { case "bullent": delDOM(obj.id); bullentArray.splice(bullentArray.indexOf(obj), 1); break; case "tank": if (--obj.life == 0) { switch (obj.belongs) { case "me": meTankNum == 0 ? gameOver() : createTank(3, null, null, "me", null); ;break; case "em": console.log("敵方坦克=" + emTankNum) if (emTankNum == 0) { console.log("victory"); } ;break; } //調(diào)用銷(xiāo)毀坦克動(dòng)畫(huà) animation("blast", obj.x, obj.y); delDOM(obj.id); delete tankArray[tankArray.indexOf(obj)]; if (obj.belongs == "me") { mytank = null; gameOver(); } //obj.life!=0 } else { obj.selfType = obj.life; showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); } ;break; case "wall": if (obj.selfType == "star") { img = "destory"; showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, img); gameOver(); } else if (obj.belongs == "function") { delDOM(obj.id); functionWallArray.splice(bullentArray.indexOf(obj), 1); } else { delDOM(obj.id); noMoveArray[obj.x / 15][obj.y / 15] = null; } ;break; } } //對(duì)象的創(chuàng)建與銷(xiāo)毀函數(shù)群完--------------------------------------------------------------------------- //碰撞檢測(cè)與處理------------------------------------------------------------------------------------ //獲取可能碰撞的靜態(tài)物體函數(shù) //在存儲(chǔ)靜物的時(shí)候使用二維數(shù)組相當(dāng)于將地圖畫(huà)成間距15的小格子,所有的靜物均在小格子中,所以給定一個(gè)物體就可以得到包圍它一圈的小格子; //這比遍歷整個(gè)noMoveArray來(lái)的快的多 function getPossibleCollisionObj(obj) { var PossibleCollisionObjArray = new Array(); var largeWidth = WALL_W; var largeHeight = WALL_H; var x_l = obj.x - largeWidth; var x_r = obj.x + largeWidth + obj.width; var y_u = obj.y - largeHeight; var y_d = obj.y + largeHeight + obj.height; //計(jì)算出的左側(cè)、右側(cè)、上下側(cè)均不能出地圖 if (x_l < 0) x_l = 0; if (x_r > MAP_W) x_r = MAP_W; if (y_u < 0) y_u = 0; if (y_d > MAP_H) y_d = MAP_H; for (var i = Math.floor(x_l / largeWidth); i < Math.floor(x_r / largeWidth); i++) { for (var j = Math.floor(y_u / largeHeight); j < Math.floor(y_d / largeHeight); j++) { if (noMoveArray[i][j] != null) { PossibleCollisionObjArray.push(noMoveArray[i][j]); } } } //console.log(PossibleCollisionObjArray); return PossibleCollisionObjArray; } //碰撞檢測(cè)及處理函數(shù) function collision(obj) { //collresult有三個(gè)值,MOVE、DELETE、NOMOVE;move表示檢測(cè)后的處理結(jié)果是繼續(xù)移動(dòng)(即使碰上了,有些也不需要處理),DELETE表示刪除自身 //因?yàn)榕鲎矙z測(cè)只存在與移動(dòng)物體,而移動(dòng)函數(shù)需要碰撞檢測(cè)給出是否移動(dòng)的結(jié)果,所以不能在碰撞處理中直接刪除被檢測(cè)物體 var collresult = "MOVE"; //單獨(dú)檢測(cè)是否碰撞老巢 //collresult = isCollision(obj, star) ? gameOver():"MOVE"; //檢測(cè)功能性磚塊 for (var i = 0; i < functionWallArray.length; i++) { if (functionWallArray[i] != null && isCollision(obj, functionWallArray[i])) { collresult = delColl(obj, functionWallArray[i]); } } //檢測(cè)所有的靜物;采用的是遍歷所有靜物 // for (var i = 0; i < noMoveArray.length; i++) { // for (var j = 0; j < noMoveArray[i].length; j++) { // if (noMoveArray[i][j] != null && isCollision(obj, noMoveArray[i][j])) { // collresult = delColl(obj, noMoveArray[i][j]); // } // } // } //檢測(cè)所有的靜物;采用的是遍歷可能相撞的靜物 var PossibleCollisionObjArray = getPossibleCollisionObj(obj); for (var i = 0; i < PossibleCollisionObjArray.length; i++) { if (isCollision(obj, PossibleCollisionObjArray[i])) { collresult = delColl(obj, PossibleCollisionObjArray[i]); } } //檢測(cè)坦克 for (var i = 0; i < tankArray.length; i++) { //tankArray[i].id != obj.id 因?yàn)闄z測(cè)的時(shí)候的對(duì)象是通過(guò)拷貝得到的,它與真正的坦克的id一樣 if (tankArray[i] != null && tankArray[i].id != obj.id && isCollision(obj, tankArray[i])) { collresult = delColl(obj, tankArray[i]); } } //檢測(cè)子彈 for (var i = 0; i < bullentArray.length; i++) { if (bullentArray[i].id != obj.id && isCollision(obj, bullentArray[i])) { collresult = delColl(obj, bullentArray[i]); } } return collresult; } //碰撞檢測(cè) function isCollision(obj, obji) { var iscoll; //用x_l、x_r、y_u、y_d分別表示左右上下的值 var x_l = obj.x; var x_r = x_l + obj.width; var y_u = obj.y; var y_d = y_u + obj.height; var x_li = obji.x; var x_ri = x_li + obji.width; var y_ui = obji.y; var y_di = y_ui + obji.height; //分別不在被檢測(cè)物體的左右上下說(shuō)明發(fā)生碰撞,開(kāi)始處理(第一種檢測(cè)碰撞算法,考慮反面情況) if (!(x_r <= x_li | x_l >= x_ri | y_d <= y_ui | y_u >= y_di)) { //console.log(obj.id+"與"+obji.id+"相撞了") iscoll = true; } else { iscoll = false; } return iscoll; } //碰撞處理函數(shù) function delColl(obj, obji) { var collresult; switch (obj.type) { case "bullent": switch (obji.type) { case "tank": switch (obj.belongs) { case "me": switch (obji.belongs) { case "me": collresult = "MOVE"; break; case "em": collresult = "DELETE"; playMusic("hit"); animation("blast", obji.x, obji.y); delObj(obji); break; } ;break; case "em": switch (obji.belongs) { case "me": collresult = "DELETE"; playMusic("hit"); delObj(obji); break; case "em": collresult = "MOVE"; break; } ;break; } break; case "wall": switch (obji.selfType) { case "steel": collresult = "DELETE"; playMusic("hit"); break; case "wall": collresult = "DELETE"; playMusic("hit"); delObj(obji); break; case "star": collresult = "DELETE"; playMusic("hit"); delObj(obji); break; } ;break; case "bullent": switch (obji.belongs) { default: collresult = "MOVE"; break; } ;break; } ;break; case "tank": switch (obji.type) { case "tank": collresult = "NOMOVE"; break; case "wall": switch (obji.selfType) { case "wall": case "steel": collresult = "NOMOVE"; break; case "timer": collresult = "MOVE"; timer(); delObj(obji); break; case "bomb": collresult = "MOVE"; bomb(); delObj(obji); break; case "stronghome": collresult = "MOVE"; delObj(obji); StrongHome(); break; } ;break; case "bullent": switch (obj.belongs) { case "me": switch (obji.belongs) { case "me": collresult = "MOVE"; break; case "em": collresult = "DELETE"; break; } ;break; case "em": switch (obji.belongs) { case "me": collresult = "DELETE"; delObj(obji); break; case "em": collresult = "MOVE"; break; } ;break; } ;break; } ;break; } //console.log(obj.id+"與"+obji.id+"相撞了 "+"結(jié)果="+collresult); return collresult; } //碰撞檢測(cè)與處理完------------------------------------------------------------------------------------ //坦克與子彈移動(dòng)函數(shù)----------------------------------------------------------------------------------- //移動(dòng)函數(shù) function move(obj, newDir) { var oldDir = obj.dir; obj.dir = newDir; if (state != "RUN") { // if(obj.type!="bullent"){ // return; // } return; } //新的方向與坦克原來(lái)方向相同就前進(jìn),否則改變坦克方向 if (obj.dir != oldDir && obj.type == "tank") { showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); return; } var x = 0 , y = 0; var step = TANK_STEP; switch (obj.dir) { case "L": x = -step; break; case "R": x = step; break; case "U": y = -step; break; case "D": y = step; break; } //粗糙的深拷貝 var objString = JSON.stringify(obj); var checkObj = JSON.parse(objString); checkObj.x += x; checkObj.y += y; var collresult = collision(checkObj); //出界檢測(cè); if (checkObj.x < 0 || (checkObj.x + checkObj.width) > MAP_W || checkObj.y < 0 || (checkObj.y + checkObj.height) > MAP_H) { if (checkObj.type == "tank") { showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); return; } if (checkObj.type == "bullent") { delObj(obj); return; } //調(diào)用碰撞檢測(cè)及處理函數(shù)給出移動(dòng)結(jié)果 } else if (collresult == "MOVE") { // if(obj.type=="tank"){ // movingFrame(obj,checkObj.x,checkObj.y) movingFrame(obj, checkObj.x, checkObj.y); // } // console.log("目標(biāo)y="+checkTank.y) obj.x = checkObj.x; obj.y = checkObj.y; // if(obj.type=="bullent"){ // showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); // } // showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); } else if (collresult == "DELETE") { delObj(obj); } else if (collresult == "NOMOVE") { showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); //如果是敵方坦克就給他一個(gè)相反的方向,防止它撞墻不回頭 if (obj.belongs == "em" && obj.type == "tank") {} return; } } //反方向函數(shù) //返回一個(gè)與輸入方向相反的方向 function negativeDir(dir) { switch (dir) { case "L": return "R"; break; case "R": return "L"; break; case "U": return "D"; break; case "D": return "U"; break; } } //自動(dòng)移動(dòng)函數(shù) //子彈坦克所特有 function autoMove(obj) { // console.log("游戲狀態(tài)="+state) var itFreq = BULLENT_FREQ; var itType = obj.type; var itId = obj.id; var itDir = obj.dir; if (obj.type == "tank") { itFreq = TANK_FREQ; } obj.t = setInterval(function() { if (itType == "tank") { var itObj = obj; var turn = randState(); if (turn == "Fire") { //console.log(obj.id+" "+obj.t) createBullent(itObj); return; } else if (turn == "none") { itDir = itObj.dir; } else { itDir = turn; } } move(obj, itDir); }, itFreq); } //簡(jiǎn)化版移動(dòng)框架 //為了使坦克的移動(dòng)更平滑;使用移動(dòng)框架的前提:必須在t時(shí)間內(nèi)屏蔽坦克的任何方向改變 //因?yàn)閖s浮點(diǎn)數(shù)的處理很復(fù)雜,這里僅僅滿足x,y為7.5的倍數(shù),step為7.5 function movingFrame(obj, x, y) { var objDom = document.getElementById(obj.id); var t = TANK_FREQ; var x1 = obj.x; var y1 = obj.y; var step_x = div(sub(x, x1), t / 10); var step_y = div(sub(y, y1), t / 10); var aaa = 1; var times = 1; var tank_t = setInterval(function() { if (times == t / 10) { clearInterval(tank_t); } times++; x1 = add(x1, step_x); y1 = add(y1, step_y); objDom.style.left = x1 + "px"; objDom.style.top = y1 + "px"; }, 10); //浮點(diǎn)數(shù)的加減乘除 function add(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; } catch (f) { c = 0; } try { d = b.toString().split(".")[1].length; } catch (f) { d = 0; } return e = Math.pow(10, Math.max(c, d)), (mul(a, e) + mul(b, e)) / e; } function sub(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; } catch (f) { c = 0; } try { d = b.toString().split(".")[1].length; } catch (f) { d = 0; } return e = Math.pow(10, Math.max(c, d)), (mul(a, e) - mul(b, e)) / e; } function mul(a, b) { var c = 0 , d = a.toString() , e = b.toString(); try { c += d.split(".")[1].length; } catch (f) {} try { c += e.split(".")[1].length; } catch (f) {} return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c); } function div(a, b) { var c, d, e = 0, f = 0; try { e = a.toString().split(".")[1].length; } catch (g) {} try { f = b.toString().split(".")[1].length; } catch (g) {} return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), mul(c / d, Math.pow(10, f - e)); } } //tank自動(dòng)移動(dòng)定時(shí)器的清除與重建函數(shù) //itState表示清除、建立定時(shí)器 function objTimer(itState) { for (var i = 0; i < tankArray.length; i++) { if (tankArray[i] != null && tankArray[i].type == "tank") { if (itState == "stop" && tankArray[i].t != undefined) { clearInterval(tankArray[i].t); } if (itState == "run" && tankArray[i].belongs == "em") { autoMove(tankArray[i]); } } } } //坦克隨機(jī)狀態(tài)函數(shù) //為自動(dòng)移動(dòng)的敵方坦克,返回一個(gè)方向LRUD或者Fire或者none,分別表示轉(zhuǎn)向、開(kāi)火和什么也不做(繼續(xù)前行) function randState() { var z; //敵方坦克隨機(jī)發(fā)射子彈的概率是1/7 z = randomNum(10); switch (z) { case 1: return "L"; break; case 2: return "R"; break; case 3: return "D"; break; case 4: return "L"; break; //5表示發(fā)射子彈 case 5: return "Fire"; break; default: //none表示按照原來(lái)方向前進(jìn) return "none"; break; } function randomNum(scope) { return parseInt(Math.random() * scope); } } //坦克與子彈移動(dòng)函數(shù)完-------------------------------------------------------------------------- //游戲狀態(tài)及提示函數(shù)群-------------------------------------------------------------------------- //開(kāi)始游戲 function runGame(mapName) { //生成地圖 var map = document.createElement("div"); map.id = "map"; map.className = "map"; document.body.appendChild(map); state = "RUN"; ifo(state); mapName(); playMusic("start"); createTank(3, "me"); createTank(1, "em", 0, 0); createTank(1, "em", 180, 0); createTank(1, "em", 330, 0); } //游戲暫停函數(shù) function stopGame() { if (state == "RUN") { state = "STOP"; ifo("STOP"); objTimer("stop"); } else if (state == "STOP") { state = "RUN"; ifo(state); objTimer("run"); } } //游戲結(jié)束函數(shù) function gameOver() { state = "OVER"; //暫停子彈的所有定時(shí)器 objTimer("stop"); //alert("GAME OVER"); createDOM("over", 120, 67.5, (MAP_W - 120) / 2, (MAP_H - 67.5) / 2, "over"); flickerObj("over"); } //更改地圖 //保留的第二關(guān)、第三關(guān) function changeMap() { //清除所有定時(shí)器及地圖 objTimer("stop"); var mapChildrenNodes = map.childNodes; document.body.removeChild(map); //執(zhí)行runGame //runGame(map2); } //提示信息函數(shù) //根據(jù)游戲狀態(tài)提示信息 function ifo(state) { var ifo = document.getElementById("ifo"); var ifo_title = document.getElementById("ifo_title"); switch (state) { case "READY": ifo_title.innerHTML = "坦克大戰(zhàn)"; break; case "RUN": ifo.style.display = "none"; break; case "STOP": ifo.style.display = "block"; ifo_title.innerHTML = "暫停"; ifo.style.backgroundColor = "transparent"; break; } } //游戲狀態(tài)及提示函數(shù)群完--------------------------------------------------------------------------------- //功能磚塊函數(shù)----------------------------------------------------------------------------------------- //生成功能性磚塊 function createFunctionWall() { if (emTankNum != 9 || emTankNum != 13 || emTankNum != 17) { return; } var selfType, x, y; switch (emTankNum) { case 9: selfType == "timer"; x = 15 * 18; y = 15 * 6; break; case 13: selfType == "stronghome"; x = 15 * 2; y = 15 * 18; break; case 17: selfType == "bomb"; x = 15 * 22; y = 15 * 17; break; } var it = new wall(selfType,x,y,"function"); flickerObj(it.id); //11秒后刪除它 setTimeout(function() { //10秒后刪除前閃爍功能磚,如果已經(jīng)被吃了就取消閃爍 if (functionWallArray.indexOf(it) != -1) { flickerObj(it.id); } }, 10000); setTimeout(function() { //如果11秒刪除時(shí)發(fā)現(xiàn)功能磚已經(jīng)被吃了就取消刪除 if (functionWallArray.indexOf(it) != -1) { delObj(it); } }, 11000); } //老巢steel磚塊函數(shù) function StrongHome() { function changeHome(selfType) { for (var i = 0; i < noMoveArray.length; i++) { for (var j = 0; j < noMoveArray[i].length; j++) { if (noMoveArray[i][j] != null && noMoveArray[i][j].belongs == "home" && noMoveArray[i][j].selfType != "star") { noMoveArray[i][j].selfType = selfType; noMoveArray[i][j].img = noMoveArray[i][j].selfType; var obj = noMoveArray[i][j]; showDOM(obj.id, obj.width, obj.height, obj.x, obj.y, obj.getImg()); } } } } changeHome("steel"); setTimeout(function() { changeHome("wall"); }, 5000); } //爆炸磚塊函數(shù) function bomb() { for (var i = 0; i < tankArray.length; i++) { objTimer("stop"); if (tankArray[i] != null && tankArray[i].belongs == "em") { //console.log(moveArray[i]) delObj(tankArray[i]); } } } //定時(shí)器磚塊函數(shù) function timer() { //暫停坦克的所有定時(shí)器 objTimer("stop"); setTimeout(function() { objTimer("run"); }, 2000); } //功能磚塊函數(shù)完--------------------------------------------------------------------------------------- //特效函數(shù)群------------------------------------------------------------------------------------------ //音樂(lè)函數(shù) function playMusic(src) { var audio = document.createElement("audio"); //var audio=document.createElement("<video controls muted autoplay >"); audio.src = MUSIC_PATH + src + ".wav"; //路徑 audio.play(); } //閃爍函數(shù) function flickerObj(id, interval) { var it = document.getElementById(id); for (let i = 1; i <= 3; i++) { setTimeout(function() { var display = i % 2 == 0 ? "none" : "block"; it.style.display = display; //it.style.display="none"; }, (interval / 3) * i); } } //創(chuàng)建坦克/坦克爆炸動(dòng)畫(huà)函數(shù) //animationType可取born、blast分別表示坦克出生以及子彈爆炸 function animation(animationType, x, y) { //這里給動(dòng)畫(huà)所用原子設(shè)置一個(gè)隨機(jī)數(shù)id,防止兩幅動(dòng)畫(huà)使用id一樣造成只有一幅動(dòng)畫(huà)的情況 //這樣仍可能使用一副動(dòng)畫(huà),不過(guò)可能為4/1000 animationTypeid = Math.random() * 1000; var id = animationType + animationTypeid; //顯示次數(shù) var times = animationType == "born" ? 3 : 1; //顯示頻率 var fre = animationType == "born" ? 1000 : 300; // var width = animationType == "born" ? TANK_W : BULLENT_W; // var height = animationType == "born" ? TANK_H : BULLENT_H; var width = TANK_W; var height = TANK_H; //創(chuàng)建動(dòng)畫(huà)原子并閃爍 for (let i = 1; i <= times; i++) { setTimeout(function() { createDOM(id + i, width, height, x, y, animationType + i); flickerObj(id + i, fre / times); }, fre * i); } //閃爍完畢刪除閃爍原子 setTimeout(function() { for (let i = 1; i <= times; i++) { delDOM(id + i); } }, fre * (times + 1)); } //特效函數(shù)群完-------------------------------------------------------------------------------------- //坦克大戰(zhàn)主邏輯----------------------------------------------------------------------------------- ifo("READY"); //坦克大戰(zhàn)主邏輯完--------------------------------------------------------------------------------- //鍵盤(pán)監(jiān)聽(tīng)及觸發(fā)處理開(kāi)始------------------------------------------------------------------------------ noresponseFire = false; noresponseTankMove = false; document.onkeydown = function(event) { //如果游戲狀態(tài)為結(jié)束就屏蔽所有按鍵 if (state == "OVER") { return; } var myTank = tankArray[0]; var newDir; // 87=W;83=S;65=A;68=D code = event.keyCode; //可以通過(guò)在此輸出code檢測(cè)鍵盤(pán)的鍵值碼 // console.log(code) if (code == 65 && state == "RUN" && mytank != null && noresponseTankMove == false) { setNOresponse("TankMove", NORESPONSEFIRETIME); newDir = "L"; } else if (code == 87 && state == "RUN" && mytank != null && noresponseTankMove == false) { console.log(noresponseTankMove) setNOresponse("TankMove", NORESPONSEFIRETIME); newDir = "U"; } else if (code == 68 && state == "RUN" && mytank != null && noresponseTankMove == false) { setNOresponse("TankMove", NORESPONSEFIRETIME); newDir = "R"; } else if (code == 83 && state == "RUN" && mytank != null && noresponseTankMove == false) { setNOresponse("TankMove", NORESPONSEFIRETIME); newDir = "D"; //T 84 開(kāi)始游戲 } else if (code == 84 && state == "READY") { runGame(map1); return; //發(fā)射子彈 Enter 13 } else if (code == 13 && state == "RUN" && mytank != null && noresponseFire == false) { //按鍵屏蔽,一定時(shí)間內(nèi)發(fā)射子彈無(wú)效 createBullent(myTank); noresponseFire = true; //屏蔽P鍵300ms setTimeout(function() { noresponseFire = false; }, NORESPONSEFIRETIME); return; //屏蔽其他無(wú)關(guān)按鍵 //P 80表示暫停 } else if (code == 80 && (state == "RUN" || state == "STOP")) { stopGame(); return; //屏蔽其他無(wú)關(guān)按鍵 } else { return; } move(myTank, newDir); } function setNOresponse(noresponseState, t) { if (noresponseState == "TankMove") { noresponseTankMove = true; //屏蔽P鍵300ms setTimeout(function() { noresponseTankMove = false; }, t); } } //鍵盤(pán)監(jiān)聽(tīng)及觸發(fā)處理完------------------------------------------------------------------------------ //地圖1------------------------------------------------------------------------------------------ var map1 = function() { //老巢 new wall("star",15 * 12,15 * 24,"home"); new wall("wall",15 * 11,15 * 25,"home"); new wall("wall",15 * 11,15 * 24,"home"); new wall("wall",15 * 11,15 * 23,"home"); new wall("wall",15 * 12,15 * 23,"home"); new wall("wall",15 * 13,15 * 23,"home"); new wall("wall",15 * 14,15 * 25,"home"); new wall("wall",15 * 14,15 * 24,"home"); new wall("wall",15 * 14,15 * 23,"home"); // 老巢完畢 //所有普通wall for (var i = 1; i <= 11; i += 2) { for (var j = 2; j < 24; j++) { if (j >= 10 && j < 14) { continue; } if (i == 5 || i == 7) { if (j > 8 && j <= 11) continue; if (j > 20) continue; } else { if (j >= 14 && j < 16) { continue; } } new wall("wall",15 * 2 * i,15 * j,"ordinary"); new wall("wall",15 * 2 * i + 15,15 * j,"ordinary"); } } for (var i = 0; i < 6; i++) { for (var j = 0; j < 2; j++) { new wall("wall",15 * i + 15 * 10,15 * 11 + 15 * j,"ordinary"); if (i > 3) continue; new wall("wall",15 * i + 15 * 4,15 * 12 + 15 * j,"ordinary"); new wall("wall",15 * i + 15 * 18,15 * 12 + 15 * j,"ordinary"); } } new wall("wall",15 * 12,15 * 15,"ordinary"); new wall("wall",15 * 12,15 * 16,"ordinary"); new wall("wall",15 * 13,15 * 15,"ordinary"); new wall("wall",15 * 13,15 * 16,"ordinary"); //steel new wall("steel",15 * 0,15 * 13,"ordinary"); new wall("steel",15 * 1,15 * 13,"ordinary"); new wall("steel",15 * 24,15 * 13,"ordinary"); new wall("steel",15 * 25,15 * 13,"ordinary"); new wall("steel",15 * 12,15 * 6,"ordinary"); new wall("steel",15 * 12,15 * 7,"ordinary"); new wall("steel",15 * 13,15 * 6,"ordinary"); new wall("steel",15 * 13,15 * 7,"ordinary"); } //地圖1完--------------------------------------------------------- </script> </html>
以上是“js如何實(shí)現(xiàn)坦克大戰(zhàn)游戲”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。