• Robocode教程7——雷达锁定,“观察者号”


    摘自:http://site.douban.com/widget/notes/7736245/note/211198836/

    Robocode教程7——雷达锁定

    在这次教程中,我们要写这样一个代码,它将让敌人逃不出我们的眼睛。雷达锁定是一个高效战斗机器人的基础,因为robot只有执行onScannedRobot方法,我们才能够获取敌人的信息,而onScannedRobot方法只有在我们的雷达扫描到敌人之后才会被调用,当然,调用的过程是自动的。
    雷达是以机器人为圆心的一条射线,为了更直观,我们最好打开雷达图形显示,方法是:
    进入robocode,打开Options-> Preferences->view options,勾选Visible Scan Arcs

     


    还记得我们的Enemy类吗?它在我们的这个机器人中有着至关重要的作用。所以如果不太熟悉class Enemy的话还是先去看看吧。
    在Enemy类中有一个direction变量,它的值为:
    direction = bearingRadian + me.getHeadingRadians();

     


    如这张图所示,弄懂了direction变量,雷达锁定就很简单了。
    雷达的扫描实际上是一条线,当扫描线扫描到目标时,触发onScannedRobot事件,更新当前数据,包括direction。当程序执行到onScannedRobot内的代码时,雷达扫描线的角度getRadarHeadingRadians()已经和direction有所偏离。为了锁定目标,我们可以把雷达往反方向扫描。因为雷达旋转很快,而且getRadarHeadingRadians()和direction的偏移量不大,机器人是有一定大小的。于是扫描线在目标身上来回扫动,实现了雷达锁定。

    public void onScannedRobot(ScannedRobotEvent e) { 
                 enemy.update(e,this); 
            double Offset = rectify( enemy.direction -getRadarHeadingRadians() ); 
          setTurnRadarRightRadians( Offset * 1.5); 
    }
    这是我们的onScannedRobot方法,enemy.updata(e,this);是调用我们的enemy对象里面的方法,更新敌人信息,当然,忘了一点,在这之前,我们需要生成一个enemy对象,具体方法为:
    Enemy enemy = new Enemy();
    这里我们还要解释一下rectify方法,它的作用是对角度进行修正,因为direction减去我们雷达的朝向,有可能会大于180度或者小于-180度,比如当大于180度时,我们所需要转动的角度并不需要那么大,只需方向转一个角度就可以了。这个rectify方法很简单,当在后面应用很多。它的代码为:
        public double rectify ( double angle ) 
        { 
            if ( angle < -Math.PI ) 
                angle += 2*Math.PI; 
            if ( angle > Math.PI ) 
                angle -= 2*Math.PI; 
            return angle; 
    }
    在代码中,enemy.direction -getRadarHeadingRadians()是雷达所要旋转的偏移量。假设之前雷达顺时针扫描,那么enemy.direction略小于getRadarHeadingRadians(),为负。经rectify()方法修正后即为需要转动的值。然后用setTurnRadarRightRadians旋转雷达,旋转度数为偏移的1.5倍,因为RadarOffset为负,故反方向扫描,保证无论目标
    如何移动,扫描线始终在目标身上。上面的1.5可以改成2,3等数。当你在Options中打开了Visible Scan Arcs选项后,就可以看到绿色的扇形,倍数为1.5的时候,类似一条线,而倍数为2,3的时候就可以看到像是一个扇形。
    另外我们还要说一下另外两段代码:
                     setAdjustGunForRobotTurn( true ); 
            setAdjustRadarForGunTurn( true );
    它们的作用是使雷达、大炮、车身运动独立,具体参考API手册。

    到这里我们雷达扫描的代码就完成了,运行试试我们的“观察者号”吧!!

     



    附:观察者号完整代码:

    package cm; 
    import java.awt.*;
    import robocode.*; 

    public class ObserverRobo extends AdvancedRobot 
    {
            Enemy enemy = new Enemy();
            public static double PI = Math.PI;
                 
            public void run() 
            { 
                    setAdjustGunForRobotTurn( true ); 
            setAdjustRadarForGunTurn( true ); 
            this.setColors(Color.red, Color.blue, Color.yellow, Color.black, Color.green);
            
                    while(true){
                            if(enemy.name == null){
                                    setTurnRadarRightRadians(2*PI); 
                                    execute(); 
                            }
                            else{
                                    execute();
                            }
                    }
        }
                 
        public void onScannedRobot(ScannedRobotEvent e) 
        { 
                enemy.update(e,this); 
            double Offset = rectify( enemy.direction - getRadarHeadingRadians() ); 
            setTurnRadarRightRadians( Offset * 1.5); 
        }
      //角度修正方法,重要
        public double rectify ( double angle ) 
        { 
            if ( angle < -Math.PI ) 
                angle += 2*Math.PI; 
            if ( angle > Math.PI ) 
                angle -= 2*Math.PI; 
            return angle; 
        }
        public class Enemy {
                public double x,y;
                public String name = null;
                public double headingRadian = 0.0D; 
            public double bearingRadian = 0.0D; 
            public double distance = 1000D; 
            public double direction = 0.0D; 
            public double velocity = 0.0D; 
            public double prevHeadingRadian = 0.0D; 
            public double energy = 100.0D; 
            
            
            public void update(ScannedRobotEvent e,AdvancedRobot me){
                    name = e.getName();
                    headingRadian = e.getHeadingRadians();
                    bearingRadian = e.getBearingRadians();
                    this.energy = e.getEnergy();
                    this.velocity = e.getVelocity();
                    this.distance = e.getDistance();
                    direction = bearingRadian + me.getHeadingRadians(); 
                    x = me.getX() + Math.sin( direction ) * distance; 
                    y= me.getY() + Math.cos( direction ) * distance; 
            }
        }
    }

  • 相关阅读:
    vim的使用
    linux 环境下,kafka_2.123.0.0 集群搭建
    NetCore3.1 ping网络是否畅通及获取服务器Cpu、内存使用率
    使用kafkatool连接使用Kafka
    NetCore3.1 制作windows服务
    kafka_2.123.0.0 版本Topic、producer 命令记录
    NetCore 控制台应用程序依赖注入
    使用 contentvisibility 优化渲染性能
    有意思的鼠标指针交互探究
    linux中如何将多条命令写入在一行中,其中包括while语句,同时,在k8s的command中如何来使用
  • 原文地址:https://www.cnblogs.com/KeenLeung/p/2558051.html
Copyright © 2020-2023  润新知