use of spacesettlers.objects.AbstractObject in project spacesettlers by amymcgovern.
the class Toroidal2DPhysics method isPathClearOfObstructions.
/**
* Check to see if following a straight line path between two given locations would result in a collision with a provided set of obstructions
*
* @author Andrew and Thibault
*
* @param startPosition the starting location of the straight line path
* @param goalPosition the ending location of the straight line path
* @param obstructions an Set of AbstractObject obstructions (i.e., if you don't wish to consider mineable asteroids or beacons obstructions)
* @param freeRadius used to determine free space buffer size
* @return Whether or not a straight line path between two positions contains obstructions from a given set
*/
public boolean isPathClearOfObstructions(Position startPosition, Position goalPosition, Set<AbstractObject> obstructions, int freeRadius) {
// Shortest straight line path from startPosition to goalPosition
Vector2D pathToGoal = findShortestDistanceVector(startPosition, goalPosition);
// Distance of straight line path
double distanceToGoal = pathToGoal.getMagnitude();
// Boolean showing whether or not the path is clear
boolean pathIsClear = true;
// Calculate distance between obstruction center and path (including buffer for ship movement)
// Uses hypotenuse * sin(theta) = opposite (on a right hand triangle)
// Vector from start position to obstruction
Vector2D pathToObstruction;
// Angle between vector from start position to obstruction
double angleBetween;
// Loop through obstructions
for (AbstractObject obstruction : obstructions) {
// If the distance to the obstruction is greater than the distance to the end goal, ignore the obstruction
pathToObstruction = findShortestDistanceVector(startPosition, obstruction.getPosition());
if (pathToObstruction.getMagnitude() > distanceToGoal) {
continue;
}
// Ignore angles > 90 degrees
angleBetween = Math.abs(pathToObstruction.angleBetween(pathToGoal));
if (angleBetween > Math.PI / 2) {
continue;
}
// Compare distance between obstruction and path with buffer distance
if (pathToObstruction.getMagnitude() * Math.sin(angleBetween) < obstruction.getRadius() + freeRadius * 1.5) {
pathIsClear = false;
break;
}
}
return pathIsClear;
}
use of spacesettlers.objects.AbstractObject in project spacesettlers by amymcgovern.
the class Toroidal2DPhysics method advanceTime.
/**
* Move all moveable objects and handle power ups.
*/
public void advanceTime(int currentTimeStep, Map<UUID, SpaceSettlersPowerupEnum> powerups) {
this.currentTimeStep = currentTimeStep;
// heal any base injuries
for (Base base : bases) {
base.updateEnergy(base.getHealingIncrement());
}
// detect collisions across all objects
detectCollisions();
// get the power ups and create any objects (weapons) as necessary
for (UUID key : powerups.keySet()) {
AbstractObject swobject = getObjectById(key);
// if the object is not alive or it is not actionable, then ignore this
if (!swobject.isAlive() || (!(swobject instanceof AbstractActionableObject))) {
continue;
}
// otherwise, handle the power up
handlePowerup((AbstractActionableObject) swobject, powerups.get(key));
}
// now move all objects that are moveable (which may include weapons)
for (AbstractObject object : allObjects) {
// skip non-moveable objects or dead object
if (!object.isMoveable() || !object.isAlive()) {
continue;
}
Position currentPosition = object.getPosition();
// is it a ship that can be controlled?
if (object.isControllable()) {
Ship ship = (Ship) object;
AbstractAction action = ship.getCurrentAction();
// handle a null action
if (action == null) {
action = new DoNothingAction();
}
// need to clone the ship and space because otherwise the ship can affect
// itself inside AbstractAction
Movement actionMovement = action.getMovement(this.deepClone(), ship.deepClone());
Position newPosition = applyMovement(currentPosition, actionMovement, timeStep);
if (newPosition.isValid()) {
ship.setPosition(newPosition);
} else {
ship.setPosition(currentPosition);
}
// spend ship energy proportional to its acceleration (old formula used velocity) and mass (new for space settlers
// since resources cost mass)
// double penalty = ENERGY_PENALTY * -Math.abs(ship.getPosition().getTotalTranslationalVelocity());
double angularAccel = Math.abs(actionMovement.getAngularAccleration());
double angularInertia = (3.0 * ship.getMass() * ship.getRadius() * angularAccel) / 2.0;
double linearAccel = actionMovement.getTranslationalAcceleration().getMagnitude();
double linearInertia = ship.getMass() * linearAccel;
int penalty = (int) Math.floor(ENERGY_PENALTY * (angularInertia + linearInertia));
ship.updateEnergy(-penalty);
// this isn't the most general fix but it will work for now (also has to be done for bases)
if (ship.isShielded()) {
ship.updateEnergy(-PowerupToggleShield.SHIELD_STEP_COST);
}
// if (!ship.isAlive()) {
// System.out.println("Ship " + ship.getTeamName() + ship.getId() + " is dead");
// }
} else {
// move all other types of objects
Position newPosition = moveOneTimestep(currentPosition);
object.setPosition(newPosition);
}
// if any ships or bases are frozen, decrement their frozen count
if (object instanceof AbstractActionableObject && !object.isControllable()) {
AbstractActionableObject actionable = (AbstractActionableObject) object;
actionable.decrementFreezeCount();
}
}
// go through and see if any bases have died
Set<Base> basesClone = new LinkedHashSet<Base>(bases);
for (Base base : basesClone) {
// this isn't the most general fix but it will work for now (also has to be done for bases)
if (base.isShielded()) {
base.updateEnergy(-PowerupToggleShield.SHIELD_STEP_COST);
}
if (!base.isAlive()) {
base.setAlive(false);
removeObject(base);
base.getTeam().removeBase(base);
}
}
// from when it was called inside updateEnergy
for (Ship ship : ships) {
if (ship.getEnergy() <= 0 && ship.isAlive() == true) {
// drop any resources that the ship was carrying
ResourcePile resources = ship.getResources();
// Spawn a new AiCore with the same velocity magnitude and direction as its parent ship.
// handle dropping the core if the ship died
Position corePosition = ship.getPosition();
corePosition.setTranslationalVelocity(ship.getPosition().getTranslationalVelocity());
corePosition.setAngularVelocity(ship.getPosition().getAngularVelocity());
AiCore shipCore = new AiCore(corePosition, ship.getTeamName(), ship.getTeamColor());
this.addObject(shipCore);
if (resources.getTotal() > 0) {
// Position newPosition = ship.getPosition();
// newPosition.setTranslationalVelocity(new Vector2D(0,0));
// newPosition.setAngularVelocity(0.0);
// Asteroid newAsteroid = new Asteroid(newPosition, true, ship.getRadius(), true, resources);
// this.addObject(newAsteroid);
// distributeResourcesToNearbyAsteroids(ship.getPosition(), resources);
// System.out.println("Adding a new asteroid with resources " + newAsteroid.getResources().getTotal() +
// " due to death, total is " + asteroids.size());
// System.out.println("Ship died and " + resources.getTotal() + " has been added to an asteroid");
}
// set the ship to dead last (so we can grab its resources first)
ship.setAlive(false);
}
}
}
use of spacesettlers.objects.AbstractObject in project spacesettlers by amymcgovern.
the class Toroidal2DPhysics method detectCollisions.
/**
* Step through all the objects and ensure they are not colliding. If they are,
* call the collision handler for those objects. Sometimes you bounce (asteroids)
* and sometimes you pick the object up (beacons), etc.
*/
private void detectCollisions() {
// would prefer to iterate over the set (as this is inefficient) but
// the set iterator collides a with b and then b with a, allowing them to
// pass through one another!
AbstractObject[] allObjectsArray = (AbstractObject[]) allObjects.toArray(new AbstractObject[allObjects.size()]);
// loop through all pairs of objects and see if they are colliding
for (int i = 0; i < allObjectsArray.length; i++) {
AbstractObject object1 = allObjectsArray[i];
if (!object1.isAlive()) {
continue;
}
for (int j = i + 1; j < allObjectsArray.length; j++) {
AbstractObject object2 = allObjectsArray[j];
if (!object2.isAlive()) {
continue;
}
// skip them if they are the same object
if (object1.equals(object2)) {
continue;
}
double distance = findShortestDistance(object1.getPosition(), object2.getPosition());
if (distance < (object1.getRadius() + object2.getRadius())) {
collisionHandler.collide(object1, object2, this);
}
}
}
}
use of spacesettlers.objects.AbstractObject in project spacesettlers by amymcgovern.
the class HumanTeamClient method getMovementStart.
/**
* Look at the last key pressed by the human and do its movement
*/
@Override
public Map<UUID, AbstractAction> getMovementStart(Toroidal2DPhysics space, Set<AbstractActionableObject> actionableObjects) {
HashMap<UUID, AbstractAction> actions = new HashMap<UUID, AbstractAction>();
for (AbstractObject actionable : actionableObjects) {
if (actionable instanceof Ship) {
// get the current position
Ship ship = (Ship) actionable;
Position myPosition = ship.getPosition();
Vector2D currentVelocity = myPosition.getTranslationalVelocity();
RawAction action = null;
double angularVel = myPosition.getAngularVelocity();
// if the key was up or down, accelerate along the current line
if (lastKeyPressed == HumanKeyPressed.UP) {
Vector2D newVel = new Vector2D(HUMAN_ACCEL * Math.cos(myPosition.getOrientation()), HUMAN_ACCEL * Math.sin(myPosition.getOrientation()));
newVel.add(currentVelocity);
action = new RawAction(newVel, 0);
} else if (lastKeyPressed == HumanKeyPressed.DOWN) {
Vector2D newVel = new Vector2D(-HUMAN_ACCEL * Math.cos(myPosition.getOrientation()), -HUMAN_ACCEL * Math.sin(myPosition.getOrientation()));
newVel.add(currentVelocity);
action = new RawAction(newVel, 0);
}
// if the key was right or left, turn
if (lastKeyPressed == HumanKeyPressed.RIGHT) {
action = new RawAction(0, HUMAN_TURN_ACCEL);
} else if (lastKeyPressed == HumanKeyPressed.LEFT) {
action = new RawAction(0, -HUMAN_TURN_ACCEL);
}
// was the mouse clicked?
if (lastMouseClick != null) {
if (mouseClickMove == null || mouseClickMove.isMovementFinished(space) || space.findShortestDistance(lastMouseClick, myPosition) > CLICK_DISTANCE) {
mouseClickMove = new MoveAction(space, myPosition, lastMouseClick);
graphicsToAdd.add(new StarGraphics(3, super.teamColor, lastMouseClick));
LineGraphics line = new LineGraphics(myPosition, lastMouseClick, space.findShortestDistanceVector(myPosition, lastMouseClick));
line.setLineColor(super.teamColor);
graphicsToAdd.add(line);
}
actions.put(actionable.getId(), mouseClickMove);
} else {
actions.put(actionable.getId(), action);
}
} else {
// can't really control anything but the ship
actions.put(actionable.getId(), new DoNothingAction());
}
}
return actions;
}
use of spacesettlers.objects.AbstractObject in project spacesettlers by amymcgovern.
the class HumanTeamClient method getMovementEnd.
@Override
public void getMovementEnd(Toroidal2DPhysics space, Set<AbstractActionableObject> actionableObjects) {
// reset so the human has to press again to move again (otherwise
// it does strange things like fly when you don't tell it anything on
// acceleration!)
lastKeyPressed = HumanKeyPressed.NONE;
for (AbstractObject actionable : actionableObjects) {
if (actionable instanceof Ship) {
Ship ship = (Ship) actionable;
if (!ship.isAlive()) {
lastMouseClick = null;
mouseClickMove = null;
}
}
}
}
Aggregations