我不明白这种方法到底在做什么。有人可以向我解释这个问题吗?
public void onScannedRobot(ScannedRobotEvent e)
{
setTurnRadarLeftRadians(getRadarTurnRemaining());
setTurnRight(e.getBearing() + 90.0D - dir / 33.0D);
if (((Guppy.var = var - e.getEnergy()) <= 3) && (var > 0.0D))
{
setMaxVelocity(Math.random() * 9.0D + 3);
setAhead(Guppy.dir = dir * type);
}
setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
if (getGunHeat() == 0.0D)
{
setFire(2.9D);
vel = e.getVelocity();
}
var = e.getEnergy();
}
答案 0 :(得分:2)
熟悉三角函数而不是Robocode的人注意: Robocode的角度值是非负的并且顺时针增加,而不是零中心,并且像三角函数惯例那样逆时针增加。
圣牛,这是一个毛球。痛苦的风格,分配变量然后在同一表达式中使用它,并随机重用static
变量用于不同的目的。 (编辑:我已经离开了robocode太长时间;看似模糊不清的混乱可能是code size手动优化的结果。)让我们试着去掉那一条凌乱的线,从这里开始:
setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
看起来var
用于保存子表达式e.getBearingRadians() + getHeadingRadians()
的结果。由于e.getBearingRadians()
会将目标相对返回到您的标题,var
是绝对 目标的承载即可。重构:
double targetBearing = e.getBearingRadians() + getHeadingRadians();
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));
唉,还是一团糟。我们还有变量vel
未提及,但基于其余代码,它似乎是上次扫描时目标的速度(并且在皮疹假设下只会进行一对一的比赛);它与当前速度合并为加权平均值,以提供粗略的预测速度,因此可能存在一些目标主导逻辑。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));
由于robocode似乎忽略了航向和航向之间的差异,因此最里面的正弦Math.sin(e.getHeadingRadians() - targetBearing)
给出了一个有符号系数,表明目标速度的哪个分量垂直于其承受因此需要调整角度。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient)));
弧正弦表达式似乎旨在将目标运动的垂直分量转换回角度调整。这个数学运算是完全错误的,因为反正弦不能这样工作:它将区间[-1,1]中的系数转回到区间中的角度[-pi / 2,pi / 2]并且将预测速度除以14可能只是试图将参数与反正弦限制在其范围内。再说一遍,目标的距离和射弹速度都没有进入计算,所以我能说的最好的调整就是模糊地朝着正确的方向前进。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + firingAngleAdjustment));
对我来说,最后的正弦对我毫无意义。 参数已经是角度,以弧度为单位,枪需要移动:目标的绝对方位减去当前的枪标(这是枪的距离)将需要转向精确指向目标),加上目标运动的射击角度调整。我完全删除那里的正弦函数。
double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(targetBearing - getGunHeadingRadians() + firingAngleAdjustment);
当然,这还取决于将枪设置为转动超过半圈(pi弧度)是否会被自动理解为将其转向另一个方向的半圈而不是......您可能最终会这样做否则就会发生许多毫无意义的枪械。
答案 1 :(得分:0)
public void onScannedRobot(ScannedRobotEvent e) // for every robots that your robot see {
setTurnRadarLeftRadians(getRadarTurnRemaining()); // Sets the robot's radar to turn left by radians
setTurnRight(e.getBearing() + 90.0D - dir / 33.0D); // Sets the robot's body to turn right by degrees, basically you are depending it in your enemy
if (((Guppy.var = var - e.getEnergy()) <= 3) && (var > 0.0D))
{
setMaxVelocity(Math.random() * 9.0D + 3); //Sets the maximum velocity of the robot measured in pixels/turn if the robot should move slower than Rules.MAX_VELOCITY (8 pixels/turn).
setAhead(Guppy.dir = dir * type);
}
setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
if (getGunHeat() == 0.0D)
{
setFire(2.9D); // how big is the damage of the bullet. The bigger the damage= bigger energy consumed
vel = e.getVelocity(); //get the enemy velocity
}
var = e.getEnergy(); // get the enemy energy
}
如果你想要,你可以玩我的这些迷你项目:
package sample;
import robocode.*;
import java.awt.Color;
import java.awt.geom.*;
import java.lang.*; // for Double and Integer objects
import java.util.*; // for collection of waves
import robocode.util.Utils;
import robocode.RobotDeathEvent;
import robocode.Rules;
import robocode.ScannedRobotEvent;
import robocode.util.Utils;
/*
A Robocode that implements the smart targeting(always attack on the nearest opponent) and circles around them
*/
public class Tutorial extends AdvancedRobot
{ boolean movingForward;
boolean peek; // Don't turn if there's a robot there
double moveAmount; // How much to move
byte moveDirection= 1;
int tooCloseToWall = 0;
int wallMargin = 60;
static final double GUN_FACTOR = 30;
static final double AIM_FACTOR = 25;
static final int AIM_START = 10;
static final int FIRE_FACTOR = 100;
private long currTime;
static final long RADARTIMEOUT = 20;
static double xForce;
static double yForce;
static double lastDistance;
private boolean radarScan;
private long lastscan;
public void run(){
setAdjustRadarForGunTurn(true);
setAdjustGunForRobotTurn(true);
// Sets these colors (robot parts): body, gun, radar, bullet, scan_arc
setBodyColor(new Color(255, 255, 255));
setGunColor(new Color(255, 255, 255));
setRadarColor(new Color(255, 255, 255));
setBulletColor(new Color(0, 0, 0));
setScanColor(new Color(255, 255, 255));
while(true) {
currTime = getTime();
turnRadarRightRadians(Double.POSITIVE_INFINITY);
turnRadarLeftRadians(Double.POSITIVE_INFINITY);
radarScan = true;
}
}
public void onScannedRobot(ScannedRobotEvent e) {
double absoluteBearing = e.getBearingRadians()+ getHeadingRadians();
double distance = e.getDistance();
double bulletPower ;
double headingRadians = getHeadingRadians();
boolean fired = false;
if(getOthers() >= 2){
xForce = xForce *.80- Math.sin(absoluteBearing) / distance;
yForce = yForce *.80 - Math.cos(absoluteBearing) / distance;
setTurnRightRadians(Utils.normalRelativeAngle(
Math.atan2(xForce + 1/getX() - 1/(getBattleFieldWidth() - getX()),
yForce + 1/getY() - 1/(getBattleFieldHeight() - getY()))
- getHeadingRadians()) );
setAhead(150- Math.abs(getTurnRemaining()));//speed
bulletPower = ( distance > 850 ? 0.1 : (distance > 700 ? 0.49 : (distance > 250 ? 1.9 : 3.0)));
bulletPower = Math.min( getEnergy()/5, Math.min( (e.getEnergy()/4) + 0.2, bulletPower));
if ((getGunHeat() <= 3.0) && (getGunTurnRemaining() == 0.0) && (bulletPower > 0.0) && (getEnergy() > 9.1)) {
// Only fire the gun when it is locked and loaded, do a radarsweep afterwards.
bulletPower=3;
setFire( bulletPower);
fired = true;
}
if ((fired == true) || (currTime >= (lastscan + RADARTIMEOUT))) {
setTurnRadarRightRadians( Double.NEGATIVE_INFINITY * Utils.normalRelativeAngle( absoluteBearing- getRadarHeadingRadians()));
lastscan = currTime;
radarScan = true;
}
// when not firing, lock on target.
//setTurnRadarRightRadians( 2.2 * Utils.normalRelativeAngle( absoluteBearing - getRadarHeadingRadians()));
//radarScan = false;
lastDistance = Double.POSITIVE_INFINITY;
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
if(lastDistance+20 > distance){
lastDistance = distance;
if(getGunHeat() < .1){
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
clearAllEvents();
}
setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + Math.max(1 - distance / (40), 0) * (e.getVelocity() / (AIM_START + Math.pow(AIM_FACTOR, distance))) * Math.sin(e.getHeadingRadians() - absoluteBearing) ));
}
}
if(getOthers() == 1){
setBodyColor(new Color(255, 0, 0));
setGunColor(new Color(255, 0, 0));
setRadarColor(new Color(255, 0, 0));
setBulletColor(new Color(255, 0, 0));
setScanColor(new Color(255, 0, 0));
double bulletPower1 = 3;
if(distance >= 700){
lastDistance = Double.POSITIVE_INFINITY;
}
else if (distance < 700 && distance > 500){
bulletPower = 3 - (( 24.5- getEnergy()) / 6);
if (getEnergy() >= 3.1 ) {
setFire(bulletPower);
lastDistance = Double.POSITIVE_INFINITY;
}
else{
lastDistance = Double.POSITIVE_INFINITY;
}
}
else if (distance <=500 && distance >=350){
bulletPower = 3 - (( 17.5- getEnergy()) / 6);
if (getEnergy() >= 3.1 ) {
setFire(bulletPower);
lastDistance = Double.POSITIVE_INFINITY;
}
else{
lastDistance = Double.POSITIVE_INFINITY;
}
}
else if (distance < 350 ){
bulletPower = 3 - (( 5- getEnergy()) / 6);
if (getEnergy() >= 3.1 ) {
setFire(bulletPower);
lastDistance = Double.POSITIVE_INFINITY;
}
else{
lastDistance = Double.POSITIVE_INFINITY;
}
}
if(lastDistance+25 > distance){
lastDistance = distance;
if(getGunHeat() < .1){
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
clearAllEvents();
clearAllEvents();
}
setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + Math.max(1 - distance / (400), 0) * (e.getVelocity() / (AIM_START + Math.pow(AIM_FACTOR, distance))) * Math.sin(e.getHeadingRadians() - absoluteBearing) ));
}
wall();
// always square off against our enemy, turning slightly toward him
setTurnRight(e.getBearing() + 90 - (10 * moveDirection));
// if we're close to the wall, eventually, we'll move away
if (tooCloseToWall > 0) tooCloseToWall--;
// normal movement: switch directions if we've stopped
if (getVelocity() == 0) {
setMaxVelocity(8);
moveDirection *= -1;
setAhead(500 * moveDirection);
}
}
}
public void onHitByBullet(HitByBulletEvent e) {
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
clearAllEvents();
}
public void onBulletMissed(BulletMissedEvent e) {
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
clearAllEvents();
}
public void onHitRobot(HitRobotEvent e) {
setTurnRadarLeft(getRadarTurnRemaining());
setTurnRadarRight(getRadarTurnRemaining());
clearAllEvents();
}
public void wall(){
//close to left, right, bottom, top wall
if(getX() <= wallMargin || getX() >= getBattleFieldWidth() - wallMargin || getY() <= wallMargin || getY() >= getBattleFieldHeight() - wallMargin){
if(tooCloseToWall <= 0){
// coming near the wall
tooCloseToWall += wallMargin;
setMaxVelocity(0); // stop!!!
}
}
}
}