js实现坦克大战游戏


Posted in Javascript onFebruary 24, 2020

本文实例为大家分享了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, x, y, belongs, 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, this.width, this.height, this.x, this.y, this.getImg(), 1);
  //把生成的子弹对象存入移动对象数组
  bullentArray.push(this);
  autoMove(this);

 }

 //墙对象 
 wall = function(selfType, x, y, 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, this.width, this.height, this.x, this.y, this.getImg(), 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, 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对象函数
 function delDOM(id) {
  var it = document.getElementById(id);
  map.removeChild(it);
 }

 //展示函数,根据obj的属性刷新对应的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对象创建与显示完-------------------------------------------------------------------------------

 //对象的创建与销毁函数群-----------------------------------------------------------------------------

 //创建坦克函数
 //因为坦克出现有一个动画,不能直接new tank生成
 //new tank(3,15 * 8,15 * 24,"me","U")
 function createTank(selfType, belongs, x, 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 * 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;
  }
  }

 }

 //发射子弹函数
 //根据发射子弹坦克位置和方向,生成一个子弹
 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);

 }

 //删除对象函数
 //在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, "me", 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.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;
  }

 }

 //对象的创建与销毁函数群完---------------------------------------------------------------------------

 //碰撞检测与处理------------------------------------------------------------------------------------

 //获取可能碰撞的静态物体函数
 //在存储静物的时候使用二维数组相当于将地图画成间距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.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;
  }
  //调用碰撞检测及处理函数给出移动结果
  } else if (collresult == "MOVE") {
  // if(obj.type=="tank"){
  // movingFrame(obj,checkObj.x,checkObj.y) 
  movingFrame(obj, checkObj.x, checkObj.y);
  // }
  // console.log("目标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());
  //如果是敌方坦克就给他一个相反的方向,防止它撞墙不回头
  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, 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);

  //浮点数的加减乘除

  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自动移动定时器的清除与重建函数
 //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, "em", 0, 0);
  createTank(1, "em", 180, 0);
  createTank(1, "em", 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, 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秒后删除前闪烁功能砖,如果已经被吃了就取消闪烁
  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.width, obj.height, obj.x, obj.y, 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, x, 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, 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));

 }
 //特效函数群完--------------------------------------------------------------------------------------

 //坦克大战主逻辑-----------------------------------------------------------------------------------

 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,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游戏的精彩文章,请查看专题: 《JavaScript经典游戏 玩不停》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
实现JavaScript中继承的三种方式
Oct 16 Javascript
JScript 脚本实现文件下载 一般用于下载木马
Oct 29 Javascript
jQuery动画效果animate和scrollTop结合使用实例
Apr 02 Javascript
JS实现仿中关村论坛评分后弹出提示效果的方法
Feb 23 Javascript
JS获取及设置TextArea或input文本框选择文本位置的方法
Mar 24 Javascript
详细分析JavaScript函数定义
Jul 16 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
Aug 08 Javascript
微信小程序侧边栏滑动特效(左右滑动)
Jan 23 Javascript
微信小程序开发之路由切换页面重定向问题
Sep 18 Javascript
jquery无缝图片轮播组件封装
Nov 25 jQuery
vue中$refs, $emit, $on, $once, $off的使用详解
May 26 Javascript
javascript History对象原理解析
Feb 17 Javascript
Vue中点击active并第一个默认选中功能的实现
Feb 24 #Javascript
如何在JavaScript中创建具有多个空格的字符串?
Feb 23 #Javascript
浅谈TypeScript的类型保护机制
Feb 23 #Javascript
原生javascript制作的拼图游戏实现方法详解
Feb 23 #Javascript
原生javascript运动函数的封装示例【匀速、抛物线、多属性的运动等】
Feb 23 #Javascript
es6中Promise 对象基本功能与用法实例分析
Feb 23 #Javascript
原生JavaScript之es6中Class的用法分析
Feb 23 #Javascript
You might like
php面向对象全攻略 (二) 实例化对象 使用对象成员
2009/09/30 PHP
php教程 插件机制在PHP中实现方案
2012/11/02 PHP
setcookie中Cannot modify header information-headers already sent by错误的解决方法详解
2013/05/08 PHP
PHP中list()函数用法实例简析
2016/01/08 PHP
CI操作cookie的方法分析(基于helper类库)
2016/03/28 PHP
PHP查询大量数据内存耗尽问题的解决方法
2016/10/28 PHP
理解Javascript_07_理解instanceof实现原理
2010/10/15 Javascript
jquery为页面增加快捷键示例
2014/01/31 Javascript
Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
2014/06/24 Javascript
javascript正则表达式中的replace方法详解
2015/04/20 Javascript
AngularJS ngModel实现指令与输入直接的数据通信
2016/09/21 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
2016/12/06 Javascript
Vue.js系列之项目结构说明(2)
2017/01/03 Javascript
JS实现的简单图片切换功能示例【测试可用】
2017/02/14 Javascript
jQuery实现遍历复选框的方法示例
2017/03/06 Javascript
AngularJS点击添加样式、点击变色设置的实例代码
2017/07/27 Javascript
bootstrap 通过加减按钮实现输入框组功能
2017/11/15 Javascript
页面内锚点定位及跳转方法总结(推荐)
2019/04/24 Javascript
不刷新网页就能链接新的js文件方法总结
2020/03/01 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
2020/07/30 Javascript
[54:28]EG vs OG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
django文档学习之applications使用详解
2018/01/29 Python
PyTorch快速搭建神经网络及其保存提取方法详解
2018/04/28 Python
python3 kmp 字符串匹配的方法
2018/07/07 Python
Python3 mmap内存映射文件示例解析
2020/03/23 Python
英国马莎百货印度官网:Marks & Spencer印度
2020/10/08 全球购物
会计师事务所审计实习自我鉴定
2013/09/20 职场文书
会议活动邀请函
2014/01/27 职场文书
团队队名口号大全
2014/06/06 职场文书
学校实习推荐信
2015/03/27 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
2015年秘书个人工作总结
2015/04/25 职场文书
2016年党员公开承诺书格式范文
2016/03/24 职场文书
python爬虫请求库httpx和parsel解析库的使用测评
2021/05/10 Python
MongoDB 常用的crud操作语句
2021/06/20 MongoDB
python获取字符串中的email
2022/03/31 Python