Module/Movement/AntiGravity
Jump to navigation
Jump to search
package jab.movement; import java.awt.Graphics2D; import java.util.Enumeration; import java.util.Iterator; import java.util.Vector; import jab.BulletInfoEnemy; import jab.Enemy; import jab.Module; import jab.Movement; /** * Credits * AntiGravityBot - A robot by Alisdair Owens */ public class AntiGravity extends Movement { public Vector<GravPoint> gravPoints; public AntiGravity(Module bot) { super(bot); gravPoints = new Vector<GravPoint>(); } public void move() { gravPoints.clear(); addGravPoints(); calculateForceAndMove(); } private double midpointstrength = 0; // The strength of the gravity point in the middle of the field private int midpointcount = 0; // Number of turns since that strength was changed. private void addGravPoints() { /** Cycle through all the enemies. **/ Enumeration<Enemy> e = bot.enemies.elements(); while (e.hasMoreElements()) { Enemy enemy = e.nextElement(); gravPoints.add(new GravPoint(enemy.x, enemy.y, -1000)); } /** Cycle through all the enemy bullets. **/ Enumeration<BulletInfoEnemy> enemyBullets = bot.enemyBullets.elements(); while (enemyBullets.hasMoreElements()) { BulletInfoEnemy bullet = enemyBullets.nextElement(); gravPoints.add(new GravPoint(bullet.x, bullet.y, -1000)); } /** * The next section adds a middle point with a random (positive or * negative) strength. The strength changes every 5 turns, and goes * between -1000 and 1000. */ midpointcount++; if (midpointcount > 5) { midpointcount = 0; midpointstrength = (Math.random() * 2000) - 1000; } gravPoints.add(new GravPoint(bot.getBattleFieldWidth() / 2, bot .getBattleFieldHeight() / 2, midpointstrength)); /** Other examples of GravPoints * */ // Corners gravPoints.add(new GravPoint(bot.getBattleFieldWidth(), bot .getBattleFieldHeight(), -1000)); gravPoints.add(new GravPoint(0, bot.getBattleFieldHeight(), -1000)); gravPoints.add(new GravPoint(bot.getBattleFieldWidth(), 0, -1000)); gravPoints.add(new GravPoint(0, 0, -1000)); // GravPoint at random positions of the walls gravPoints.add(new GravPoint(Math.random() * bot.getBattleFieldWidth(), bot.getBattleFieldHeight(), -1000)); gravPoints.add(new GravPoint(bot.getBattleFieldWidth(), Math.random() * bot.getBattleFieldHeight(), -1000)); gravPoints.add(new GravPoint(0, Math.random() * bot.getBattleFieldHeight(), -1000)); gravPoints.add(new GravPoint(Math.random() * bot.getBattleFieldWidth(), 0, -1000)); } private void calculateForceAndMove() { double xforce = 0; double yforce = 0; double force; double ang; Iterator<GravPoint> i = gravPoints.iterator(); while (i.hasNext()) { GravPoint gravPoint = i.next(); force = gravPoint.power / Math.pow(getRange(bot.getX(), bot.getY(), gravPoint.x, gravPoint.y), 2); // Find the bearing from the point to us ang = normaliseBearing(Math.PI / 2 - Math.atan2(bot.getY() - gravPoint.y, bot.getX() - gravPoint.x)); // Add the components of this force to the total force in their // respective directions xforce += Math.sin(ang) * force; yforce += Math.cos(ang) * force; } /** * The following four lines add wall avoidance. They will only affect us * if the bot is close to the walls due to the force from the walls * decreasing at a power 3. */ xforce += 5000 / Math.pow(getRange(bot.getX(), bot.getY(), bot .getBattleFieldWidth(), bot.getY()), 3); xforce -= 5000 / Math.pow(getRange(bot.getX(), bot.getY(), 0, bot .getY()), 3); yforce += 5000 / Math.pow(getRange(bot.getX(), bot.getY(), bot.getX(), bot.getBattleFieldHeight()), 3); yforce -= 5000 / Math.pow(getRange(bot.getX(), bot.getY(), bot.getX(), 0), 3); // Move in the direction of our resolved force. goTo(bot.getX() - xforce, bot.getY() - yforce); } /** Move towards an x and y coordinate **/ private void goTo(double x, double y) { double dist = 20; double angle = Math.toDegrees(absbearing(bot.getX(), bot.getY(), x, y)); double r = turnTo(angle); bot.setAhead(dist * r); } /** * Turns the shortest angle possible to come to a heading, then returns the * direction the the bot needs to move in. */ private int turnTo(double angle) { double ang; int dir; ang = normaliseBearing(bot.getHeading() - angle); if (ang > 90) { ang -= 180; dir = -1; } else if (ang < -90) { ang += 180; dir = -1; } else { dir = 1; } bot.setTurnLeft(ang); return dir; } // if a bearing is not within the -pi to pi range, alters it to provide the // shortest angle private double normaliseBearing(double ang) { if (ang > Math.PI) ang -= 2 * Math.PI; if (ang < -Math.PI) ang += 2 * Math.PI; return ang; } // returns the distance between two x,y coordinates private double getRange(double x1, double y1, double x2, double y2) { double xo = x2 - x1; double yo = y2 - y1; double h = Math.sqrt(xo * xo + yo * yo); return h; } // gets the absolute bearing between to x,y coordinates private double absbearing(double x1, double y1, double x2, double y2) { double xo = x2 - x1; double yo = y2 - y1; double h = getRange(x1, y1, x2, y2); if (xo > 0 && yo > 0) { return Math.asin(xo / h); } if (xo > 0 && yo < 0) { return Math.PI - Math.asin(xo / h); } if (xo < 0 && yo < 0) { return Math.PI + Math.asin(-xo / h); } if (xo < 0 && yo > 0) { return 2.0 * Math.PI - Math.asin(-xo / h); } return 0; } public void onPaint(Graphics2D g) { Enumeration<GravPoint> e = gravPoints.elements(); while (e.hasMoreElements()) { GravPoint gp = e.nextElement(); g.drawOval((int) gp.x - 5, (int) gp.y - 5, 10, 10); } } /** Holds the x, y, and strength info of a gravity point* */ class GravPoint { public double x, y, power; public GravPoint(double pX, double pY, double pPower) { x = pX; y = pY; power = pPower; } } }