js实现坦克大战游戏

本文实例为大家分享了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>

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

(0)

相关推荐

  • 使用 TypeScript 重新编写的 JavaScript 坦克大战游戏代码

    源码下载 源码我已经上传到 CSDN 了,无需资源分,下载地址:http://download.csdn.net/detail/zgynhqf/8565873. 源码使用 VS 2013 +TypeScript 1.4 进行开发.打开后,显示如下图: JsTankGame 1.0:老的使用 JS 编写的坦克游戏. JsTankGame 2.0:新的使用 TS 直接翻译过来的游戏. JsTankGame:在 2.0 的基础上,对类型进行了重构后的新游戏. 重构步骤 由于老的 JS 游戏是采用 MS

  • javascript 模拟坦克大战游戏(html5版)附源码下载

    一.总结关键点和遇到的问题 1.javascript中的继承,最好父类只提供方法共享,属性写到各自子类中,避免父类和子类的构造函数混杂. 2.prototype模拟继承的代码,应写在所有方法定义之前,否则原型对象被改变,方法就变成了未定义,如: 复制代码 代码如下: Hero.prototype = new Tank (0, 0, 0); Hero.prototype.constructor = Hero; Hero.prototype.addLife = function(){ this.li

  • javascript制作坦克大战全纪录(2)

    2.   完善地图 我们的地图中有空地,墙,钢,草丛,水,总部等障碍物. 我们可以把这些全部设计为对象. 2.1  创建障碍物对象群 对象群保存各种地图上的对象,我们通过对象的属性来判断对象是否可以被穿过或被攻击.   Barrier.js: 复制代码 代码如下: // 障碍物基类对象,继承自TankObject  Barrier = function () {      this.DefenVal = 1;  // 防御力      this.CanBeAttacked = true;  //

  • javascript制作坦克大战全纪录(1)

    PS:这个坦克大战是在网上下的一段源码之后,自己进行的重写.本身没有太难的东西,这个案例将js面向对象用的比较好,可以作为js面向对象的入门教程. 1.   创建基本对象,实现坦克简单的移动 1.1    如何在地图中绘制画布? 考虑到浏览器兼容的问题,我们用操作dom的方式来实现游戏对象的绘制和刷新.我们如何存储我们的地图呢? 我们应该把地图用一个二维数组来保存, js中没有二维数组,但是可以通过在一维数组从存储数组来实现. 1.2    代码实现 我们将画布设计为 13 * 13 的一个二维

  • javascript 制作坦克大战游戏初步 图片与代码

    学了一阵子的javascript,该做点东西,虽然东西还是东拼西凑,见笑.方向键控制坦克移动,回车键发射炸弹.其他的功能敌方坦克那些还没写. javascript坦克游戏初步|阿会楠练习作品 body{ background:black; } #tanke{ position:absolute; left:500px; top:200px; } var i = 0; var bombLeftArray = new Array(100);//存放炸弹信息x var bombTopArray = n

  • js实现坦克大战游戏

    本文实例为大家分享了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: 39

  • Vue3+Canvas实现坦克大战游戏

    目录 前言 架构搭建 Canvas构造函数 画布绘制 文本渲染 画布重绘前的clear 核心:绘制函数 BattleCity构造函数 实现坦克的移动 坦克发射子弹的逻辑 总结 前言 记得几年前刚做前端开发的时候,跟着师傅用纯 es5 实现了这款坦克大战,可以说我入行前端是从 javaScript 小游戏开始的,时间已匆匆过去了数年,前端发展日新月异,各种新框架.新概念层出不穷,很容易就迷失在对各种新技术的盲目学习和应用中,真正的编程是什么呢?值得思考的问题. 我准备用 vue3 重新实现一下这款

  • Vue3+Canvas实现坦克大战游戏(一)

    目录 前言 架构搭建 Canvas 构造函数 画布绘制 文本渲染 画布重绘前的 clear 核心:绘制函数 BattleCity 构造函数 实现坦克的移动 坦克发射子弹的逻辑 总结 前言 记得几年前刚做前端开发的时候,跟着师傅用纯 es5 实现了这款坦克大战,可以说我入行前端是从 javaScript 小游戏开始的,时间已匆匆过去了数年,前端发展日新月异,各种新框架.新概念层出不穷,很容易就迷失在对各种新技术的盲目学习和应用中,真正的编程是什么呢?值得思考的问题. 我准备用 vue3 重新实现一

  • 经典再现 基于JAVA平台开发坦克大战游戏

    一.需求描述  1.功能性需求 在功能需求分析阶段,我们的主要任务是指定系统必须提供哪些服务,定义软件完成哪些功能,提供给那些人使用,功能需求是软件开发的一项基本需求,是需求分析必不可少的一部分.坦克大战是一款经典游戏了,本游戏学习了一些前辈们的经验,整体来说讲,游戏分为敌我双方,主要参与战斗的坦克有玩家控制,敌人坦克可以智能随机出现在屏幕上,并且移动,发射一定数量的子弹:玩家可以在规定的区域内随意移动坦克,当有子弹击中玩家时,玩家死亡,游戏结束:敌人坦克智能运行,敌方坦克由于需要具有一定智能性

  • Java版坦克大战游戏源码示例

    整理文档,搜刮出一个Java版坦克大战游戏的代码,稍微整理精简一下做下分享. package tankwar; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.File; import java.io.FileInputStream; imp

  • python使用pygame模块实现坦克大战游戏

    本文实例为大家分享了pygame模块实现坦克大战游戏的具体代码,供大家参考,具体内容如下 首先,第一步,游戏简单素材的准备. 炮弹,炮弹,坦克移动.音乐-开火素材. 其次,思路整理. 我们需要几个类,分别是玩家类,敌人类,炮弹类及地图类,开始游戏界面以及结束界面,血条等等. 开始coding. 主函数,new一个对象(java乱入emmm),声明一个对象. # encoding : utf-8 # anthor : comi from gameloop import * from pygame

  • C#实现坦克大战游戏

    本文实例为大家分享了C#实现坦克大战游戏的具体代码,供大家参考,具体内容如下 前言 该程序主要对原始的坦克大战游戏进行了简单的还原.目前程序可以做到自动生成敌方坦克且敌方能够随机发射子弹,我方坦克也能做到边发射子弹边移动.唯一的不足之处就是还没有完整通关的设置以及障碍的设置. 界面效果图 图1 部分代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; u

  • js实现飞机大战游戏

    本文实例为大家分享了js实现飞机大战游戏的具体代码,供大家参考,具体内容如下 CSS部分的代码: <style> * { margin: 0px; padding: 0px; } canvas{ border: 1px solid #000; display: block; margin: auto; } </style> JavaScript代码: <!-- 先创建一个画布 --> <canvas id="canvas" width=&quo

  • java实现坦克大战游戏

    本文实例为大家分享了java实现坦克大战游戏的具体代码,供大家参考,具体内容如下 一.实现的功能 1.游戏玩法介绍 2.自定义游戏(选择游戏难度.关卡等) 3.自定义玩家姓名 4.数据的动态显示 二.程序基本结构 三.主要的界面 1)游戏首页 2)自定义游戏页面 3)游戏介绍 4)开始游戏,自定义玩家姓名 5)游戏主页面 四.主要代码 1)数据的初始化类 public class Data { public static boolean isRestart=false; public stati

  • 基于python实现坦克大战游戏

    本文实例为大家分享了python实现坦克大战游戏的具体代码,供大家参考,具体内容如下 游戏界面 pygame游戏引擎的安装 pip安装 windows + R --> cmd --> 命令行输入 pip install 模块名==版本号 pycharm中安装 File --> setting --> Project --> Project Interpreter --> 右侧 + install --> 搜索框输入pygame --> 下方 installP

随机推荐