/**
* @param ship The ship to move
* @return returns a double representing how many radians away from the desired angle the ship is.
* This is to be used for considering when to fire when the destination is a Ship
*/
public static double[] moveShipInCombat(Ship ship) {
double destX = ship.getTarget().getX();
double destY = ship.getTarget().getY();
double directTheta = Math.atan2(
destY - ship.getY(),
destX - ship.getX());
double distanceSqrd = Point2D.distanceSq(destX, destY, ship.getX(), ship.getY());
if (Rimscape.DEBUG && Rimscape.gameInProgress && MainScreen.isScreenTarget(ship))
System.out.println("moving in combat, distance = " + Math.sqrt(distanceSqrd));
//FIXME: I don't like how this works
//if (distanceSqrd < Ship.RANGE_SQRD)
// directTheta += (chanceRand.nextDouble()*2 - 1)*((double)(Constants.DIFFICULTY_MAX - Rimscape.difficulty)/Constants.DIFFICULTY_DEFAULT);
double dx = ship.getDx(), dy = ship.getDy();
double velocityTheta = Math.atan2(dy, dx);
double offset = circleMod(velocityTheta - directTheta);
if (distanceSqrd < Ship.RANGE_SQRD/9) {
ship.accel();
}
else if (distanceSqrd < Ship.RANGE_SQRD/6) {
ship.reverse();
}
else if (distanceSqrd < Ship.RANGE_SQRD/4) {
//coast
}
else if (distanceSqrd < Ship.RANGE_SQRD/2) {
ship.decel();
}
else {
double accel = ship.getStatMax(Ship.STAT_ACCELERATION);
double vSqrd = dx*dx + dy*dy;
double stuffUnderRadical = 0; //calculated when it's first checked to avoid an unnecessary sqrt
//stuffUnderRadical < 0 means that Math.sqrt() check will return NaN
// this is because the equation checks for when the velocity will equal 0 if the brakes are hit now (Quadratic regression)
// therefore an imaginary root means you never reached 0 and thus didn't reach your destination
// it also means that if we stop now we'll stop waaay short of our destination so go further
//Math.abs(offset) < THETA_TOLERANCE means don't hit the gas if you're not facing the right direction
//however if vSqrd < accel, then this check ^^^ probably doesn't make sense because the velocity
//used to create the offset is so small that deriving an angle from it isn't practical
if (Math.abs(offset) < THETA_TOLERANCE/2 && (stuffUnderRadical = vSqrd - 2*accel*Math.sqrt(distanceSqrd)) < 0
//If other checks pass, check finalV < accel
|| (vSqrd < accel || (2*Math.sqrt(vSqrd) - Math.sqrt(stuffUnderRadical)) < accel*accel)) {
if (Rimscape.DEBUG && Rimscape.gameInProgress && MainScreen.isScreenTarget(ship))
System.out.println("speeding up to target");
if (vSqrd < REALLY_FAST*REALLY_FAST*2) //TODO: new change...test it
ship.accel();
}
else {
if (Rimscape.DEBUG && Rimscape.gameInProgress && MainScreen.isScreenTarget(ship))
System.out.println("slowing down");
ship.decel();
}
}
double desiredTheta;
if (distanceSqrd < Ship.RANGE_SQRD)
desiredTheta = directTheta;
else
desiredTheta = directTheta - (Math.abs(offset) < THETA_TOLERANCE ? offset : 0);
double thetaToGo = circleMod(desiredTheta - ship.getTheta());
if (thetaToGo < -ship.getStat(Ship.STAT_ROTATION))
ship.turnLeft();
else if (thetaToGo > ship.getStat(Ship.STAT_ROTATION))
ship.turnRight();
else
ship.setTheta(desiredTheta);
//return new double[] {thetaToGo, distanceSqrd};
return new double[] {circleMod(directTheta - ship.getTheta()), distanceSqrd};
}
There she is Hopefully the comments help to illustrate what’s going on. I felt this might be appropriate for the Shared Code forum, but since I’m interested in feedback and suggestions and it’s also directly related to AI, I felt this forum was better.
Let me know what you guys think! If you wanna see it in action, start up Rimscape and piss someone off