js實現坦克大戰遊戲
阿新 • • 發佈:2020-02-25
本文例項為大家分享了js實現坦克大戰遊戲的具體程式碼,供大家參考,具體內容如下
<!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"> <h1 id="ifo_title"></h1> <h3>按鍵說明:</h3> T:開始遊戲(遊戲開始後無效)<br/> P:暫停遊戲<br/> W、S、A、D:上、下、左、右<br/> ENTER:發射子彈<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; //當前檔案同目錄 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; //坦克移動不響應時間 const NORESPONSEFIRETIME = 200; const NORESPONSETANKMOVETIME = TANK_FREQ + 100; //我方坦克開火、移動狀態 noresponseFire = false; noresponseTankMove = false; //遊戲狀態 state = "READY"; //frequency頻率 //物件id var tank_id = 0; var bullent_id = 0; var wall_id = 0; //敵方坦克總數 var emTankNum = 20; var meTankNum = 3; //我方坦克物件 var mytank = null; var tankArray = new Array(); var bullentArray = new Array(); //因為功能性磚塊會與普通靜態磚塊重疊所以必須另外儲存 var functionWallArray = new Array(); //地圖width=390,地圖中最小的靜物wall寬度高度=15,所以陣列的一維二維均為390/15=26 //先宣告一維 var noMoveArray = new Array(4); for (var i = 0; i < MAP_W / WALL_W; i++) { //一維長度 noMoveArray[i] = new Array(); //再宣告二維 for (var j = 0; j < MAP_H / WALL_H; j++) { //二維長度 noMoveArray[i][j] = null; } } //常量及全域性變數完-------------------------------------------------------------------------------- //物件的定義------------------------------------------------------------------------------------- //坦克物件 tank = function(selfType,x,y,belongs,dir) { //共有屬性 this.id = "tank_" + tank_id++; this.type = "tank"; //selfType可取1、2、3表示一類坦克,二類坦克,三類坦克 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; //因為坦克的img與方向有關,每一次改變dir都會影響img,所以設定一個物件函式用於獲取 this.getImg = function() { return img = this.belongs + "Tank" + this.selfType + this.dir; } //敵方坦克的自移動函式的setInterval的值t this.t; createDOM(this.id,this.width,this.height,this.x,this.y,this.getImg(),2); //把生成的坦克物件存入移動物件陣列 tankArray.push(this); if (belongs == "me") { mytank = this; meTankNum--; } //敵方坦克呼叫自移動函式 if (this.belongs == "em") { emTankNum--; //檢測是否需要生成功能磚塊 createFunctionWall(); autoMove(this); } } //子彈物件 bullent = function(selfType,dir) { //播放發射子彈音樂 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保持一致,同樣設定一個物件函式用於獲取 this.getImg = function() { return img = this.type; } //子彈與敵方坦克特有屬性,自移動的定時器 this.t; createDOM(this.id,1); //把生成的子彈物件存入移動物件陣列 bullentArray.push(this); autoMove(this); } //牆物件 wall = function(selfType,belongs) { //共有屬性 this.id = "wall_" + wall_id++; this.type = "wall"; //wall、steel、star、timer分別表示普通磚塊、子彈不可打破磚塊、我方老巢、定時器 this.selfType = selfType; this.x = x; this.y = y; //belongs取值home、ordinary、function分別表示老巢的磚塊、一般磚塊、功能性磚塊 this.belongs = belongs; this.width; this.height; if (this.selfType == "star") { //設定全域性變數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保持一致,同樣設定一個物件函式用於獲取 this.getImg = function() { return img = this.selfType; } var zIndex = belongs == "function" ? 3 : 2; createDOM(this.id,zIndex); // if(n==13)console.log(this) //地圖中所有的靜物都是wall型別的,分為長寬15的wall、steel和長寬30的star;我們只需要儲存15規格的,star只有一個不需要儲存 if (this.belongs != "function") { noMoveArray[x / 15][y / 15] = this; } else { functionWallArray.push(this); } } //物件的定義完------------------------------------------------------------------------------------ //DOM物件建立與顯示------------------------------------------------------------------------------- //總體說明:1、為了便於計算所有物件的width、height、x、y均不帶px單位 // 建立DOM物件函式 function createDOM(id,width,height,img,zIndex) { var map = document.getElementById("map"); var it = document.createElement("div"); it.id = id; it.style.zIndex = zIndex; map.appendChild(it); showDOM(id,img); } //刪除DOM物件函式 function delDOM(id) { var it = document.getElementById(id); map.removeChild(it); } //展示函式,根據obj的屬性重新整理對應的DOM function showDOM(id,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物件建立與顯示完------------------------------------------------------------------------------- //物件的建立與銷燬函式群----------------------------------------------------------------------------- //建立坦克函式 //因為坦克出現有一個動畫,不能直接new tank生成 //new tank(3,15 * 8,15 * 24,"me","U") function createTank(selfType,y) { //先讓建立動畫顯示 var emTank_x1 = 0,emTank_x2 = 180; emTank_x3 = 360; var emTank_y = 0; var meTank_x = 15 * 8; var meTank_y = 15 * 24; //因為建立動畫顯示3s+銷燬1s,所以需要在4s後建立坦克 //這裡需要對出生的位置進行檢測,防止坦克重疊 if (belongs == "me" && meTankNum != 0) { animation("born",15 * 24); //我方坦克顯示位置固定 setTimeout(function() { var mytank = new tank(3,"U"); flickerObj(mytank.id); },4500); } if (belongs == "em" && emTankNum != 0) { animation("born",y); //我方坦克顯示位置固定 setTimeout(function() { var emtank = new tank(1,"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; } } } //發射子彈函式 //根據發射子彈坦克位置和方向,生成一個子彈 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",obj.belongs,obj.dir); } //刪除物件函式 //在html中刪除元素,並將陣列中的值賦值為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); ;break; case "em": console.log("敵方坦克=" + emTankNum) if (emTankNum == 0) { console.log("victory"); } ;break; } //呼叫銷燬坦克動畫 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.y,obj.getImg()); } ;break; case "wall": if (obj.selfType == "star") { img = "destory"; showDOM(obj.id,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; } } //物件的建立與銷燬函式群完--------------------------------------------------------------------------- //碰撞檢測與處理------------------------------------------------------------------------------------ //獲取可能碰撞的靜態物體函式 //在儲存靜物的時候使用二維陣列相當於將地圖畫成間距15的小格子,所有的靜物均在小格子中,所以給定一個物體就可以得到包圍它一圈的小格子; //這比遍歷整個noMoveArray來的快的多 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; //計算出的左側、右側、上下側均不能出地圖 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; } //碰撞檢測及處理函式 function collision(obj) { //collresult有三個值,MOVE、DELETE、NOMOVE;move表示檢測後的處理結果是繼續移動(即使碰上了,有些也不需要處理),DELETE表示刪除自身 //因為碰撞檢測只存在與移動物體,而移動函式需要碰撞檢測給出是否移動的結果,所以不能在碰撞處理中直接刪除被檢測物體 var collresult = "MOVE"; //單獨檢測是否碰撞老巢 //collresult = isCollision(obj,star) ? gameOver():"MOVE"; //檢測功能性磚塊 for (var i = 0; i < functionWallArray.length; i++) { if (functionWallArray[i] != null && isCollision(obj,functionWallArray[i])) { collresult = delColl(obj,functionWallArray[i]); } } //檢測所有的靜物;採用的是遍歷所有靜物 // 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]); // } // } // } //檢測所有的靜物;採用的是遍歷可能相撞的靜物 var PossibleCollisionObjArray = getPossibleCollisionObj(obj); for (var i = 0; i < PossibleCollisionObjArray.length; i++) { if (isCollision(obj,PossibleCollisionObjArray[i])) { collresult = delColl(obj,PossibleCollisionObjArray[i]); } } //檢測坦克 for (var i = 0; i < tankArray.length; i++) { //tankArray[i].id != obj.id 因為檢測的時候的物件是通過拷貝得到的,它與真正的坦克的id一樣 if (tankArray[i] != null && tankArray[i].id != obj.id && isCollision(obj,tankArray[i])) { collresult = delColl(obj,tankArray[i]); } } //檢測子彈 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; } //碰撞檢測 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; //分別不在被檢測物體的左右上下說明發生碰撞,開始處理(第一種檢測碰撞演算法,考慮反面情況) 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; } //碰撞處理函式 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+"相撞了 "+"結果="+collresult); return collresult; } //碰撞檢測與處理完------------------------------------------------------------------------------------ //坦克與子彈移動函式----------------------------------------------------------------------------------- //移動函式 function move(obj,newDir) { var oldDir = obj.dir; obj.dir = newDir; if (state != "RUN") { // if(obj.type!="bullent"){ // return; // } return; } //新的方向與坦克原來方向相同就前進,否則改變坦克方向 if (obj.dir != oldDir && obj.type == "tank") { showDOM(obj.id,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); //出界檢測; 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.getImg()); return; } if (checkObj.type == "bullent") { delObj(obj); return; } //呼叫碰撞檢測及處理函式給出移動結果 } else if (collresult == "MOVE") { // if(obj.type=="tank"){ // movingFrame(obj,checkObj.x,checkObj.y) movingFrame(obj,checkObj.y); // } // console.log("目標y="+checkTank.y) obj.x = checkObj.x; obj.y = checkObj.y; // if(obj.type=="bullent"){ // showDOM(obj.id,obj.getImg()); // } // showDOM(obj.id,obj.getImg()); } else if (collresult == "DELETE") { delObj(obj); } else if (collresult == "NOMOVE") { showDOM(obj.id,obj.getImg()); //如果是敵方坦克就給他一個相反的方向,防止它撞牆不回頭 if (obj.belongs == "em" && obj.type == "tank") {} return; } } //反方向函式 //返回一個與輸入方向相反的方向 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; } } //自動移動函式 //子彈坦克所特有 function autoMove(obj) { // console.log("遊戲狀態="+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); } //簡化版移動框架 //為了使坦克的移動更平滑;使用移動框架的前提:必須在t時間內遮蔽坦克的任何方向改變 //因為js浮點數的處理很複雜,這裡僅僅滿足x,y為7.5的倍數,step為7.5 function movingFrame(obj,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); //浮點數的加減乘除 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,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,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自動移動定時器的清除與重建函式 //itState表示清除、建立定時器 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]); } } } } //坦克隨機狀態函式 //為自動移動的敵方坦克,返回一個方向LRUD或者Fire或者none,分別表示轉向、開火和什麼也不做(繼續前行) function randState() { var z; //敵方坦克隨機發射子彈的概率是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表示發射子彈 case 5: return "Fire"; break; default: //none表示按照原來方向前進 return "none"; break; } function randomNum(scope) { return parseInt(Math.random() * scope); } } //坦克與子彈移動函式完-------------------------------------------------------------------------- //遊戲狀態及提示函式群-------------------------------------------------------------------------- //開始遊戲 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,0); createTank(1,180,330,0); } //遊戲暫停函式 function stopGame() { if (state == "RUN") { state = "STOP"; ifo("STOP"); objTimer("stop"); } else if (state == "STOP") { state = "RUN"; ifo(state); objTimer("run"); } } //遊戲結束函式 function gameOver() { state = "OVER"; //暫停子彈的所有定時器 objTimer("stop"); //alert("GAME OVER"); createDOM("over",120,67.5,(MAP_W - 120) / 2,(MAP_H - 67.5) / 2,"over"); flickerObj("over"); } //更改地圖 //保留的第二關、第三關 function changeMap() { //清除所有定時器及地圖 objTimer("stop"); var mapChildrenNodes = map.childNodes; document.body.removeChild(map); //執行runGame //runGame(map2); } //提示資訊函式 //根據遊戲狀態提示資訊 function ifo(state) { var ifo = document.getElementById("ifo"); var ifo_title = document.getElementById("ifo_title"); switch (state) { case "READY": ifo_title.innerHTML = "坦克大戰"; break; case "RUN": ifo.style.display = "none"; break; case "STOP": ifo.style.display = "block"; ifo_title.innerHTML = "暫停"; ifo.style.backgroundColor = "transparent"; break; } } //遊戲狀態及提示函式群完--------------------------------------------------------------------------------- //功能磚塊函式----------------------------------------------------------------------------------------- //生成功能性磚塊 function createFunctionWall() { if (emTankNum != 9 || emTankNum != 13 || emTankNum != 17) { return; } var selfType,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,"function"); flickerObj(it.id); //11秒後刪除它 setTimeout(function() { //10秒後刪除前閃爍功能磚,如果已經被吃了就取消閃爍 if (functionWallArray.indexOf(it) != -1) { flickerObj(it.id); } },10000); setTimeout(function() { //如果11秒刪除時發現功能磚已經被吃了就取消刪除 if (functionWallArray.indexOf(it) != -1) { delObj(it); } },11000); } //老巢steel磚塊函式 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.getImg()); } } } } changeHome("steel"); setTimeout(function() { changeHome("wall"); },5000); } //爆炸磚塊函式 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]); } } } //定時器磚塊函式 function timer() { //暫停坦克的所有定時器 objTimer("stop"); setTimeout(function() { objTimer("run"); },2000); } //功能磚塊函式完--------------------------------------------------------------------------------------- //特效函式群------------------------------------------------------------------------------------------ //音樂函式 function playMusic(src) { var audio = document.createElement("audio"); //var audio=document.createElement("<video controls muted autoplay >"); audio.src = MUSIC_PATH + src + ".wav"; //路徑 audio.play(); } //閃爍函式 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); } } //建立坦克/坦克爆炸動畫函式 //animationType可取born、blast分別表示坦克出生以及子彈爆炸 function animation(animationType,y) { //這裡給動畫所用原子設定一個隨機數id,防止兩幅動畫使用id一樣造成只有一幅動畫的情況 //這樣仍可能使用一副動畫,不過可能為4/1000 animationTypeid = Math.random() * 1000; var id = animationType + animationTypeid; //顯示次數 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; //建立動畫原子並閃爍 for (let i = 1; i <= times; i++) { setTimeout(function() { createDOM(id + i,animationType + i); flickerObj(id + i,fre / times); },fre * i); } //閃爍完畢刪除閃爍原子 setTimeout(function() { for (let i = 1; i <= times; i++) { delDOM(id + i); } },fre * (times + 1)); } //特效函式群完-------------------------------------------------------------------------------------- //坦克大戰主邏輯----------------------------------------------------------------------------------- ifo("READY"); //坦克大戰主邏輯完--------------------------------------------------------------------------------- //鍵盤監聽及觸發處理開始------------------------------------------------------------------------------ noresponseFire = false; noresponseTankMove = false; document.onkeydown = function(event) { //如果遊戲狀態為結束就遮蔽所有按鍵 if (state == "OVER") { return; } var myTank = tankArray[0]; var newDir; // 87=W;83=S;65=A;68=D code = event.keyCode; //可以通過在此輸出code檢測鍵盤的鍵值碼 // 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 開始遊戲 } else if (code == 84 && state == "READY") { runGame(map1); return; //發射子彈 Enter 13 } else if (code == 13 && state == "RUN" && mytank != null && noresponseFire == false) { //按鍵遮蔽,一定時間內發射子彈無效 createBullent(myTank); noresponseFire = true; //遮蔽P鍵300ms setTimeout(function() { noresponseFire = false; },NORESPONSEFIRETIME); return; //遮蔽其他無關按鍵 //P 80表示暫停 } else if (code == 80 && (state == "RUN" || state == "STOP")) { stopGame(); return; //遮蔽其他無關按鍵 } else { return; } move(myTank,newDir); } function setNOresponse(noresponseState,t) { if (noresponseState == "TankMove") { noresponseTankMove = true; //遮蔽P鍵300ms setTimeout(function() { noresponseTankMove = false; },t); } } //鍵盤監聽及觸發處理完------------------------------------------------------------------------------ //地圖1------------------------------------------------------------------------------------------ var map1 = function() { //老巢 new wall("star",15 * 12,"home"); new wall("wall",15 * 11,15 * 25,15 * 23,"home"); new wall("wall",15 * 13,15 * 14,"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,"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,"ordinary"); } } new wall("wall",15 * 15,"ordinary"); new wall("wall",15 * 16,"ordinary"); //steel new wall("steel",15 * 0,"ordinary"); new wall("steel",15 * 1,"ordinary"); new wall("steel",15 * 6,15 * 7,"ordinary"); } //地圖1完--------------------------------------------------------- </script> </html>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。