js實(shí)現(xiàn)坦克大戰(zhàn)游戲
本文實(shí)例為大家分享了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">
<h1 id="ifo_title"></h1>
<h3>按鍵說明:</h3>
T:開始游戲(游戲開始后無效)<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;
//坦克移動不響應(yīng)時(shí)間
const NORESPONSEFIRETIME = 200;
const NORESPONSETANKMOVETIME = TANK_FREQ + 100;
//我方坦克開火、移動狀態(tài)
noresponseFire = false;
noresponseTankMove = false;
//游戲狀態(tài)
state = "READY";
//frequency頻率
//對象id
var tank_id = 0;
var bullent_id = 0;
var wall_id = 0;
//敵方坦克總數(shù)
var emTankNum = 20;
var meTankNum = 3;
//我方坦克對象
var mytank = null;
var tankArray = new Array();
var bullentArray = new Array();
//因?yàn)楣δ苄源u塊會與普通靜態(tài)磚塊重疊所以必須另外存儲
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++) {
//一維長度
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;
//因?yàn)樘箍说膇mg與方向有關(guān),每一次改變dir都會影響img,所以設(shè)置一個(gè)對象函數(shù)用于獲取
this.getImg = function() {
return img = this.belongs + "Tank" + this.selfType + this.dir;
}
//敵方坦克的自移動函數(shù)的setInterval的值t
this.t;
createDOM(this.id, this.width, this.height, this.x, this.y, this.getImg(), 2);
//把生成的坦克對象存入移動對象數(shù)組
tankArray.push(this);
if (belongs == "me") {
mytank = this;
meTankNum--;
}
//敵方坦克調(diào)用自移動函數(shù)
if (this.belongs == "em") {
emTankNum--;
//檢測是否需要生成功能磚塊
createFunctionWall();
autoMove(this);
}
}
//子彈對象
bullent = function(selfType, x, y, belongs, dir) {
//播放發(fā)射子彈音樂
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è)對象函數(shù)用于獲取
this.getImg = function() {
return img = this.type;
}
//子彈與敵方坦克特有屬性,自移動的定時(shí)器
this.t;
createDOM(this.id, this.width, this.height, this.x, this.y, this.getImg(), 1);
//把生成的子彈對象存入移動對象數(shù)組
bullentArray.push(this);
autoMove(this);
}
//墻對象
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è)對象函數(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類型的,分為長寬15的wall、steel和長寬30的star;我們只需要存儲15規(guī)格的,star只有一個(gè)不需要存儲
if (this.belongs != "function") {
noMoveArray[x / 15][y / 15] = this;
} else {
functionWallArray.push(this);
}
}
//對象的定義完------------------------------------------------------------------------------------
//DOM對象創(chuàng)建與顯示-------------------------------------------------------------------------------
//總體說明:1、為了便于計(jì)算所有對象的width、height、x、y均不帶px單位
// 創(chuàng)建DOM對象函數(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對象函數(shù)
function delDOM(id) {
var it = document.getElementById(id);
map.removeChild(it);
}
//展示函數(shù),根據(jù)obj的屬性刷新對應(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對象創(chuàng)建與顯示完-------------------------------------------------------------------------------
//對象的創(chuàng)建與銷毀函數(shù)群-----------------------------------------------------------------------------
//創(chuàng)建坦克函數(shù)
//因?yàn)樘箍顺霈F(xiàn)有一個(gè)動畫,不能直接new tank生成
//new tank(3,15 * 8,15 * 24,"me","U")
function createTank(selfType, belongs, x, y) {
//先讓創(chuàng)建動畫顯示
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)建動畫顯示3s+銷毀1s,所以需要在4s后創(chuàng)建坦克
//這里需要對出生的位置進(jìn)行檢測,防止坦克重疊
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);
}
//刪除對象函數(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)用銷毀坦克動畫
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;
}
}
//對象的創(chuàng)建與銷毀函數(shù)群完---------------------------------------------------------------------------
//碰撞檢測與處理------------------------------------------------------------------------------------
//獲取可能碰撞的靜態(tài)物體函數(shù)
//在存儲靜物的時(shí)候使用二維數(shù)組相當(dāng)于將地圖畫成間距15的小格子,所有的靜物均在小格子中,所以給定一個(gè)物體就可以得到包圍它一圈的小格子;
//這比遍歷整個(gè)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;
//計(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;
}
//碰撞檢測及處理函數(shù)
function collision(obj) {
//collresult有三個(gè)值,MOVE、DELETE、NOMOVE;move表示檢測后的處理結(jié)果是繼續(xù)移動(即使碰上了,有些也不需要處理),DELETE表示刪除自身
//因?yàn)榕鲎矙z測只存在與移動物體,而移動函數(shù)需要碰撞檢測給出是否移動的結(jié)果,所以不能在碰撞處理中直接刪除被檢測物體
var collresult = "MOVE";
//單獨(dú)檢測是否碰撞老巢
//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 因?yàn)闄z測的時(shí)候的對象是通過拷貝得到的,它與真正的坦克的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;
//分別不在被檢測物體的左右上下說明發(fā)生碰撞,開始處理(第一種檢測碰撞算法,考慮反面情況)
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;
}
//碰撞檢測與處理完------------------------------------------------------------------------------------
//坦克與子彈移動函數(shù)-----------------------------------------------------------------------------------
//移動函數(shù)
function move(obj, newDir) {
var oldDir = obj.dir;
obj.dir = newDir;
if (state != "RUN") {
// if(obj.type!="bullent"){
// return;
// }
return;
}
//新的方向與坦克原來方向相同就前進(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);
//出界檢測;
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)用碰撞檢測及處理函數(shù)給出移動結(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;
}
}
//自動移動函數(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);
}
//簡化版移動框架
//為了使坦克的移動更平滑;使用移動框架的前提:必須在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自動移動定時(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ù)
//為自動移動的敵方坦克,返回一個(gè)方向LRUD或者Fire或者none,分別表示轉(zhuǎn)向、開火和什么也不做(繼續(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表示按照原來方向前進(jìn)
return "none";
break;
}
function randomNum(scope) {
return parseInt(Math.random() * scope);
}
}
//坦克與子彈移動函數(shù)完--------------------------------------------------------------------------
//游戲狀態(tài)及提示函數(shù)群--------------------------------------------------------------------------
//開始游戲
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ù)群------------------------------------------------------------------------------------------
//音樂函數(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)建坦克/坦克爆炸動畫函數(shù)
//animationType可取born、blast分別表示坦克出生以及子彈爆炸
function animation(animationType, x, y) {
//這里給動畫所用原子設(shè)置一個(gè)隨機(jī)數(shù)id,防止兩幅動畫使用id一樣造成只有一幅動畫的情況
//這樣仍可能使用一副動畫,不過可能為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)建動畫原子并閃爍
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)主邏輯完---------------------------------------------------------------------------------
//鍵盤監(jiān)聽及觸發(fā)處理開始------------------------------------------------------------------------------
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;
//可以通過在此輸出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;
//發(fā)射子彈 Enter 13
} else if (code == 13 && state == "RUN" && mytank != null && noresponseFire == false) {
//按鍵屏蔽,一定時(shí)間內(nèi)發(fā)射子彈無效
createBullent(myTank);
noresponseFire = true;
//屏蔽P鍵300ms
setTimeout(function() {
noresponseFire = false;
}, NORESPONSEFIRETIME);
return;
//屏蔽其他無關(guān)按鍵
//P 80表示暫停
} else if (code == 80 && (state == "RUN" || state == "STOP")) {
stopGame();
return;
//屏蔽其他無關(guān)按鍵
} else {
return;
}
move(myTank, newDir);
}
function setNOresponse(noresponseState, t) {
if (noresponseState == "TankMove") {
noresponseTankMove = true;
//屏蔽P鍵300ms
setTimeout(function() {
noresponseTankMove = false;
}, t);
}
}
//鍵盤監(jiān)聽及觸發(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>
更多關(guān)于Js游戲的精彩文章,請查看專題: 《JavaScript經(jīng)典游戲 玩不停》
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實(shí)現(xiàn)語音排隊(duì)叫號系統(tǒng)
語音排隊(duì)叫號系統(tǒng)廣泛用于銀行,餐飲,醫(yī)院等場景。本文主要介紹了通過JavaScript實(shí)現(xiàn)的語音排隊(duì)叫號系統(tǒng),有掃碼排隊(duì),語音叫號等功能。需要的可以參考一下2021-12-12
javascript下function聲明一些小結(jié)
function聲明一些東西,我們都知道function和var一樣是預(yù)處理的在js里面,但是到底什么是函數(shù)聲明呢,我們來看幾個(gè)例子2007-12-12
zepto中使用swipe.js制作輪播圖附swipeUp,swipeDown不起效果問題
Swipe JS 是一個(gè)輕量級的移動滑動組件,支持 1:1 的觸摸移動,阻力以及防滑性能都不錯,可以讓移動web應(yīng)用展現(xiàn)更多的內(nèi)容,能解決我們對于移動Web對滑動的需求。下面小編給大家介紹zepto中使用swipe.js制作輪播圖附swipeUp,swipeDown不起效果問題,需要朋友可以參考下2015-08-08
JS注冊/移除事件處理程序(ExtJS應(yīng)用程序設(shè)計(jì)實(shí)戰(zhàn))
最常做的事情就是注冊事件處理程序,因?yàn)樵贓xtJS的世界里,幾乎完全由時(shí)間組成,下面是處理程序案例,感興趣的朋友可以參考下哈,希望可以幫助到你2013-05-05
10個(gè)在JavaScript開發(fā)中常遇到的BUG
給大家詳細(xì)著整理了在JavaScript開發(fā)中大家經(jīng)常遇到的BUG和問題,需要的朋友參考學(xué)習(xí)下吧。2017-12-12
javascript實(shí)現(xiàn)抽獎程序的簡單實(shí)例
下面小編就為大家?guī)硪黄猨avascript實(shí)現(xiàn)抽獎程序的簡單實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06

