首页 > 解决方案 > 为什么AI在追逐/奔跑时会振动

问题描述

    //let meow=meowmeow
     let cell = []    
     let Xgrid = 200;
     let Ygrid = 150;
     let cpu = [];
     let CPUteam = 2;
     let AIdist = [];
     let Cpudist = [];
     let Cpudist2 = [];
     let lost = false;
     function setup() {
       smooth();
       frameRate(999)
       createCanvas(600, 450);
     }
    
     function draw() {
       Newcelltimer++;
       let cellDist = [];
       let cpuDist = [];
       if (lost) {
         background(0)
       } else {
         background(220);
    
         translate(200,150)
         scale(0.9)
         if (Newcelltimer == 1 ) {
           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++;
         }
           if (Newcelltimer == 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)))
    
           cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
             ceil(random(0 - Ygrid, 2 * Ygrid)))
           CPUteam++;
         }   
         
        
        for (let j = 0; j < (cpu.length / 4); j++) {
    
           if (cpu[j*4+2]>200) {
             lost = true;
           }
           
           let cpuDist = [];
    //Constrains the AI in the Canvas
--------------------------------------------
           if (cpu[j * 4] > (2 * Xgrid) - (cpu[j * 4 + 2] / 2)) {
             cpu[j * 4] = (2 * Xgrid) - (cpu[j * 4 + 2] / 2)
           }
    
           if (cpu[j * 4] < (-Xgrid) + (cpu[j * 4 + 2] / 2)) {
             cpu[j * 4] = (-Xgrid) + (cpu[j * 4 + 2] / 2);
           }
    
           if (cpu[j * 4 + 1] > (2 * Ygrid) - (cpu[j * 4 + 2] / 2)) {
             cpu[j * 4 + 1] = (2 * Ygrid) - (cpu[j * 4 + 2] / 2);
           }
    
           if (cpu[j * 4 + 1] < (-Ygrid) + (cpu[j * 4 + 2] / 2)) {
             cpu[j * 4 + 1] = (-Ygrid) + (cpu[j * 4 + 2] / 2)
           }
---------------------------------------------------------------------
           for (let m = 0; m < cpu.length / 4; m++) {
             if (m != j) {
               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/2 >= distant) {
                   if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
                     cpu[m * 4 + 2] += cpu[j * 4 + 2]
                     cpu.splice(j * 4, 4)
                   } else if(cpu[j*4+2]>cpu[m*4+2]) {
                     cpu[j * 4 + 2] += cpu[m * 4 + 2]
                     cpu.splice(m * 4, 4)
                   } //Else
                 } //If
                 else {
                   cpuDist.push(distant);
                 } //Else
               } //If
             } //If
           } //For
           //Finds the Closest CPU's index value
    -------------------------------------------------
           let ClosestCpu = round(min(cpuDist));
           let ClosestCpupos;
    
           for (var q = 0; q < cpu.length / 4; q++) {
             if (ClosestCpu == round(int(dist(cpu[q * 4], cpu[q * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])))) {
               ClosestCpupos = q;
               break;
             }
           }
   ---------------------------------------------------

    //Checks if AI ate a 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 cell is NOT eaten, pushes the distance between AI and cell into an array
               cellDist.push(dis)
             }
           }
        --------------------------------------------------

    //Find the closest Cell's index value
    -------------------------------------
           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;
             }
           }
        --------------------------------------
           
Checks if the closest AI is close enough to either chase or run away from it.
    -------------------------------------

      if (Cpudist[j]) {
      Cpudist[j] = dist(cpu[ClosestCpupos * 4], cpu[ClosestCpupos * 4 + 1], cpu[j*4], cpu[j*4+1]) < 250 &&  cpu[ClosestCpupos*4+2] < cpu[j * 4 + 2];
    } else {
      Cpudist[j] = dist(cpu[j * 4], cpu[j * 4 + 1], cpu[ClosestCpupos*4],cpu[ClosestCpupos*4+1]) < 200 && cpu[ClosestCpupos*4+2] < cpu[j * 4 + 2];
    }     
             if (Cpudist2[j]) {
      Cpudist2[j] = dist(cpu[ClosestCpupos * 4], cpu[ClosestCpupos * 4 + 1], cpu[j*4], cpu[j*4+1]) < 250 &&  cpu[ClosestCpupos*4+2] > cpu[j * 4 + 2];
    } else {
      Cpudist2[j] = dist(cpu[j * 4], cpu[j * 4 + 1], cpu[ClosestCpupos*4],cpu[ClosestCpupos*4+1]) < 200 && cpu[ClosestCpupos*4+2] > cpu[j * 4 + 2];
    }  
    -------------------------------------

  let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 20000) / 2000;                        
  

//Moves the AI in the following way: If the closest AI is less than an arbitrary 250 then you run, if not, check if the closest cell is less than another arbitrary 250, then you chase the cell. Otherways, you use noise values to move (I deleted that because it was quite repetitive) 
     if (Cpudist2[j]) {
       //Run        
       
          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 = 250/abs(higherVal);
             
             distXpos*=MultVal;
             distYpos*=MultVal;
             
             distXpos = map(distXpos, -250, 250, -1, 1);
             distYpos = map(distYpos, -250, 250, -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])<250&&cpu[ClosestCpupos*4+2]<cpu[j*4+2]) {
             //Chase
             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 = 250/abs(higherVal);
             
             distXpos*=MultVal;
             distYpos*=MultVal;
             
             distXpos = map(distXpos, -250, 250, -1, 1);
             distYpos = map(distYpos, -250, 250, -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]) < 250) {
             
             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 = 250/abs(higherVal);
             
             distXpos*=MultVal;
             distYpos*=MultVal;
    
             distXpos = map(distXpos, -250, 250, -1, 1);
             distYpos = map(distYpos, -250, 250, -1, 1);
             cpu[j * 4] += distXpos * amp;
             cpu[j * 4 + 1] += distYpos * amp;
           }
           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])
           }
         }
       }
Displays the cells on the canvas
       for (let k = 0; k < cell.length / 2; k++) {
    
         fill(0, 255, 255, 100)
         circle(cell[k * 2], cell[k * 2 + 1], 7)
       }
     }

只是想提一下,这是为了在 AI 中进行调试,因为我的 OTHER 程序和我的 OTHER程序在某种程度上基于agar.io。

标签: javascriptp5.js

解决方案


您应该真正使用对象。您的两个 cpu 的示例数组将是这样的:


cpu = [
  {
    x: 100,
    y: 150,
    size: 25,
    team: 3
  },
  {
    x: 250,
    y: 600,
    size: 15,
    team: 4
  }
]

然后你可以简单地通过一个循环cpu,并访问每个 cpu 的属性,如下所示:

for (let ai of cpu) {
  circle(ai.x, ai.y, ai.size)
}

这不会太难实现,只需使用查找和替换。

对于您的实际问题,我无法像julien.giband在他们的评论中所说的那样运行您的代码。但是,我认为问题在于您只是在逃避最近的单个 CPU。与您之前的问题类似,振动是行为变化过快的结果。

为了说明这一点,假设您在一维中有 3 个 CPU。将它们的位置设置为 0、49 和 100。让中间的尺寸为 10,外部的尺寸为 20。我只是假设较小的每帧移动 3 个像素,较大的每帧移动 1 个像素框架。以下是他们的进展情况:

  1. (0, 49, 100)
    • 离左49,离右51,向右移动
  2. (1, 52, 99)
    • 离左51,离右47,左移
  3. (2, 49, 98)
    • 离左47,离右49,向右移动
  4. (3, 52, 97)
    • 离左49,离右45,左移
  5. (4, 49, 96)
    • 离左45,离右47,向右移动
  6. (5, 52, 95)
    • 等等,你明白了

你看到中间那个是如何振动的吗?这就是您的代码中发生的事情。如果您想解决此问题,您可以执行julien.giband建议的建议之一。

如果你想避开多个 CPU,我建议给每个 CPU 一个正在追逐它的 CPU 的列表。我不会尝试使用您的数组格式来解决它,但这是 CPU 作为对象的样子:

single_cpu = {
  x: 100,
  y: 150,
  size: 25,
  team: 3,
  chased_by: [1, 2]
}

您可以动态更改chased_by列表,类似于您Cpudist[j]在当前版本中的更改方式。它可能看起来像这样(在j循环内部):

for (let i; i < cpu.length; i++) {
  chase_index = cpu[j].chased_by.indexOf(i);
  if (chase_index == -1) { // if i is not in the list of cpus currently chasing j
    if (dist(cpu[i].x, cpu[i].y, cpu[j].x, cpu[j].y) < 200 &&
        cpu[i].team %2 != cpu[j].team %2 &&
        cpu[i].size > cpu[j].size) { // if i is bigger, on the other team, and within 200 of j
      cpu[j].chased_by.push(i); // add i to the list of cpus currently chasing j
    }
  } else { // if i is in the list
    if (dist(cpu[i].x, cpu[i].y, cpu[j].x, cpu[j].y) > 250 || 
        cpu[i].size < cpu[j].size) { // if i is smaller than or more than 250 away from j
      cpu[j].chased_by.splice(chase_index, 1); // remove i from the list
    }
  }
}

然后当你计算如何逃跑时,你会从你逃跑的所有 CPU 的平均位置逃跑。你必须做一些额外的事情才能同时逃离播放器和多个 CPU。


推荐阅读