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;
}
}
}