反重力引擎_反重力运动

反重力运动是一种高度灵活的技术,通过允许您在战场上定义避免避开的特定点(称为重力点 ),可以帮助您欺骗模式分析机器人。 每个重力点都有自己的强度 。 通过沿x和y方向解析这种强度的分量,可以很好地避开所有敌方机器人。 (请参阅侧栏“ 反重力术语 ”以帮助理解本技巧中使用的术语。)

本技巧的第一部分介绍了一种基本的反重力技术,而下一部分介绍了解决此基本代码固有的局限性的想法。

反重力运动背后的数学

如果您具有三角学的实际知识,反重力背后的数学实际上非常简单。

在图1中,标有“ F”的箭头显示了来自Crazy的作用在AntiGravityBot上的力的方向。 可以将力视为x和y方向的分量,如其他两个箭头所示。 分解力使我们能够简单地将x和y方向上所有重力点的所有力加在一起,从而产生x和y方向上的总力。

图1.解决力
解决力量

为了防止我们的机器人受到遥远的机器人的影响,我们必须使用函数force = strength/Math.pow(distance,2)从重力点计算对机器人的force = strength/Math.pow(distance,2)其中力量是重力点的力量, 距离是指重力点与机器人之间的距离。 2的幂值不固定; 您可以使用3的值来避免只在非常接近该点时才使用该点。

代码

以下清单为您展示了基本的反重力系统的代码。 清单1显示了主要的反重力功能。 它在向量中的所有重力点之间循环,分解力,然后沿正确方向移动机器人。 我建议将敌方机器人指定为排斥点。 为此,您必须对战场保持最新状态,这意味着您的雷达必须经常旋转。

清单1.反重力主力:antiGravMove()
void antiGravMove() {
    double xforce = 0;
    double yforce = 0;
    double force;
    double ang;
    GravPoint p;
    
    for(int i = 0;i<gravpoints.size();i++) {
        p = (GravPoint)gravpoints.elementAt(i);
        //Calculate the total force from this point on us
        force = p.power/Math.pow(getRange(getX(),getY(),p.x,p.y),2);
        //Find the bearing from the point to us
        ang = 
    normaliseBearing(Math.PI/2 - Math.atan2(getY() - p.y, getX() - p.x)); 
        //Add the components of this force to the total force in their 
        //respective directions
        xforce += Math.sin(ang) * force;
        yforce += Math.cos(ang) * force;
    }
    
    /**The following four lines add wall avoidance.  They will only 
    affect us if the bot is close to the walls due to the
    force from the walls decreasing at a power 3.**/
    xforce += 5000/Math.pow(getRange(getX(), 
      getY(), getBattleFieldWidth(), getY()), 3);
    xforce -= 5000/Math.pow(getRange(getX(), 
      getY(), 0, getY()), 3);
    yforce += 5000/Math.pow(getRange(getX(), 
      getY(), getX(), getBattleFieldHeight()), 3);
    yforce -= 5000/Math.pow(getRange(getX(), 
      getY(), getX(), 0), 3);
    
    //Move in the direction of our resolved force.
    goTo(getX()-xforce,getY()-yforce);
}

清单2中所示的辅助方法使我们能够以最有效的方式移至某个点,并获得机器人与敌人之间的距离。

清单2. Helper方法
/**Move in the direction of an x and y coordinate**/
void goTo(double x, double y) {
    double dist = 20; 
    double angle = Math.toDegrees(absbearing(getX(),getY(),x,y));
    double r = turnTo(angle);
    setAhead(dist * r);
}

/**Turns the shortest angle possible to come to a heading, then returns 
the direction the bot needs to move in.**/
int turnTo(double angle) {
    double ang;
    int dir;
    ang = normalisebearing(getHeading() - angle);
    if (ang > 90) {
        ang -= 180;
        dir = -1;
    }
    else if (ang < -90) {
        ang += 180;
        dir = -1;
    }
    else {
        dir = 1;
    }
    setTurnLeft(ang);
    return dir;
}

/**/Returns the distance between two points**/
double getRange(double x1,double y1, double x2,double y2) {
    double x = x2-x1;
    double y = y2-y1;
    double range = Math.sqrt(x*x + y*y);
    return range;	
}

最后,在清单3中,我们看到了GravPoint类,该类保存了重力点所需的所有数据。 请注意, power必须为负才能排斥。

清单3. GravPoint类
class GravPoint {
    public double x,y,power;
    public GravPoint(double pX,double pY,double pPower) {
        x = pX;
        y = pY;
        power = pPower;
    }
}

可以从下载中下载此技巧的完整资源。

改善行为

清单1至清单3中的代码产生了合理的行为,但战斗性能几乎令人叹为观止。 尽管该机器人通常远离其他机器人,但它倾向于卡在墙壁附近。 这样做的原因是,一旦机器人到达底壁,下面便没有机器人了。 因此,除了壁自身产生的排斥力之外,没有力将其推离壁。 由于壁排斥力的范围有限,因此会产生不良行为。

为了解决这个问题,我使用了一个系统,将所有力量集中在赛场周围的一系列点上。 然后,我将推斥力值分配给在其上具有大于平均总力的点(这意味着它们附近有机器人),并将吸引力值分配给在其上具有小于平均总力的那些点。 然后,我解决这些新点对我的机器人的作用。 分配吸引力点时,必须格外小心。 如果您的机器人接近一个吸引力点,它将悬停在它上面,永不离开。 因此,我建议随机分配这些中间点的位置并定期更改其位置。

我将留给您制定增强功能的代码。 请确保,上述代码仅作了少许改动,使用了与上述代码完全相同的基本原理。 作为进一步的提示,我建议使用force = strength/Math.pow(distance,1.5)来计算机器人中间点的力。

其他增强功能

反重力是一种非常灵活的技术,因此,讨论使用它产生的全部行为是不切实际的。 但是,这里有一些更有趣的内容:

目标选择 :通过为您擅长击中或健康状况不佳的目标分配较低的排斥值,您可以靠近它们并捕食弱者。

随机化 :您可能需要定期从x和y力中增加或减去随机量,以产生更多的随机运动,甚至偶尔停止,以欺骗敌人的目标瞄准系统。 我鼓励您实施这种行为。

近战子弹躲避 :如果您知道何时有敌人向您开火,您可以将发射的子弹建模为反重力点。 如果您假设它是使用线性目标射击的,则可以每转一圈更新该重力点的位置并躲避子弹。 但是,此增强功能尚未被任何机器人完善。

跟随领导者 :此增强功能为您的机器人创造了一个吸引人的关注点。 因此,您可以通过移动点来生成所需的任何模式(在robocode物理定律内),同时保留标准的反重力墙排斥力。


翻译自: https://www.ibm.com/developerworks/java/library/j-antigrav/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值