Javascript 优化阵列更新和性能

Javascript 优化阵列更新和性能,javascript,performance,oop,Javascript,Performance,Oop,我正在尝试创建一个RPG游戏。但我想应该有很多优化。最大的问题之一是性能。我用for循环更新了一个数组来设置新的块,但这需要花费太长的时间。我认为我也应该使用OOP来获得更好的性能,但是应该如何实现呢 希望你能帮助我,对不起我的英语:) Javascript: var keyCode = {}; var player = document.getElementsByClassName("player")[0]; var div = document.getElementsByTagName("d

我正在尝试创建一个RPG游戏。但我想应该有很多优化。最大的问题之一是性能。我用for循环更新了一个数组来设置新的块,但这需要花费太长的时间。我认为我也应该使用OOP来获得更好的性能,但是应该如何实现呢

希望你能帮助我,对不起我的英语:)

Javascript:

var keyCode = {};
var player = document.getElementsByClassName("player")[0];
var div = document.getElementsByTagName("div")[0];
var iGrass = document.querySelectorAll(".interface > .grass")[0];
var iWater = document.querySelectorAll(".interface > .water")[0];
var iWall = document.querySelectorAll(".interface > .wall")[0];
var setEle = iWall;
var xPos = player.offsetWidth;
var yPos = player.offsetWidth;
var speed = 20;
var currentxPos;
var currentyPos;
var field = [];
field[0] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
field[1] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[2] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[3] = [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[4] = [1, 0, 0, 0, 0, "g", "g", 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[5] = [1, 0, 0, 0, "g", "g", "g", "g", 0, 0, 0, 0, 0, 0, 0, 1];
field[6] = [1, 0, 0, 0, "g", "g", "g", "g", 0, 0, 0, 0, 0, 0, 0, 1];
field[7] = [1, 0, 0, 0, 0, "g", "g", 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[8] = [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1];
field[9] = [1, 0, 0, 0, 0, 0, 0, 0, "w", "w", "w", 1, 0, 0, 0, 1];
field[10] = [1, 0, 0, 0, 0, 0, 0, 0, "w", "w", "w", 1, 0, 0, 0, 1];
field[11] = [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1];
field[12] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[13] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[14] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[15] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
field[16] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];

function setStage() {
  for (y = 0; y < field.length; y++) {
    for (x = 0; x < field[y].length; x++) {
      if (field[y][x] == 1) {
        div.innerHTML = div.innerHTML + "<span class='wall'></span>";
      } else if (field[y][x] == "w") {
        div.innerHTML = div.innerHTML + "<span class='water'></span>";
      } else if (field[y][x] == "g") {
        div.innerHTML = div.innerHTML + "<span class='grass'></span>";
      } else {
        div.innerHTML = div.innerHTML + "<span></span>";
      }
    }
  }

  for (var i = 0; i < document.querySelectorAll('span').length; i++) {
    document.querySelectorAll("span")[i].style.width = player.offsetWidth + "px";
    document.querySelectorAll("span")[i].style.height = player.offsetWidth + "px";
  }
}
setStage();
div.style.width = field[0].length * player.offsetWidth + "px";

document.addEventListener("keydown", function(e) {
  keyCode[e.which || e.keyCode] = true;
  e.preventDefault();
});
document.addEventListener("keyup", function(e) {
  keyCode[e.which || e.keyCode] = false;
});

function playerMovement() {
  currentxPos = parseInt(xPos / player.offsetWidth);
  currentyPos = parseInt(yPos / player.offsetWidth);
  if (field[currentyPos][currentxPos] == "w") {
    speed = 1;
    player.style.transition = "0.4s all";
  } else {
    speed = 5;
    player.style.transition = "0.2s all";
  }
  /*Left*/
  if (keyCode[65] && xPos > 0) {
    if (field[currentyPos][currentxPos - 1] != 1) {
      xPos -= speed;
    } else {
      xPos = currentxPos * player.offsetWidth;
    }
  }
  /*Right*/
  if (keyCode[68] && xPos < div.offsetWidth - player.offsetWidth) {
    if (field[currentyPos][currentxPos + 1] != 1) {
      xPos += speed;
    } else {
      xPos = currentxPos * player.offsetWidth;
    }
  }
  /*Bottom*/
  if (keyCode[83]) {
    if (field[currentyPos + 1][currentxPos] != 1) {
      yPos += speed;
    } else {
      yPos = currentyPos * player.offsetWidth;
    }
  }
  /*Top*/
  if (keyCode[87] && yPos > 1) {
    if (field[currentyPos - 1][currentxPos] != 1) {
      yPos -= speed;
    } else {
      yPos = currentyPos * player.offsetWidth;
    }
  }
  /*Space*/
  if (keyCode[32]) {
    player.style.background = "#f00";
    if (field[currentyPos][currentxPos] == "g") {
      field[currentyPos][currentxPos] = 0;
      div.innerHTML = "";
      setStage();
    }
  } else {
    player.style.background = "#66f";
  }
  player.style.left = (currentxPos * player.offsetWidth) + "px";
  player.style.top = (currentyPos * player.offsetWidth) + "px";
}
iWall.addEventListener("click", function() {
  setEle = iWall;
});
iGrass.addEventListener("click", function() {
  setEle = iGrass;
});
iWater.addEventListener("click", function() {
  setEle = iWater;
});
div.addEventListener("click", function(e) {

  var setXpos = parseInt(e.x / player.offsetWidth);
  var setYpos = parseInt(e.y / player.offsetWidth);
  if (setEle == iWall) {
    field[setYpos][setXpos] = 1;
  } else if (setEle == iGrass) {
    field[setYpos][setXpos] = "g";
  } else if (setEle == iWater) {
    field[setYpos][setXpos] = "w";
  } else {
    field[setYpos][setXpos] = 0;
  }
  div.innerHTML = "";
  setStage();
});
setInterval(function() {
  playerMovement();
}, 10);
*演示:

为什么不尝试只替换选定的块,而不是解析player DIV的全部内容。只需将id添加到:

div.innerHTML = div.innerHTML + "<span class='wall' id='cell-"+y+"-"+x+"'></span>";
      } else if (field[y][x] == "w") {
        div.innerHTML = div.innerHTML + "<span class='water' id='cell-"+y+"-"+x+"'></span>";
      } else if (field[y][x] == "g") {
        div.innerHTML = div.innerHTML + "<span class='grass' id='cell-"+y+"-"+x+"'></span>";
      } else {
        div.innerHTML = div.innerHTML + "<span id='cell-"+y+"-"+x+"'></span>";
修正点击空间按钮

 if (keyCode[32]) {
    player.style.background = "#f00";
    if (field[currentyPos][currentxPos] == "g") {
      field[currentyPos][currentxPos] = 0;
      var selectedEl = document.getElementById('cell-'+currentyPos+'-'+currentxPos);
      var whiteSpace = document.createElement('span');
      whiteSpace.setAttribute('id', 'cell-' +currentyPos+'-'+currentxPos);
      whiteSpace.style.width = '20px';
      whiteSpace.style.height = '20px';
      selectedEl.replaceWith(whiteSpace);
    }

这里的示例

OOP不能保证更好的性能。主要问题是,每次都要更新整个网格,这导致html解析器很忙。这就是reactJS如此出名的原因。所以你们可以只听更改…是的,我试着只在点击和文档开始时启动。但正如我所看到的,它仍然太消耗性能。我应该如何优化steStage方法?T.T.当然,你可以使用画布来创建你的游戏。这将避免您在每次发生操作/更改时都操纵DOM。是的,我知道canvas可能是一个解决方案。但我尝试基于纯html和javascript创建它:)我想稍后将此代码用作android应用程序。这就是我想要避免使用画布的原因,也是我追求性能的原因:)哦,这是一个巨大的差异:D它几乎完美。唯一的问题是,通过单击空格,网格元素以一种奇怪的方式克隆。(空格用于修剪“草”)。这样,您可以放置数据属性,例如
data type=“white Space”
,并在
replacetwith
函数之前检查其值,然后执行所需操作。我添加ID的方式唯一的问题是点击时会有一个回调,但我需要让他们明白,按键时应该被替换^^^^但现在我有了一个很好的基础来进一步:我已经编辑了我的答案,也许它会帮助你更多。更好,但现在你只能在草地上构建:D它只需要type==='whiteSpace'仍然有一些bug,但现在我可以使用它并修复bug。谢谢你,约丹:D
div.innerHTML = div.innerHTML + "<span class='wall' id='cell-"+y+"-"+x+"'></span>";
      } else if (field[y][x] == "w") {
        div.innerHTML = div.innerHTML + "<span class='water' id='cell-"+y+"-"+x+"'></span>";
      } else if (field[y][x] == "g") {
        div.innerHTML = div.innerHTML + "<span class='grass' id='cell-"+y+"-"+x+"'></span>";
      } else {
        div.innerHTML = div.innerHTML + "<span id='cell-"+y+"-"+x+"'></span>";
div.addEventListener("click", function(e) {

   .....
   // div.innerHTML = "";
   // setStage();       
    document.getElementById(e.target.getAttribute('id')).replaceWith(setEle.cloneNode())
});
 if (keyCode[32]) {
    player.style.background = "#f00";
    if (field[currentyPos][currentxPos] == "g") {
      field[currentyPos][currentxPos] = 0;
      var selectedEl = document.getElementById('cell-'+currentyPos+'-'+currentxPos);
      var whiteSpace = document.createElement('span');
      whiteSpace.setAttribute('id', 'cell-' +currentyPos+'-'+currentxPos);
      whiteSpace.style.width = '20px';
      whiteSpace.style.height = '20px';
      selectedEl.replaceWith(whiteSpace);
    }