robocode 相关的总结

news2024/11/6 3:06:55

基础知识

1. heading 角度系

如图所示,所谓heading角,即从Y轴出发,然后顺时针绕回Y轴的这么个角度区间,取值范围: [0,360]

2. bearing角度系

所谓bearing 角,即从Y轴顺、逆时针出发,绕半圈回到Y轴所形成的两个角度区间,取值范围:顺时针[0,180) ;逆时针[0,-180]

实例分析

说明:

e.getBearingRadians(),如图中的∠FBC所示

是敌机(Enemy)与自己车头方向(你使用setAhead(正值)前进的方向即为车头方向,如BC箭头所示)所成的角,因为是以BC为Y轴的bearing角,所以这个角在这个例子中是个负值。

getHeadingRadians(),如图中∠ABC所示

是以自己的车头方向与屏幕垂直正上方为Y轴所成的heaing角。

absBearing=robocode.util.Utils.normalRelativeAngle(e.getBearingRadians()+getHeadingRadians());

所以absBearing角即为∠FBA,即自己与敌机的连线,与Y轴所成的bearing角,取值范围为[-180,180)。
 

相应的代码

 public void onScannedRobot(ScannedRobotEvent e) {

       //注意 这里的计算都以弧度为单位
       double absBearing=0d;
       //雷达转动角度
       double radarTurnAngle=0d;
       //得到绝对角度差
absBearing=robocode.util.Utils.normalRelativeAngle(e.getBearingRadians()+getHeadingRadians());

       //根据absBearing角算出Radar要调整的角度
       radarTurnAngle=Math.sin(absBearing - getRadarHeadingRadians());
       //转动雷达,注意是向右
       setTurnRadarRightRadians(radarTurnAngle);
    }

雷达锁定

我们要写这样一个代码,它将让敌人逃不出我们的眼睛。雷达锁定是一个高效战斗机器人的基础,因为robot只有执行onScannedRobot方法,我们才能够获取敌人的信息,而onScannedRobot方法只有在我们的雷达扫描到敌人之后才会被调用,当然,调用的过程是自动的。

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

public void onScannedRobot(ScannedRobotEvent e) {
     enemy.update(e,this);
     doubleOffset = 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)
	{
		System.out.println("angle:"+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 com;

import java.awt.Color;
import robocode.AdvancedRobot;
import robocode.ScannedRobotEvent;

public class ObserverRobot 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;

		}

	}

}

敌方坦克坐标预测

完整代码

...

AdvancedRobot类中相应的API解读

1. getHeadingRadians

public double getHeadingRadians()

Returns the direction that the robot's body is facing, in radians. The value returned will be between 0 and 2 * PI (is excluded).

Note that the heading in Robocode is like a compass, where 0 means North, PI / 2 means East, PI means South, and 3 * PI / 2 means West.

Overrides:

getHeadingRadians in class _AdvancedRadiansRobot

Returns:

the direction that the robot's body is facing, in radians.

疑问

I want to fire a bullet every turn, but I can't. Why?

Every time you fire, the gun generates some heat. You must wait till it is cool again to fire. If you give a fire order when your gun is hot, it will do nothing. The heat generated by a shot is 1 + (firepower / 5). The gun cools down at a default rate of 0.1 per turn (note that you can change this parameter when you run the battle, but nobody usually does). It means you can fire a 3.0 power bullet every 16 ticks.

See Rules.getGunHeat() and Robot.getGunCoolingRate().

What is the difference between the setXXX() (e.g. setFire()) and the XXX() (e.g. fire()) methods?

Basically, the setXXX() methods just notify Robocode to take some action at the end of the turn. The XXX()-type methods end the turn when you call them, and they block your robot's thread until the command finishes. Unless you have a good reason, you should almost always use the setXXX() version when writing AdvancedRobots.

What is the difference between a set method like setAhead() and ahead() without the set-prefix?

The difference between a method like ahead(), and the method setAhead() is that set-methods are only available with the AdvancedRobot. The difference is that you can call multiple setters like e.g. setAhead()setTurnGunLeft(), and setFire() in the same turn. These set commands will first take effect, i.e. execute, when you call the execute() method explicitly in a turn. Methods that are not setters like e.g. ahead()turnGunLeft(), and fire() will execute independently and take one to many turns to complete, as one command will need to execute and complete before the next command is being executed. Setters are called in the same turn when execute() is called. So the method ahead() is actually the same as setAhead() + execute(), and in that order. The set methods can be seen as "fire and forget" methods that are executed immediately, whereas the methods like ahead() must first complete its movement, turning, firing etc. before the next command is being run. Hence those commands need to wait for the other commands to complete first before the method itself will be executed.

How fast can I turn my gun?

The gun turns at 20 degrees per tick.

See Rules.GUN_TURN_RATE.

How fast can I turn my radar?

It turns 45 degrees per tick.

See Rules.RADAR_TURN_RATE.

What are ticks, turns, and frames?

A tick refers to one unit, which is also called a turn in Robocode. During one turn, you may perform one action as a Robot, or multiple (independent) actions as an AdvancedRobot. A frame is a unit of drawing to the Robocode client interface. If you are processing turns slowly, you will get one frame per tick / turn. However, if you up the turns per second beyond your computer's ability to render the frames, you will miss some frames of animation. This won't affect the robots' behavior, unless you foolishly added code in your onPaint(Graphics2D) method that alters your bots behavior. In that case, your bot will behave differently depending on whether or not the Paint button has been enabled, and if the framerate can keep up with the turnrate.

参考资料

Robowiki

Robocode教程7——雷达锁定_dawnsun001的博客-CSDN博客Robocode中一个高效雷达的学习记录_lihe758的博客-CSDN博客_雷达 heading angle

https://github.com/robo-code/robocode/blob/master/robocode.api/src/main/java/robocode/AdvancedRobot.java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/54768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计智能衣橱APPSpringboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

svg路径动画

前言 最近在开发大屏看板&#xff0c;UI让做一个这样的效果 本来也简单&#xff0c;UI给个git动图放上就好了。但是UI给的图有四五十m&#xff0c;实在是太大了。后来想到了svg路径动画&#xff0c;之前从来没有搞过&#xff0c;就研究了下&#xff0c;由于svg没怎么研究过&a…

考试周刊杂志考试周刊杂志社考试周刊编辑部2022年第39期目录

教育教学研究《考试周刊》投稿&#xff1a;cn7kantougao163.com 新课程标准下高中体育课堂教学的有效性研究 张子龙; 1-6 减负政策下小学科学作业设计对策研究 董婷; 7-11 “双新”背景下高中通用技术学科技术试验活动教学路径分析 洪晓云; 12-16 浅析小学科学…

学习二十大奋进新征程线上知识答题活动回顾

学习二十大奋进新征程线上知识答题活动回顾 活动背景 开展直播宣讲、组织知识竞赛答题……各地通过多种形式广泛开展学习宣传活动&#xff0c;一起学。 为深入学习宣传贯彻二十大精神&#xff0c;近日&#xff0c;我市开展“奋进新征程&#xff0c;共创强国业”学习二十大精神…

大型系统技术架构之服务架构(进阶版)

原版参照系统架构之服务器架构图https://blog.csdn.net/qq_36632174/article/details/102460730?spm1001.2014.3001.5502 目录 单体架构 第一次进阶&#xff1a;应用与数据库分离 第二次进阶&#xff1a;引入本地缓存和分布式缓存 第三次进阶&#xff1a;引入反向代理实现…

如何编辑图片合成图片?让我们来看看这些合成方法

相信大家在日常出行的时候&#xff0c;都会遇到想要和自己的朋友合照这种情况&#xff0c;却会因为社恐而不敢去向他人求助或者不想麻烦他人。所以通常我们会在同一个场景中拍摄照片&#xff0c;然后通过后期编辑将这些图片组合在一起&#xff0c;那么有的朋友会问&#xff0c;…

驱动开发代码研读

文章目录一、程序流程图二、头文件程序详解1、public.h2、driver.h3、device.h4、trace.h5.XDMA.h三、C程序详解1、driver.c1.头文件2.声明3.标记分页函数4.定义5.主函数1&#xff09;参数&类型2&#xff09;WPP&#xff08;非必要&#xff09;3&#xff09;清理回调函数4&…

【元胞自动机】元胞自动机晶体生长【含Matlab源码 232期】

⛄一、元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 何顿 康威设计了一个电脑游戏 “生命游戏” 后, 元胞自动机才吸引了科学家们的注意. 1983 年…

智工教育:军队文职报考要注意限制性条件

军队文职报考限制性条件 &#xff08;1&#xff09;曾因犯罪受过刑事处罚的人员和曾被开除公职的人员&#xff1b; &#xff08;2&#xff09;在各级公务员招考中被认定有舞弊等严重违反录用纪律行为的人员&#xff1b; &#xff08;3&#xff09;现役军人&#xff1b; &…

【多目标进化优化】MOEA 性能评价

1. 概述 \quad\quad对一个多目标进化算法的性能进行评价时&#xff0c;一方面需要有一套能够客观地反应 MOEA 优劣的评价工具或方法&#xff1b;另一方面需要选取一组比较有代表性的测试问题&#xff0c;通常选取有已知解的问 (benchmark test problem) 作为测试用例&#xff0…

C++中的回调函数再次总结(std::bind和function)

文章目录0 引入1、回调函数1.定义2.基本格式2、应用场景1.一件事需要多个独立步骤完成2.回调3、C11中的std::function和bind4、引用0 引入 最近看到一些文章说回调函数&#xff0c;再加上看到一些比较好的文章和代码&#xff0c;对于回调函数又有了重新的认识&#xff0c;在这…

react源码分析:babel如何解析jsx

同作为MVVM框架&#xff0c;React相比于Vue来讲&#xff0c;上手更需要JavaScript功底深厚一些&#xff0c;本系列将阅读React相关源码&#xff0c;从jsx -> VDom -> RDOM等一些列的过程&#xff0c;将会在本系列中一一讲解 工欲善其事&#xff0c;必先利其器 经过多年的…

性能测试 之cpu 线程 上下文切换问题分析

使用 stress-ng: 性能测试模拟线程上下文切换 上篇文章使用了stress-ng 模拟了 进程上下文切换导致的性能问题&#xff0c; 现在我们在使用 该工具模拟线程上下文切换&#xff0c;那么进程和线程有什么区别呢 抽象&#xff1a;线程&#xff08;thread&#xff09;是操作系统能…

MEMM最大熵模型

最大熵模型&#xff08;MEMM&#xff09;: 提出背景&#xff1a;解决模型三个缺点 最大熵结构&#xff1a;HMM框架加上多项的逻辑回归。 HMM缺点&#xff1a; 1.观测独立假设和齐次马尔可夫假设 解决办法&#xff1a;调转模型箭头 2.模型建模和求解不一致&#xff08;建模&am…

农产品溯源中GIS应用

农产品溯源中GIS应用 摘要 构建“从田间地头到餐桌”的农产品安全生产与溯源体系需求日益迫切。农产品的食品安全也是维持人们的生命健康重要因素之一。当前&#xff0c;农业信息化推进速度非常的迅速&#xff0c;各类型农业相关基础设施正在不断加强&#xff0c;信息技术能提…

vs2013的使用及编译中遇到的问题

目录 一、vs2013的使用 1、新建项目 2、新建源文件 3、编辑代码 但是如果每次新建文件都要加上这一句就很麻烦&#xff0c;所以这里提供一个一劳永逸的方法 二、运行代码的中的小问题 问题1&#xff1a;scanf函数不安全 解决办法 法1.用报错提示中的 scanf_s 来代替 scanf…

ShaderGraph实现序列帧动画

介绍 上篇我们介绍了ShaderLab编程实现序列帧动画,这里我们介绍一下如何使用可视化界面ShaderGraph来实现。 在使用ShaderGraph的过程中,我们可以了解ShaderGranph的一些操作,由于上篇文章已经分享了原理方面的知识,这里不再赘述。我们便开始ShaderGraph来实现序列帧动画。…

Proxyless Mesh 在 Dubbo 中的实践

作者&#xff1a;王程铭 背景 随着 Dubbo 3.1 的 release&#xff0c;Dubbo 在云原生的路上又迈出了重要的一步。在这个版本中添加了 Proxyless Mesh 的新特性&#xff0c;Dubbo Proxyless Mesh 直接实现 xDS 协议解析&#xff0c;实现 Dubbo 与 Control Plane 的直接通信&am…

深度学习训练营实现minist手写数字识别

深度学习训练营原文链接环境介绍前置工作设置GPU导入要使用的包进行归一化操作样本可视化调整图片格式构建CNN网络编译模型模型训练预测操作原文链接 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训…

OpenCV图像处理——卷积操作

总目录 图像处理总目录←点击这里 二十五、卷积操作 25.1、预处理 # 指定输入图像 ap argparse.ArgumentParser() ap.add_argument("-i", "--image", requiredTrue, help"path to the input image") args vars(ap.parse_args())# 分别构建…