虚拟子弹技术的例子坦克VirtualGunsSampleBot

本文介绍了一个使用多种虚拟枪法策略的机器人示例,通过模拟子弹飞行路径预测敌方位置,选择最佳射击角度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.Vector;

import robocode.AdvancedRobot;
import robocode.Bullet;
import robocode.DeathEvent;
import robocode.ScannedRobotEvent;
import robocode.WinEvent;

public class VirtualGunsSampleBot extends AdvancedRobot {
    static final double BULLET_POWER = 3.0;
   
    RobotState me, target; // these aren't static, so they will be reset every round
   
    static Vector guns; // this Vector (and all its contents) will persist from round to round
   
    static Vector virtualBullets = new Vector();
   
    Rectangle2D.Double battlefield;
   
    public void run(){
        setAdjustGunForRobotTurn(true);
        setAdjustRadarForGunTurn(true);
        setAdjustRadarForRobotTurn(true);
       
        battlefield = new Rectangle2D.Double(0,0,getBattleFieldWidth(), getBattleFieldHeight());
       
        if(guns == null){
            guns = new Vector();
           
            Gun defaultGun = new ReallyBadGun();
            defaultGun.hits = 1;
            guns.add(defaultGun);
            guns.add(new HeadOnGun());
            guns.add(new RandomGun());
        }
       
        virtualBullets.clear();
       
        while(true){           
            //Update our position, heading, and velocity
            me = new RobotState();
            me.name = getName();
            me.velocity = getVelocity();
            me.heading = getHeadingRadians();
            me.x = getX();
            me.y = getY();
           
            //Turn our radar
            if(target == null)
                setTurnRadarRightRadians(Math.toRadians(45));
            else {
                double radarTurnAngle = normalizeRelativeAngle(me.absoluteAngleTo(target) - getRadarHeadingRadians());
                if(radarTurnAngle > 0)
                    radarTurnAngle += .4;
                else
                    radarTurnAngle -= .4;
                setTurnRadarRightRadians(radarTurnAngle);
            }
           
            //Move each virtual bullet forward one tick. After moving, check if they are off the field or near the target.
            Iterator i = virtualBullets.iterator();
            while(i.hasNext()){
                VirtualBullet virtualBullet = (VirtualBullet) i.next();
                virtualBullet.setLocation(virtualBullet.project(virtualBullet.heading, virtualBullet.velocity));
               
                if(virtualBullet.distance(target) < 25){ //check if the virtual bullet "hit" the enemy
                   
                    virtualBullet.gunUsed.hits += 1;
                    i.remove();
                } else if(!battlefield.contains(virtualBullet)){ //check if the virtual bullet is off the field
                    i.remove();
                }
            }
           
            if(target != null) gun();
           
            execute();
        }
    }
   
    public void gun(){
       
        //Select the best gun
        long bestScore = -1;
        Gun bestGun = null;
        Iterator i = guns.iterator();
        while(i.hasNext()){
            Gun gun = (Gun) i.next();
            if(gun.hits > bestScore){
                bestScore = gun.hits;
                bestGun = gun;
            }
        }
       
       
        //Aim with the best gun
        setTurnGunRightRadians(normalizeRelativeAngle(bestGun.getFiringAngle(me, target, BULLET_POWER) - getGunHeadingRadians()));
       
       
        // create new virtual bullets only if we actually fired this turn
        Bullet b = setFireBullet(BULLET_POWER);
        if(b != null){
            i = guns.iterator();
            while(i.hasNext()){
                Gun gun = (Gun) i.next();
                VirtualBullet newVirtualBullet = new VirtualBullet();
                newVirtualBullet.setLocation(me);
                newVirtualBullet.heading = gun.getFiringAngle(me, target, BULLET_POWER);
                newVirtualBullet.velocity = 20.0 - 3.0 * BULLET_POWER;
                newVirtualBullet.gunUsed = gun;
                virtualBullets.add(newVirtualBullet);
            }
        }
    }
   
    public void onScannedRobot(ScannedRobotEvent e){
        // Create a new RobotState object to represent the enemy's current state
        target = new RobotState();
        target.setLocation(me.project(e.getBearingRadians() + getHeadingRadians(), e.getDistance()));
        target.heading = e.getHeadingRadians();
        target.velocity = e.getVelocity();
        target.name = e.getName();
    }
   
    public void onDeath(DeathEvent e){
        endRound();
    }
   
    public void onWin(WinEvent e){
        endRound();
    }
   
    public void endRound(){
        Iterator i = guns.iterator();
        out.println();
        out.println("Virtual bullet hit table");
        out.println("------------------------");
        while(i.hasNext()){
            Gun gun = (Gun) i.next();
            out.println(gun.getName() + ": " + gun.hits);
        }
        out.println();
       
        //So we don't keep firing
        target = null;
    }
   
    //Draw the virtual bullets on screen - this will only work with a recent version of robocode and "Paint" turned on in the robot's console
    public void onPaint(Graphics2D g){
       
        Iterator i = virtualBullets.iterator();
        while(i.hasNext()){
            VirtualBullet virtualBullet = (VirtualBullet) i.next();
            g.setColor(virtualBullet.gunUsed.getColor());
            g.fillOval((int)virtualBullet.x - 3, (int)virtualBullet.y -3, 6, 6);
        }
       
        int numberOfGuns = guns.size();
        for(int j = 0; j < numberOfGuns; j++){
            Gun gun = (Gun) guns.elementAt(j);
            g.setColor(Color.WHITE);
            g.drawString(gun.getName() + ": " + gun.hits, 20, 5 + j*15);
            g.setColor(gun.getColor());
            g.fillOval(5, 5 + j * 15, 10, 10);
        }
    }
   
    //This method ensures that angles are between -180 and 180 degrees, for turning radar / gun
    public static double normalizeRelativeAngle(double angle){
        while(angle <= -Math.PI){
            angle += 2.0 * Math.PI;
        }
        while(angle > Math.PI){
            angle -= 2.0 * Math.PI;
        }
        return angle;
    }
}

class ReallyBadGun extends Gun{
    public String getName(){return "Really bad gun - fires away from the enemy";}
    public Color getColor(){return Color.RED;}
   
    public double getFiringAngle(RobotState shooter, RobotState target, double bulletPower) {
        return target.absoluteAngleTo(shooter);
    }
}
class RandomGun extends Gun {
    public String getName(){return "Simple linear gun";}
    public Color getColor(){return Color.BLUE;}
   
    public double getFiringAngle(RobotState shooter, RobotState target, double bulletPower) {
        //double maxAngle = Math.asin(8.0 / (20.0 - 3.0 * bulletPower));
        double directAngle = shooter.absoluteAngleTo(target);
        return directAngle - target.velocity * Math.sin(directAngle - target.heading) / (20.0 - 3.0 * bulletPower);
    }
}

class HeadOnGun extends Gun {
    public String getName(){return "Head on";}
    public Color getColor(){return Color.GREEN;}
   
    public double getFiringAngle(RobotState shooter, RobotState target, double bulletPower) {
        return shooter.absoluteAngleTo(target);
    }
}

abstract class Gun {
    public long hits;
    public abstract Color getColor();
    public abstract String getName();
    public abstract double getFiringAngle(RobotState shooter, RobotState target, double bulletPower);
}

class FieldPoint extends Point2D.Double{
    public FieldPoint(){}
    public FieldPoint(double x, double y){
        super(x,y);
    }
   
    public double absoluteAngleTo(FieldPoint p){
        double angle = Math.atan2(p.x - x, p.y - y);
        while(angle < 0.0){
             angle += 2.0 * Math.PI;
        }
        while(angle >= 2.0 * Math.PI){
             angle -= 2.0 * Math.PI;
        }
        return angle;
    }
   
    public FieldPoint project(double angle, double distance) {
        return new FieldPoint(x + Math.sin(angle) * distance, y + Math.cos(angle) * distance);
    }
}

class MotionState extends FieldPoint{
    public double velocity, heading;
}

class VirtualBullet extends MotionState{
    public Gun gunUsed;
}

class RobotState extends MotionState{
    public String name;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值