TA的每日心情 | 慵懒 2015-1-8 08:46 |
---|
签到天数: 2 天 连续签到: 1 天 [LV.1]测试小兵
|
导论
很多人不太明白,当自己撞到墙时,为什么生命点会下降?为什么发射子弹时生命点也会下降?为什么有时候自己没有被消灭而不能发射子弹了,为什么子弹打到敌人时总不那么精确?为什么自己突然在战斗中一动不动了?其实这一切都是Robocode中存在的参数在起作用。比如静态的参数:屏幕高宽,坦克车的高宽,绝对方向,相对方向等等;动态的参数:速度,加速度,炮管冷却时间,能量,损伤,子弹速度,旋转速度等等。在物理学原理中” 运动的物体是变化的,变化的物体是相互影响的”。这些许许多多的参数也验证了这一规律。任何一个参数方的变动都会影响到其它参数的作用。所以就产生了很多让人迷惑的现象。要想真正了解 Robocode,想成为Robocode机器人的顶级玩家,我想我们必须对这些参数及其相互作用力要精确的了解,并应用到我们的战争中来。下面天翼.李 (Skyala.Li)就和大家一起来看看Robocode中重要的参数并分析分析这些参数的来龙去脉以及它们之间千丝万缕的关系。让我们一起走向 Robocode机器人专家之路。
系统参数
系统系数中最重要的是要清楚整个坐标系统和方向系统。
1.方向系统
整个战场是以屏幕正上角为0度,按顺时针排列的方向。详情可见” Robocode基本原理之方向剖析”。
2.坐标系统
整个战场的坐标是以屏幕左下角为原点,高为Y坐标,宽为X坐标。详情可见”Robocode基本原理之坐标锁定”。
3.单位
* 距离单位:
游戏中规定的距离是以像素(Pixels)点为单位,如果你把屏幕缩小了,那就是以缩小后的像素点为单位,反之就是放大后的像素点为单位。
* 时间单位:
游戏中规定的时间是以帧(frame)或滴答(ticks)(有点像时钟滴答),或时间周期(turns),或单独的时间片(simply timeslices)为单位.由于时间单位的多样化所以一直没有一个标准出来。我们利用getTime()函数可返回每个回合中的帧(frame)时间,注意每一场战斗都是由多个回合数组成的。所以每一个回合的开始都会设置Time的默认值为0。
4.比赛回合
比赛回合是比赛中由用户自己设置的比赛次数,默认值为10,用户可利用函数getRoundNum()返回当前正在进行的比赛回合,并可利用函数 getNumRounds()返回自己设置的总回合数。用户可在战场环境下选择菜单Battle->New Battle 在中间的Number of round选项中输入自己想要进行的回合。
5.战争速度
可能有些朋友对比赛的速度不太满意,想以更慢的速度观察比赛的每一个细节,好仔细研究机器人的性能;也有人想以更快的速度结束比赛来进行联赛。没关系,你只要在Option->Preferences->frame per second下的列表框中输入你想要的速度或选择你要的默认速度。注意:最小为1,最大为10000,数字越小战争比赛速度就越慢。当然这些都是我们自己所预设的值,实际上在战争中它会依据仿真引擎的处理时间而稍有不同。好,让我们选择10,再回到战场,呵呵,是不是像放慢镜头。注:FPS也就是每秒内 Robocode仿真引擎能播放多少帧。1 to rounds 10 代表着10个回合中的第一个回合,22 FPS就是我们当时的比赛速度,你把屏幕最小化你会发现FPS变大了。仔细想想你会明白为什么的?对,它少了静态图片的播放了.仿真器不再需要加载静态图片,处理速度当然快了。
6.扫描器开关
不少初学者说看不到机器人雷达扫描的蓝光,由此怀疑自己创造的机器人雷达系统不完善。其实这是由于你的系统扫描器开关没有打开。选择Option-> Preferences->Visible Scan Arcs(Cool,but May slow down game).你就可打开你的扫描器了,连Robocode的作者自己都说Cool,but May slow down game(可能会影响速度),不要担心速度会慢下来,现在的PC速度足以处理这一切了。
7.记分牌
所有回合比赛结束你都会看到自动弹出一个对话框,里面显示了一些数字,这就是记分牌,也即你设置的回合比赛结束后的成绩单。它可是你分析数据及参加联赛的重要依据。Robot Name 是比赛机器人的名字。Total Scroe为这次比赛你的总共得分;Survival是你存活率的得分;Last Survivor Bonus:你是赢的次数相对对手的分红得分;Bullet Dmg:是你的子弹损失得分也即发射的子弹数的得分;Bonus:是子弹数的分红得分;Ram Dmg *2是你的撞击得分;Bonus:是你撞击得分分红;最后两项Survival 1sts,是你赢的次数,不算做分数。所有分数加起来就是你的总分。记住在联赛并不是总分越高越好,它是算综合平均分的。其中撞击分和子弹损失分就要越少越好。你如果观察两大高手比赛的记分牌,你会发现他们的Ram Dmg 和Ram Dmg中的Bonus一般都为0。
战斗参数之静参
战争的机器人身上会打出字幕'disabled',这是为什么?其实这是警告你机器人不能动了也意味着你的生命点值为0,但是你没有死。如果你的子弹已经打中了别的机器人,你能够从这个状态中恢复过来。
1.方向系
方向是用角来表示,角在数学中有弧度表示法和角度表示法,所以在我们的Robocode中也有两种表示方向的方法。弧度表示法要在角度表示的函数后加上”Radians”字符。详细的见下面说明:
* 绝对方向:
战争中每一个部件都有自己的绝对方向。我们分别用下面的函数求得:getHeading(),getHeading()返回你想处理的部件如炮管和屏幕的绝对方向,它大于等于0 ,小于< 360。 getHeadingRadians()返回以弧度表示的绝对方向,它大于等于0 ,小于 2 * PI
* 相对方向:
相对方向是战争中以任一物为参照而求得的方向。它的值可用下面的函数得到:getBearing() 也即参照物的绝对方向减去你的绝对方向的值。它小于负180,大于等于180度。 getBearingRadians()的原理同上,它大于负Math.PI,小于等于Math.PI。
2.坐标系
在战争中方向和坐标是最重要两个参数了。只要清楚了这两个参数。其他的都好解决。每一个行动中的机器人在屏幕中都有它自己的位置,也即坐标。我们可分别用函数getX,getY得到机器人精确的位置,再辅以距离就可定位到屏幕上的任何机器人。
3.机器人的高,宽,姓名
我们可分别用下面函数得到:getHeight,getWidth, getName机器人本身有关的静态参数。
4.事件
每一场战争,机器人的每一动作都是由事件机制而触发的。了解其中的事件,并能动态得到每一个事件对于决定我们的行动很重要。函数getAllEvents()就提供了此功能。下面代码打印出了比赛中的所有事件。
{ Vector v = getAllEvents();
for (int i = 0; i < v.size(); i++) {
out.println(“Events: ” + v.elementAt(i))
}
Robocode中存在的事件列表如下:
Robot.onBulletHit(robocode.BulletHitEvent)
Robot.onBulletHitBullet(robocode.BulletHitBulletEvent)
Robot.onBulletMissed(robocode.BulletMissedEvent)
Robot.onHitByBullet(robocode.HitByBulletEvent)
Robot.onHitRobot(robocode.HitRobotEvent)
Robot.onHitWall(robocode.HitWallEvent)
Robot.onDeath(robocode.RobotDeathEvent)
Robot.onWin(robocode.WinEvent)
对于事件的处理我们要注意下面几点:
* onSkippedTurn事件的处理:
当你的代码处理时间非常长,你可调用方法onSkippedTurn(),跳过一个turn(时间周期),意味着你放弃在这帧中行动的机会。除非你采取行动否则你将收不到这个事件。如果你在一个进程中跳过2个turn(时间周期),你将失去所有事件。如果你在一个进程中跳过30 个turn(时间周期),你将以0分离开这回合比赛。Robocode中规定每个机器人的一个turn(时间周期)的时间长度大约是15毫秒(根据系统来变化的)。上面涉及到线程的问题,在Robocode中当每一时间周期机器人处理完自己的行为后这个事件会被放入线程队列等待,当所有机器的人行为都在事件队列中排队了,系统才唤醒线程处理队列。在等待的过程中,每一个机器人有权决定这个时间周期内是否等待,不等待,相当于弃权。
* 事件内队列的排列顺序:
事件内的队列都是按优先权来排列的,我们可以从AdvancedRobot api中的getEventPriority()方法中查看到默认的优先权. 注意:当正在处理一个事件的时候如果我访问事件队列,事件已经从队列中移走了。我们是无法得个这个事件的。
5.优先级别
说到事件,我们不得不提优先级别.每一个Robocode系统事件都有其自身的优先级别我们从下表可以看到从低到高排列的事件优先级,高优先级别的事件可中断低优先级别的事件。
ScannedRobotEvent: 10
HitRobotEvent: 20
HitWallEvent: 30
HitByBulletEvent: 40
BulletHitEvent: 50
BulletHitBulletEvent: 50
BulletMissedEvent: 60
RobotDeathEvent: 70
CustomEvent: 80
SkippedTurnEvent: 100
WinEvent: 100
DeathEvent: 100
如果你想让某一事件先处理,我们就要利用函数setEventPriority()改变事件的优先级,事件的优先级别在0- 99之间,100为保留的数字。
战争参数之动参
1.生命点参数
整个战斗中数生命点最重要,你的一切都是为了它而存在,当生命点没有了,也代表着你输了这场战斗。
我们可以用函数getEnergy()得到我们机器人的生命点数。
* 损失:
相撞损失:在哪些相撞过程中我们的生命点会下降呢?当我们撞到墙时我们的生命点会下降,生命点损伤度=Math.abs (velocity) * 0.5 -1。当我们撞到另一个机器人,我们移动将会停止,并且我们会损失生命点6点。同时我们会被扣除积分1.2分。
击中损失
当我们被子弹打中我们的生命点损失是依据对方的能量大小而定的。当子弹能量为1时,我们生命点损失=4 * power,如果子弹能量大于1,那么我们的生命损失+= 2 * (power-1)
发射损失
每发射一颗子弹我们的生命能量就会减1,为什么会这样?这可是遵从物理学中的能量转换守恒定理。我们生命能量已经会转化为子弹能量了。子弹能量增加有失必有得,怎样才能有战争中获得额处的能量呢?如果我们的子弹打中别的机器人,我们可以从子弹那窃取到3*power的能量.这是唯一增加生命力的途径,所以我们尽量少被敌人打,并提高自己的命中率,还要保存实力,以备攻击。
2.子弹参数
由于子弹对生命力的影响很大,我们的每一个子弹要用到要害处,精确计算子弹及其能量值就变得很重要了。
* 子弹能量:
子弹能量是通过函数getPower()得到的。它大于等于0.1,小于等于 3。
* 子弹速度:
每一颗子弹有着自身的速度,这在处理敌人向你开炮前的移动策略可是很有帮助的。子弹的速度也和它的能量有关: speed = 20 - 3 * power。由于能量范围在0.1到3之间我们可求得子弹的速度范围:11 <= bullet speed <= 19.7。
3.炮管参数
子弹由炮管发射,炮管的方向决定了子弹的方向,炮管的热量也决定着子弹的发射。炮管还会发热?很多人都会很惊奇,不错。真实战争中我们的大炮不一样也会发热吗?Robocode也就是别一个真实的战场,战争中能用到的知识都可应用在Robocode中。方向参数从我们上面的战争静态参数说明中可看到。下面我们来看看炮管的其他参数:
* 旋转速率:
炮管在每一个时间周期内旋转速率=20 度/帧(frame)
* 炮管热量:
当我们开火时,炮管产生的热量由子弹开火时的能量决定也即:热量=1+(firepower/5),我们可以利用函数 getGunHeat()得到炮管当时的热量,只有当getGunHeat恒等于0时,我们才能再次发射子弹。现在你明白了为什么有时候我们生命点非零并且有子弹就是不能开火的原因了吗?炮管过热了!
* 冷却度:
有热度当然就有冷却度,不冷却我们的炮管会永远不会开火的。系统战斗设定的默认冷却速度是0.1/tick(时间周期),我们可通过函数 getGunCoolingRate()得到这个参数值。我们还可以通过系统设置冷却速度。选择Battle->New ->Rules->Gun Cooling Rate。
4.雷达参数
雷达,是我们在战争中的双眼,它能看到并告诉我们敌人的一举一动,知已知彼才能百战不贻!
* 旋转速度:
雷达以每时间周期45度的速度旋转。也即45 degrees/frame.
* 扫描面积:
雷达扫描是呈扇形的,它的开始位置到终止位置的长度大约为1200。只要我们放大屏幕可以通过眼睛估算出这个面积。
* 扫描排列:
扫描到的数据有墙,目标,子弹等等。这些是按扫描距离来排列,从离雷达最近的物体开始到最后扫描到的物体。
5.坦克车参数
好了,回到我们的机器人本身了。我们来看看它又有些什么参数。
* 前进速度:
我们的机器人最大的速度(Velocity)为8,函数getVelocity()返回了我们机器人当前的速度。
* 加/减速度
在这之前我们先来看看物理学中的加/减速度的求法,及相关的一些公式知识。
我们设S为距离,Vt为终速度,Vo为初速度,t为时间,a为加速度得到如下:
位移公式S=vot+at2/2
速度公式vt=vo+at
速度-位移公式vt2-vo2=2a
平均速度公式v=(vt+vo)/2=s/t
加速度公式a=(vt-vo)/t
我们再来看看Robocode中的加/减速度:加速度为 1 像素(pixel)/帧frame ,减速度为 2 pixel/frame。
如果我们的机器人从静止到最大速度,由公式可求得所要的时间(getTime)=8/1也即要8个时间周期,很有意思的计算,我们还可据此计算出更多的相关有用的数据。
* 旋转速度:
机器人的旋转速度和当前的速度有关即旋转速度=10 - 0.75 * getVelocity()
相互作用参数
在Robocode 中每一个部件都不是单独起作用的,都会影响到其他部件。上面的部分例子已经说明了这点,下面我们用旋转过程再来验证一下:雷达安装在炮上,炮安装在机器人上,它们会相互影响。如果我们向左转动炮管,而使雷达向右转动,那么雷达只会向右转动(45-20) =25度;如果两者都向右转动,雷达将向右转(45+20)=65度。同样的道理炮和机器人也是方向同相加,方向反相减。
有的人会问,坦克车在前进时,按照物理中的说法:如果一个物体在另一物体之上,如都向同一方向运动,上面的物体会继承下面物体的速度。那么子弹是不是也可以继承坦克车的速度。答案是错误的。这里我们注意一点,子弹本身又是一种特殊的能量它的速度不符合能量的转换定理,不可以继承坦克车的速度的。
总结
其实Robocode中各个运动的参数都遵守物理学的基本规律。而其中起关键作用的是能量转换守恒定理。只要大家把他们之间的能量转化理清楚了。相信参数的秘密也不是什么秘密了。本文章中我们揭示了大部分在实际战斗中用到的参数,有部分没有列出的大家可参考Robocode API文档说明。我们不仅要知道参数的存在及他们的关系还要用到我们的机器人战斗中去。这样才能真正明白个中之理。 |
|