Game walk by path in array
Asked Answered
W

2

6

I am writing an algorithm for iterating over the elements of an array at a given speed. I use this to iterate through the cells on the game map in an array of paths that I find.

I need that when a new function is called with a new array, the last function call stops working.

This will be used to move along the path, at the click of a mouse. Now, if we call the first function, it will go along the path, but if, before the end of the path, the function is called again with a new path, then both of them will continue to change the current coordinate.

The object must interrupt its path at the place it had come to when it first called the function and continue its path in the second function call.

Here is a sample code of how it works now:

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);

Output to console now:

{
  "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
}

Needed output:

{
  "x": 0,
  "y": 1
}
{
  "x": 1,
  "y": 1
}
{
  "x": 1,
  "y": 3
}
{
  "x": 1,
  "y": 4
}
{
  "x": 1,
  "y": 5
}
Walt answered 27/6, 2019 at 13:45 Comment(2)
I suggest you rewrite it using classes. One "entity" class that has the current coordinate and current path. When the path is updated change the path out for the new path, and stop the other. That would solve your problem.Untimely
Is the assumption that you want some kind of CancellationToken if a new goByPath is called right?Edana
B
3

You just need clearTimeout https://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;
}
<canvas></canvas>
Brume answered 27/6, 2019 at 14:11 Comment(2)
Thank you for the good decision. When the function is called, the movement is interrupted, if you make several calls in a row, the function is stay on place. Is it possible to implement this without interruption or do I need to look for another solution?Walt
can you share a codepen or fiddle with your code so I can search for a simple solution?Brume
M
0

You can have a simple multithreaded implementation as follows:

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)

That being said, I think this implementation is weak for such a task. You should have proper object oriented structure for such task. If this code base grows, you'll have unexpected results in future for sure To change an important thing as coordinates you can't rely on side effects and globally defined objects

Mord answered 27/6, 2019 at 14:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.