The first function returns the Area in which the target probably will move during the time the bullet travels, cropped so that it doesn't include any area outside the battle field. The second functions returns an array with the relative angles to the edges of the area from the gunners point of view.
static Area escapeArea(Point2D gunLocation, Point2D targetLocation, double forwardAngle, double backwardAngle, Rectangle2D battleField, double bulletPower, double targetVelocity) { double distance = gunLocation.distance(targetLocation); double maxDistance = targetVelocity * travelTime(distance, bulletVelocity(bulletPower)); double bearingToGun = pointsToAngle(targetLocation, gunLocation); Area escapeArea; Point2D point = new Point2D.Double(); Polygon escapePolygon = new Polygon(); toLocation(bearingToGun, 5.0, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun - forwardAngle, maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun - 90.0, maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun - (180.0 - backwardAngle), maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun - 180.0, 5.0, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun + (180.0 - backwardAngle), maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun + 90.0, maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); toLocation(bearingToGun + forwardAngle, maxDistance, targetLocation, point); escapePolygon.addPoint((int)point.getX(), (int)point.getY()); escapeArea = new Area(escapePolygon); escapeArea.intersect(new Area(battleField)); return escapeArea; } static double[] escapeMinMaxAngles(Point2D gunLocation, Point2D targetLocation, Area escapeArea) { double[] angles = new double[2]; double min = java.lang.Double.POSITIVE_INFINITY; double max = java.lang.Double.NEGATIVE_INFINITY; double bearingToTarget = pointsToAngle(gunLocation, targetLocation); PathIterator pathIterator = escapeArea.getPathIterator(null); double[] points = new double[6]; Point2D point = new Point2D.Double(); while (!pathIterator.isDone()) { int type = pathIterator.currentSegment(points); if (type != java.awt.geom.PathIterator.SEG_CLOSE) { point.setLocation(points[0], points[1]); double angle = pointsToAngle(gunLocation, point); angle = normalRelativeAngle(angle - bearingToTarget); if (angle < min) { min = angle; } if (angle > max) { max = angle; } } pathIterator.next(); } angles[0] = min; angles[1] = max; return angles; }
In order to use right off this page you'll need to also implement some of the functions from Marshmallow/RobotUtilsCode.