计算避开障碍物的圆角

Calculate angle to circle with avoiding obstacles

我正在为一个名为 Ogar 的项目制作一个机器人,这是一个用 Node.js 编写的 Agar.io 服务器实现。

这个机器人有一个障碍物,一个叫做病毒的绿色尖状细胞(见插图)。我需要对这个机器人进行编程以避免该障碍,但我没有运气。由于图中有很多目标,所以它是基于更新的。

这是我到现在为止得到的代码。

BotPlayer.prototype.avoidObstacles = function(cell, angle) {
    // Sum up all of the vector angles of obstacles to cell and react against it
    var angleSum = 0;
    var collided = this.collisionFromList(cell, this.obstacles);
    if (collided.length == 0) return angle; // Not to return NaN

    for (var i = 0; i < collided.length; i++) {
        angleSum += this.angle(cell.position, collided[i].position);
    }

    angleSum /= collided.length; // Average out the angle sum

    // TODO: Find closest available edge
    angleSum += Math.PI / 2;

    return angle + angleSum;
};

这在大多数情况下确实有效,但机器人有时会完全忽略障碍物(this.collisionFromList(cell, this.obstacles); 完全没问题)并最终通过它(爆炸成很多单元格)。

BotPlayer.prototype 有很多用于此类计算的有用函数。参见 this link

我不需要任何寻路争吵,只是这个简单的避让措施。

这是你的一个很大的启发式,但如果你想保持这个逻辑,那么考虑考虑到病毒的笛卡尔距离,因为你显然可以访问它们的位置。

函数为BotPlayer.prototype.getDistBotPlayer.prototype.getAccDist

您可以使用阈值 DIST_MIN 和简单的 if 或使用像 angle/distance 这样的函数(更好)来减少远处病毒对角度的影响。

对于您正在尝试做的事情,还有一种替代方法。该方法是使用吸引子来描述系统中的实体。你的 "bot" 就是 agent,它有一个位置,它知道世界上的其他实体及其吸引力。假设你的目的地有 +1 attraction 力,障碍物有 -X attraction 力,有效排斥 "bot" (agent)。

这是一个决策伪代码:

/**
* @param {Array.<{position:Vector2, attraction:Number}>} entities
*/
Agent.prototype.calculateDirectionVector = function(entities){
    var agentPosition = this.position;
    var result = new Vector2(0,0);

    entities.forEach(function(entity){
         //calculate separation between agent and entity
         var displacement = entity.position.clone().sub(agentPosition);
         //figure out distance between entities
         var distance = displacement.length();
         //dampen influence of attraction linearly with distance
         var influence = entity.attraction/distance;
         //produce force vector exerted by this entity on the agent
         var force = displacement.normalize().multiplyScalar(influence);
         //add up forces on the entity
         result.add(force);
    });

    //normalize the resulting vector
    result.normalize();

    return result;
}