【问题标题】:Game walk by path in array游戏中的路径在数组中行走
【发布时间】:2019-11-09 13:25:08
【问题描述】:

我正在编写一个算法,用于以给定的速度迭代数组的元素。我用它在我找到的路径数组中遍历游戏地图上的单元格。

我需要当使用新数组调用新函数时,最后一个函数调用停止工作。

这将用于在单击鼠标时沿路径移动。现在,如果我们调用第一个函数,它会沿着路径走,但是如果在路径结束之前,用新路径再次调用该函数,那么它们都会继续改变当前坐标。

对象必须在第一次调用函数时中断其路径,并在第二次函数调用时继续其路径。

下面是它现在如何工作的示例代码:

let coord = {x:0,y:0}
 
 let goByPath = (path=[],coord={})=>{
    let i = 0;
    pathIteration(i,path,coord)
  }

  let pathIteration = (i,path,coord)=>{

    if(i++<path.length){
      setTimeout(()=>{
        coord = path[i-1];
        console.log(coord);
        pathIteration(i,path,coord);
      },500);
    }
    return i;
  };
  
path1 = [{x:0,y:1},{x:1,y:1},{x:1,y:2},{x:2,y:2}];

path2 = [{x:1,y:3},{x:1,y:4},{x:1,y:5}];

goByPath(path1, coord);

setTimeout(()=>{
    goByPath(path2, coord);  
},900);

现在输出到控制台:

{
  "x": 0,
  "y": 1
}
{
  "x": 1,
  "y": 1
}
{
  "x": 1,
  "y": 3
}
{
  "x": 1,
  "y": 2
}
{
  "x": 1,
  "y": 4
}
{
  "x": 2,
  "y": 2
}
{
  "x": 1,
  "y": 5
}

需要的输出:

{
  "x": 0,
  "y": 1
}
{
  "x": 1,
  "y": 1
}
{
  "x": 1,
  "y": 3
}
{
  "x": 1,
  "y": 4
}
{
  "x": 1,
  "y": 5
}

【问题讨论】:

  • 我建议你用类重写它。一个具有当前坐标和当前路径的“实体”类。当路径更新时,将路径更改为新路径,并停止另一个。那会解决你的问题。
  • 如果一个新的 goByPath 被调用,你是否需要某种 CancellationToken 的假设是正确的?

标签: javascript game-development


【解决方案1】:

你只需要clearTimeouthttps://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout

let coord = { x: 0, y: 0 };

let myTimeout;

let goByPath = (path = [], coord = {}) => {
  let i = 0;
  clearTimeout(myTimeout); // stop previous calls
  pathIteration(i, path, coord);
}

let pathIteration = (i, path, coord) => {
  rect(coord);
  if (i++ < path.length) {
    myTimeout = setTimeout(() => { // store reference to timeout
      coord = path[i - 1];
      pathIteration(i, path, coord);
    }, 500);
  }
  return i;
};

/* canvas grid for display purposes */

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var n = 10;
var size = Math.min(innerWidth, innerHeight);
var u = size / n;

var draw = function() {
  size = Math.min(innerWidth, innerHeight);
  u = size / n;
  canvas.width = size;
  canvas.height = size;

  for (var y = 0; y < n; y++) {
    for (var x = 0; x < n; x++) {
      ctx.strokeStyle = '#000';
      ctx.strokeRect(x * u, y * u, u, u);
    }
  }
};
draw();
var rect = (coord) => {
  ctx.fillStyle = '#888';
  ctx.fillRect(coord.x * u, coord.y * u, u, u);
};

/* example */

var path1 = [{x:0,y:1},{x:1,y:1},{x:1,y:2},{x:2,y:2}];
goByPath(path1, coord);


var path2 = [{x:1,y:3},{x:1,y:4},{x:1,y:5}];
setTimeout(() => { goByPath(path2, coord); }, 1600);
body {
  margin: 0;
  display: grid;
  place-content: center;
}
&lt;canvas&gt;&lt;/canvas&gt;

【讨论】:

  • 感谢您的明智决定。当函数被调用时,运动被中断,如果连续多次调用,则函数保持原位。是否可以在不中断的情况下实现这一点,还是我需要寻找其他解决方案?
  • 你能分享一个codepen或摆弄你的代码,以便我搜索一个简单的解决方案吗?
【解决方案2】:

你可以有一个简单的多线程实现如下:

let coord = { x: 0, y: 0 }
let coordLock = null

let goByPath = (path = [], coord = {}) => {
  const newLock = Math.random()
  coordLock = newLock
  pathIteration(0, path, coord, newLock)
}

let pathIteration = (i, path, coord, lock) => {
  if (lock !== coordLock) return i
  if (i++ < path.length) {
    setTimeout(() => {
      coord = path[i - 1]
      console.log(coord)
      pathIteration(i, path, coord, lock)
    }, 500)
  }
  return i
}

const path1 = [{ x: 0, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 2 }, { x: 2, y: 2 }]
const path2 = [{ x: 1, y: 3 }, { x: 1, y: 4 }, { x: 1, y: 5 }]

goByPath(path1, coord)
setTimeout(() => goByPath(path2, coord), 900)

话虽如此,我认为这个实现对于这样的任务来说很弱。对于此类任务,您应该具有适当的面向对象结构。如果这个代码库增长,你肯定会在未来得到意想不到的结果 要将重要的东西更改为坐标,您不能依赖副作用和全局定义的对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-06
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多