Javascript 是什么导致我的AI在地图上找到随机点而不选择真实目标? 背景

Javascript 是什么导致我的AI在地图上找到随机点而不选择真实目标? 背景,javascript,debugging,artificial-intelligence,Javascript,Debugging,Artificial Intelligence,我正在写一个具有基本目标和运动的AI。有两种类型的“生物”:活跃的动物群,以及不活跃的目标植物群 问题 我的AI(附于动物群)首先针对植物群,但它只“看到”一些植物群。当人工智能看不到flora时,人工智能将旋转成圆圈,似乎随机反弹;即使还有flora残留 是什么原因导致只看到一些flora?为什么动物群在停止寻找植物群后似乎漫无目的地四处跳跃?为什么在代码运行一段时间后,fauna会结块?是什么原因导致看不到flora 如果你需要任何额外的信息,请询问 我试图修复它 我第一次尝试解决问题取得了

我正在写一个具有基本目标和运动的AI。有两种类型的“生物”:活跃的
动物群
,以及不活跃的目标
植物群

问题 我的AI(附于
动物群
)首先针对
植物群
,但它只“看到”一些
植物群
。当人工智能看不到flora时,人工智能将旋转成圆圈,似乎随机反弹;即使还有
flora
残留

是什么原因导致只看到一些
flora
?为什么
动物群
在停止寻找
植物群
后似乎漫无目的地四处跳跃?为什么在代码运行一段时间后,
fauna
会结块?是什么原因导致看不到
flora

如果你需要任何额外的信息,请询问

我试图修复它 我第一次尝试解决问题取得了一些成功,但没有完全解决问题。这就是我使用对象而不是数组重写代码的时候。一旦我这么做了,目标就成功了,但一些
动物群会没完没了地旋转

然后我意识到,生物的旋转很可能无法与getAngle函数的返回进行比较。该生物的旋转可能等同于getAngle的返回,但不会相等(例如360度~=720度,但360度!=720度)。在我修复了这个问题之后,它似乎工作了一段时间,但是当我通过更多的检查和更长的时间运行测试时,我发现了这些问题

我真的不确定什么会导致这样的问题,但我很想知道。谢谢你的帮助。:)

代码解释 该代码可在线访问:

在我的代码开始时,我有一些
对象
原型扩展,允许我使用数组之类的对象。它们大致相当于它们的
数组
对应项。我不认为这些是问题的根源,但它们是程序运行所必需的

Object.prototype.filter = function(fn) {
  let ob = this, keep = {},
      k = Object.keys(ob);

  for (let i = 0; i < k.length; i++) {
    if (fn(k[i], ob[k[i]]))
      keep[k[i]] = ob[k[i]];
  }

  return keep;
}

Object.prototype.forEach = function(fn) {
  let ob = this, k = Object.keys(ob);

  for (let i = 0; i < k.length; i++)
    fn(k[i], ob[k[i]]);
}

Object.prototype.reduce = function(test, initialValue = null) {
  let ob = this, k = Object.keys(ob),
      accumulator = initialValue || ob[k[0]],
      i = (initialValue === null) ? 1 : 0;

  for (; i < k.length; i++)
    accumulator = test(accumulator, k[i], ob[k[i]], ob);

  return accumulator;
}

现在我有了目标函数。它首先获取运行ai的生物,然后获取该生物的一个对象进行查看,然后采用当前只能找到最近的模式,最后采用过滤功能,让目标查找者只能查看flora

代码首先过滤掉那些不在人工智能视线内的。这就是我所期望的问题所在。接下来,它应用输入过滤器(这样在我的情况下,只有
flora
保留)。最后,只有当生物对象中还有剩余的生物时,代码才会将该对象减少到最近的生物。如果在生物的对象中没有任何剩余,它将返回一个未定义的数组

function getTarget(c, of, mode = `nearest`, filter) {
  let first;

  // filter so its only the ones in view
  of = of.filter((k, t) => {
    return Math.abs(getAngle(c.pos, t.pos) - c.direction) < c.viewAngle / 2;
  });

  // filter for target type; eg. only return flora
  if (filter)
    of = of.filter(filter);

  if (Object.keys(of).length) {
    first = of[Object.keys(of)[0]];

    if (mode == `nearest`) {
      return of.reduce((acc, k, cur) => {
        let dist = getDist(c.pos, cur.pos);
        if (dist < acc[0])
          return [dist, k];
        else
          return acc;
      }, [getDist(c.pos, first.pos), first]);
    }
  }
  else
    return [undefined, undefined];
}

在这里,我生成了一个对象,其中包含随机放置的
flora
flora
。我使用的ID系统使用的是
对象
,而不是和
数组
。所有生物都存储在动态全局对象中

ob = {};

for (let i = 20; i > 0; i--) {
  let id = Math.floor(Math.random() * 1000000000),
      type = (Math.random() > .2 ? `flora` : `fauna`);

  ob[id] = {
    type: type,
    pos: { x: Math.floor(Math.random() * canvas.width), y: Math.floor(Math.random() * canvas.height) },
    direction: Math.random() * 360
  }
  if (type == `fauna`) {
    ob[id].ai = findfood;
    ob[id].viewAngle = 90;
    ob[id].speed = .8;
    ob[id].turnSpeed = 1.6;
  }
}

然后,我在setInterval中运行模拟,如果生物拥有AI函数,它将调用AI函数。问题也不在这里

let fixedUpdate = setInterval(function() {
  Object.keys(ob).forEach((ck) => {
    let c = ob[ck];

    if (c && c.ai)
      c.ai.apply(c);
  });
}, 1000 / 60);

这是我用来显示它的代码。这只是基本的画布材料,所以问题肯定不在这里

let draw = () => {
  // clear canvas
  ctx.putImageData(emptyCanvas, 0, 0);

  Object.keys(ob).forEach((ck) => {

    let c = ob[ck];

    if (c.type == 'flora')
      ctx.fillStyle = '#22cc33';
    else if (c.type == 'fauna') {
      ctx.fillStyle = '#0066ee';
      ctx.beginPath();
      ctx.moveTo(c.pos.x, c.pos.y);
      // ctx.lineTo(c.pos.x + 100, c.pos.y - 50);
      // ctx.lineTo(c.pos.x + 100, c.pos.y + 50);
      ctx.lineTo(c.pos.x, c.pos.y);
      ctx.fill();
      ctx.beginPath();
      ctx.arc(c.pos.x, c.pos.y, 100, (c.direction - c.viewAngle / 2) * Math.PI / 180, (c.direction + c.viewAngle / 2) * Math.PI / 180);
      ctx.fill();
    }
    else
      ctx.fillStyle = '#424242';

    ctx.beginPath();
    ctx.arc(c.pos.x, c.pos.y, 10, 0, 2 * Math.PI);
    ctx.fill();
  });

  requestAnimationFrame(draw);
}

draw();

以下是嵌入的代码:

console.clear();
Object.prototype.filter=函数(fn){
让ob=this,keep={},
k=对象键(ob);
for(设i=0;i{
返回数学abs(getAngle(c.pos,t.pos)-c.direction){
设dist=getDist(c.pos,cur.pos);
如果(距离c.type==`flora`);
this.target=目标[1];
if(ob[this.target]){
调用(this,getAngle(this.pos,ob[this.target].pos));
if(getDist(this.pos,ob[this.target].pos)>5)
移动,呼叫(这个);
否则{
删除ob[this.target];
}
}
其他的
旋转呼叫(这个,这个,旋转速度);
}
ob={};
对于(设i=20;i>0;i--){
设id=Math.floor(Math.random()*100000000),
type=(Math.random()>.2?`flora`:`fauna`);
ob[id]={
let fixedUpdate = setInterval(function() {
  Object.keys(ob).forEach((ck) => {
    let c = ob[ck];

    if (c && c.ai)
      c.ai.apply(c);
  });
}, 1000 / 60);
let draw = () => {
  // clear canvas
  ctx.putImageData(emptyCanvas, 0, 0);

  Object.keys(ob).forEach((ck) => {

    let c = ob[ck];

    if (c.type == 'flora')
      ctx.fillStyle = '#22cc33';
    else if (c.type == 'fauna') {
      ctx.fillStyle = '#0066ee';
      ctx.beginPath();
      ctx.moveTo(c.pos.x, c.pos.y);
      // ctx.lineTo(c.pos.x + 100, c.pos.y - 50);
      // ctx.lineTo(c.pos.x + 100, c.pos.y + 50);
      ctx.lineTo(c.pos.x, c.pos.y);
      ctx.fill();
      ctx.beginPath();
      ctx.arc(c.pos.x, c.pos.y, 100, (c.direction - c.viewAngle / 2) * Math.PI / 180, (c.direction + c.viewAngle / 2) * Math.PI / 180);
      ctx.fill();
    }
    else
      ctx.fillStyle = '#424242';

    ctx.beginPath();
    ctx.arc(c.pos.x, c.pos.y, 10, 0, 2 * Math.PI);
    ctx.fill();
  });

  requestAnimationFrame(draw);
}

draw();
first = of[Object.keys(of)[0]];
first = Object.keys(of)[0];
}, [getDist(c.pos, first.pos), first]);
}, [getDist(c.pos, of[first].pos), first]);
function getTarget(c, of, mode = `nearest`, filter) {
  let first;

  // filter so its only the ones in view
  of = of.filter((k, t) => {
    return Math.abs(getAngle(c.pos, t.pos) - c.direction) < c.viewAngle / 2;
  });

  // filter for target type; eg. only return flora
  if (filter)
    of = of.filter(filter);

  if (Object.keys(of).length) {
    first = Object.keys(of)[0];

    if (mode == `nearest`) {
      return of.reduce((acc, k, cur) => {
        let dist = getDist(c.pos, cur.pos);
        if (dist < acc[0])
          return [dist, k];
        else
          return acc;
      }, [getDist(c.pos, of[first].pos), first]);
    }
  }
  else
    return [undefined, undefined];
}