为什么AI在移动时会振动

Why is the AI vibrating when it moves

let playerX;
let playerY;
let playerSize = 15;
let playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
let Newcelltimer = 0;
let cell = []
let zoom = 1;
let n = 0;
let Xgrid = 600;
let Ygrid = 600;
let cpu = [];
let x = 0;
let y = 10;
let OffSetX = [];
let OffSetY = [];
let CPUteam = 2;

function setup() {
  smooth();
  frameRate(999)
  createCanvas(600, 450);
  playerX = 500;
  playerY = 100;

}

function draw() {
  let cellDist = [];
  let cpuDist = [];
  background(220);
  push();
  //Changes the FOV depending on your size
  let Newzoom = 10 / playerSize
  let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
  Newzoom = lerp(zoom, Newzoom, 0.3)
  translate(Xgrid / 2, Ygrid / 2 - 50);
  scale(newnewZoom)
  translate(-playerX, -playerY);

  // Player's speed
  playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
  Newcelltimer++;

  //Adds in new cells
  if (Newcelltimer % 40 == 0) {
    cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
    ceil(random(0 - Ygrid, 2 * Ygrid)))
  }
  //Adds in new AI's
  if (Newcelltimer % 200 == 0) {
    cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
    OffSetX.push(ceil(random(0, 1000000)))
    OffSetY.push(ceil(random(1000000, 2000000)))
    CPUteam++;
  }
  //Creates AI when you start playing
  if (Newcelltimer == 1 || Newcelltimer == 2) {
    cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
    OffSetX.push(ceil(random(0, 1000000)))
    OffSetY.push(ceil(random(1000000, 2000000)))

    cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
    ceil(random(0 - Ygrid, 2 * Ygrid)))
    CPUteam++;
  }
  //Checks if cell is eaten
  for (let i = 0; i < cell.length / 2; i++) {
    let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
    if (d <= playerSize / 2) {
      playerSize += 5;
      cell.splice(i * 2, 2)
      celliseaten = true;
    }
    else{
      fill(0,255,255,180);
      circle(i*2,i*2+1,8);
    }
  }
  //The cells disappear after a bit
  if (Newcelltimer % 200 == 0) {
    cell.splice(0, 2)
  }

  //Everything to do with the AI system
  for (let j = 0; j < (cpu.length / 4); j++) {

    let cpuDist = [];

    let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY)) //Distance between AI and player
    if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
      playerSize += floor(cpu[j * 4 + 2]);
      cpu.splice(j * 4, 4)
    }
    else if(distance<=cpu[j*4+2]/2&&cpu[j*4+2]<playerSize)
    {
    //You lose
    }
    //Checks if AI ate AI
    for (let m = 0; m < cpu.length / 4; m++) {
      //Makes sure the AI's isn't the AI in the "j" loop
      if (m != j) {
        //Checks if the Ai's are on the same team
        if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {

          distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
          let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2];

          if (higher > distant) {
            if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
              cpu[m * 4 + 2] += cpu[j * 4 + 2]
              cpu.splice(j * 4, 4)
            } else {
              cpu[j * 4 + 2] += cpu[m * 4 + 2]
              cpu.splice(m * 4, 4)
            } //Else
          } //If
          //If AI didn't eat another AI, return the distance
          else {
            cpuDist.push(distant);
          } //Else
        } //If
      } //If
    } //For

    let ClosestCpu = min(cpuDist);
    let ClosestCpupos;
    //Index value of the closest cpu (NOT WORKINGS)
    for (var q = 0; q < cpu.length / 4; q++) {
      if (ClosestCpu == int(dist(cpu[q * 4], cpu[q * 4 + 1], cpu[j * 4], cpu[j * 4 + 1]))) {
        ClosestCpupos = q;
        break;
      }
    }
    //Checks if AI ate cell
    for (let n = 0; n < cell.length / 2; n++) {
      let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
      if (dis <= cpu[j * 4 + 2] / 2) {
        cpu[j * 4 + 2] += 5;
        cell.splice(n * 2, 2)
      } else {
        //If it didn't eat the cell, does the same idea with the AI from before
        cellDist.push(dis)
      }
    }
    let ClosestCell = min(cellDist);
    let ClosestCellpos;
    for (let r = 0; r < cell.length / 2; r++) {
      if (ClosestCell == int(dist(cell[r * 2], cell[r * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))) {
        ClosestCellpos = r;
        break;
      }
    }
    //AI sppeed
    let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 70000) / 7000;

    if (dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) < 150 && playerSize > cpu[j * 4 + 2]) {

      let distXpos = cpu[j * 4]-playerX;
      let distYpos = cpu[j * 4 + 1]-playerY;

      let higherVal = (abs(distXpos) > abs(distYpos)) ? distXpos : distYpos;

      let MultVal = 150/abs(higherVal);

      distXpos*=MultVal;
      distYpos*=MultVal;

      distXpos = map(distXpos, -150, 150, -1, 1);
      distYpos = map(distYpos, -150, 150, -1, 1);
      cpu[j * 4] += distXpos * amp;
      cpu[j * 4 + 1] += distYpos * amp;
    } else if (dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) < 150 && playerSize < cpu[j * 4 + 2]) {
      let distXpos = cpu[j * 4]-playerX;
      let distYpos = cpu[j * 4 + 1]-playerY;

      let higherVal = (abs(distXpos) > abs(distYpos)) ? distXpos : distYpos;

      let MultVal = 150/abs(higherVal);

      distXpos*=MultVal;
      distYpos*=MultVal;

      distXpos = map(distXpos, -150, 150, -1, 1);
      distYpos = map(distYpos, -150, 150, -1, 1);
      cpu[j * 4] -= distXpos * amp;
      cpu[j * 4 + 1] -= distYpos * amp; 
    } 
    else if (dist(cpu[ClosestCpupos * 4], cpu[ClosestCpupos * 4 + 1], cpu[j * 4], cpu[j * 4 + 1]) < 150 && cpu[j * 4 + 2] > cpu[ClosestCpupos * 4 + 2]) {

      let distXpos = cpu[ClosestCpupos * 4] - cpu[j * 4];
      let distYpos = cpu[ClosestCpupos * 4 + 1] - cpu[j * 4 + 1];

      let higherVal = (abs(distXpos) > abs(distYpos)) ? distXpos : distYpos;

      let MultVal = 150/abs(higherVal);

      distXpos*=MultVal;
      distYpos*=MultVal;

      distXpos = map(distXpos, -150, 150, -1, 1);
      distYpos = map(distYpos, -150, 150, -1, 1);
      cpu[j * 4] += distXpos * amp;
      cpu[j * 4 + 1] += distYpos * amp;
    } else if (dist(cpu[ClosestCpupos * 4], cpu[ClosestCpupos * 4 + 1], cpu[j * 4], cpu[j * 4 + 1]) < 150 && cpu[j * 4 + 2] > cpu[ClosestCpupos * 4 + 2]) {

      let distXpos = cpu[ClosestCpupos * 4] - cpu[j * 4];
      let distYpos = cpu[ClosestCpupos * 4 + 1] - cpu[j * 4 + 1];

      let higherVal = (abs(distXpos) > abs(distYpos)) ? distXpos : distYpos;

      let MultVal = 150/abs(higherVal);

      distXpos*=MultVal;
      distYpos*=MultVal;

      distXpos = map(distXpos, -150, 150, -1, 1);
      distYpos = map(distYpos, -150, 150, -1, 1);
      cpu[j * 4] -= distXpos * amp;
      cpu[j * 4 + 1] -= distYpos * amp;
    } else if (dist(cell[ClosestCellpos * 2], cell[ClosestCellpos * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]) < 150) {

      let distXpos = cell[ClosestCellpos * 2] - cpu[j * 4];
      let distYpos = cell[ClosestCellpos * 2 + 1] - cpu[j * 4 + 1];

      let higherVal = (abs(distXpos) > abs(distYpos)) ? distXpos : distYpos;

      let MultVal = 150/abs(higherVal);

      distXpos*=MultVal;
      distYpos*=MultVal;

      distXpos = map(distXpos, -150, 150, -1, 1);
      distYpos = map(distYpos, -150, 150, -1, 1);
      cpu[j * 4] += distXpos * amp;
      cpu[j * 4 + 1] += distYpos * amp;
    } else {
      x += 0.003;
      y += 0.003;
      let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
      let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
      cpu[j * 4] += offsetX;
      cpu[j * 4 + 1] += offsetY;
    }
    if (cpu[j * 4 + 3] % 2 == 0) {
      fill(0, 0, 255)
      circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
    } else {
      fill(255, 0, 0)
      circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
    } // Else
  } //Cpu for


  //Draws player
  fill(255, 255, 0)
  circle(playerX, playerY, playerSize)
  pop();
}

问题是玩家在追AI的时候,AI在运行ning的时候,AI在运行ning的时候在震动。此外, closestCpupos 由于某种原因未定义,这不是我的问题,我稍后会修复或问另一个问题,后者可能就是这种情况。我已经输入了很多代码,所以我对大多数内容都发表了评论。问题可能出在 for(var j = 0;j<cpu.length/4;j++) 循环中的某处。也不确定这段代码是否会 运行 在 snipper 中,我可能删除了一些不会在代码段工具中 运行 的东西,并且代码有太多的嵌套循环。

这是因为 AI 比玩家移动得更快、更有效率。假设 CPU 每帧移动 3 个像素,玩家移动 1 个像素。现在考虑以下内容:

  • CPU 距离玩家 149 像素,因此它向远离玩家的方向移动 3 个像素,而玩家向 CPU
  • 方向移动 1 个像素
  • 下一帧:CPU 距离 151 像素,因此它恢复到正常行为。
  • 下一帧:玩家靠得近了,恢复到被追赶状态
  • 重复

这种状态之间的交替是导致您看到的振动的原因。你如何解决这个问题?一种解决方案是给每个 CPU 一个布尔值以供追逐。当 CPU 距离玩家 150 以内时,您可以将其设置为 true,然后在距离玩家 200 时将其设置回 false。这样,它就不会振荡,因为它需要移动 50 个像素才能改变行为。为此,您需要将 j * 4 的所有实例更改为 j * 5 并为 cpu[j * 5 + 4] 提供初始布尔值。这是我的测试解决方案:

if (cpu[j * 5 + 4]) {//if currently running away
  //continue running away if smallerthan player and still within 200
  cpu[j * 5 + 4] = dist(cpu[j * 5], cpu[j * 5 + 1], playerX, playerY) < 200 && 
                   playerSize > cpu[j * 5 + 2];
} else {//if not currently running away
  //start running away if smaller than player and within 150
  cpu[j * 5 + 4] = dist(cpu[j * 5], cpu[j * 5 + 1], playerX, playerY) < 150 && 
                   playerSize > cpu[j * 5 + 2];
}
if (cpu[j * 5 + 4]) {
  //your running away code...
}//...

高度鼓励您使用classes。如果你为你的 CPU 制作一个 class,你可以为你想做的每件事制作一个方法。然后你可以有一个 CPU 数组并遍历它,做你需要它做的所有事情。它只是让代码更有条理。