379 lines
11 KiB
Java
379 lines
11 KiB
Java
package worms.model;
|
|
|
|
import be.kuleuven.cs.som.annotate.Raw;
|
|
import worms.util.Coordinate;
|
|
|
|
import static java.lang.Math.*;
|
|
|
|
/**
|
|
* A class of GameObjects involving a world, a location and a radius.
|
|
*
|
|
* @version 3.0
|
|
* @author Arthur Bols & Leen Dereu
|
|
*/
|
|
public abstract class GameObject {
|
|
|
|
// region Constructor
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @param world
|
|
* @param location
|
|
* @param radius
|
|
*
|
|
* @post ...
|
|
* |setWorld(world)
|
|
* @post ...
|
|
* |setLocation(location)
|
|
* @post ...
|
|
* |setRadius(radius)
|
|
*/
|
|
protected GameObject(World world, double[] location, double radius) {
|
|
this(world, Coordinate.create(location), radius);
|
|
|
|
}
|
|
|
|
/**
|
|
* @param world
|
|
* @param location
|
|
* @param radius
|
|
*
|
|
* @post ...
|
|
* |new.getLocation() == location
|
|
* @post ...
|
|
* |new.getRadius() == radius
|
|
* @post ...
|
|
* |if (isValidWorld(world))
|
|
* | world.add(this)
|
|
* @post ...
|
|
* |new.getWorld() == world
|
|
*
|
|
* @throws IllegalArgumentException ...
|
|
* |!isValidLocation(location)
|
|
*/
|
|
protected GameObject(World world, Coordinate location, double radius) {
|
|
if (!isValidLocation(location)) throw new IllegalArgumentException("Illegal location");
|
|
setLocation(location);
|
|
setRadius(radius);
|
|
if (isValidWorld(world)) world.add(this);
|
|
setWorld(world);
|
|
}
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
// region world
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.world
|
|
*/
|
|
public World getWorld() {
|
|
return this.world;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param world
|
|
*
|
|
* @return ...
|
|
* |result == world != null && !world.hasActiveGame() && !world.isTerminated()
|
|
*/
|
|
public static boolean isValidWorld(World world) {
|
|
return world != null && !world.hasActiveGame() && !world.isTerminated();
|
|
}
|
|
|
|
|
|
/**
|
|
* @param world
|
|
*
|
|
* @post ...
|
|
* |if (world == null)
|
|
* | this.world = null
|
|
* | return
|
|
* @post ...
|
|
* |new.getWorld() == world
|
|
*
|
|
* @throws IllegalArgumentException ...
|
|
* |!isValidWorld(world)
|
|
*/
|
|
public void setWorld(World world) throws IllegalArgumentException {
|
|
if (world == null) {
|
|
this.world = null;
|
|
return;
|
|
}
|
|
if (!isValidWorld(world)) throw new IllegalArgumentException();
|
|
this.world = world;
|
|
}
|
|
|
|
protected World world;
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
// region location
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.location
|
|
*/
|
|
public Coordinate getLocation() {
|
|
return this.location;
|
|
}
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.location.toArray()
|
|
*/
|
|
public double[] getLocationArray() {
|
|
return this.location.toArray();
|
|
}
|
|
|
|
/**
|
|
* @param location
|
|
*
|
|
* @post ...
|
|
* |if (!isValidLocation(location)
|
|
* | if (!(location.getX() - radius < 0) || !(location.getX() + radius > getWorld().getWidth()) ||
|
|
* | !(location.getY() + radius > getWorld().getHeight()) || !(location.getY() - radius < 0))
|
|
* | world.remove(this)
|
|
* @post ...
|
|
* |if (isValidLocation(location)
|
|
* | new.getLocation() == location
|
|
*
|
|
* @throws IllegalArgumentException ...
|
|
* |!isValidLocation(location) && (location.getX() - radius < 0 ||
|
|
* |location.getX() + radius > getWorld().getWidth() ||
|
|
* |location.getY() + radius > getWorld().getHeight() ||
|
|
* |location.getY() - radius < 0)
|
|
*/
|
|
protected void setLocation(Coordinate location) throws IllegalArgumentException {
|
|
|
|
if (!isValidLocation(location)) {
|
|
if (!(location.getX() - radius < 0) ||
|
|
!(location.getX() + radius > getWorld().getWidth()) ||
|
|
!(location.getY() + radius > getWorld().getHeight()) ||
|
|
!(location.getY() - radius < 0)) {
|
|
world.remove(this);
|
|
} else throw new IllegalArgumentException();
|
|
}
|
|
this.location = location;
|
|
}
|
|
|
|
/**
|
|
* @param location
|
|
*
|
|
* @post ...
|
|
* |new.getLocation() == Coordinate.create(location)
|
|
*/
|
|
protected void setLocation(double[] location) {
|
|
|
|
setLocation(Coordinate.create(location));
|
|
}
|
|
|
|
|
|
/**
|
|
* @param location
|
|
*
|
|
* @return ...
|
|
* |if (world == null)
|
|
* | result == !Double.isNaN(location.getX()) && !Double.isNaN(location.getY())
|
|
* |result == !Double.isNaN(location.getX()) && !Double.isNaN(location.getY()) &&
|
|
* | !(location.getX() - getRadius() < 0) && !(location.getX() + getRadius() > getWorld().getWidth()) &&
|
|
* | !(location.getY() + getRadius() > getWorld().getHeight()) && !(location.getY() - getRadius() < 0) &&
|
|
* | getWorld().isPassable(location)
|
|
*/
|
|
protected boolean isValidLocation(Coordinate location) {
|
|
double radius = getRadius();
|
|
|
|
if (world == null) {
|
|
return !Double.isNaN(location.getX()) &&
|
|
!Double.isNaN(location.getY());
|
|
}
|
|
return !Double.isNaN(location.getX()) &&
|
|
!Double.isNaN(location.getY()) &&
|
|
!(location.getX() - radius < 0) &&
|
|
!(location.getX() + radius > getWorld().getWidth()) &&
|
|
!(location.getY() + radius > getWorld().getHeight()) &&
|
|
!(location.getY() - radius < 0) && getWorld().isPassable(location);
|
|
}
|
|
|
|
protected Coordinate location;
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
// region radius
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.radius
|
|
*/
|
|
public double getRadius() {
|
|
return this.radius;
|
|
}
|
|
|
|
/**
|
|
* @param radius
|
|
*
|
|
* @post ...
|
|
* |new.getRadius() == radius
|
|
*
|
|
* @throws IllegalArgumentException ...
|
|
* |!canHaveAsRadius(radius)
|
|
*/
|
|
protected void setRadius(double radius) {
|
|
if (!canHaveAsRadius(radius)) throw new IllegalArgumentException();
|
|
this.radius = radius;
|
|
}
|
|
|
|
protected double radius;
|
|
|
|
/**
|
|
* @param radius
|
|
*
|
|
* @return ...
|
|
* |result == !Double.isNaN(radius) && radius > 0
|
|
*/
|
|
@Raw
|
|
private boolean canHaveAsRadius(double radius) {
|
|
return !Double.isNaN(radius) && radius > 0;
|
|
}
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
// region mass
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.mass
|
|
*/
|
|
public double getMass() {
|
|
return this.mass;
|
|
}
|
|
|
|
/**
|
|
* @param radius
|
|
* @param rho
|
|
*
|
|
* @post ...
|
|
* |new.getMass() == rho * (4.0 / 3.0 * PI * pow(radius, 3.0)
|
|
*/
|
|
protected void setMass(double radius, double rho) {
|
|
|
|
this.mass = rho * (4.0 / 3.0 * PI * pow(radius, 3.0));
|
|
}
|
|
|
|
protected double mass;
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
|
|
// region distance calc
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @param o
|
|
*
|
|
* @return ...
|
|
* |result == getDistance(o.getLocation(), o.getRadius())
|
|
*/
|
|
public double getDistance(GameObject o) {
|
|
|
|
return getDistance(o.getLocation(), o.getRadius());
|
|
}
|
|
|
|
/**
|
|
* @param otherLocation
|
|
* @param radius
|
|
*
|
|
* @return ...
|
|
* |result == Math.round((Math.sqrt(Math.pow((otherLocation.getX() - this.location.getX()), 2) + Math.pow(
|
|
* |(otherLocation.getY() - this.location.getY()), 2)) - radius - this.radius) * 10000.0) / 10000.0
|
|
*/
|
|
public double getDistance(Coordinate otherLocation, double radius) {
|
|
|
|
return Math.round((Math.sqrt(Math.pow((otherLocation.getX() - this.location.getX()), 2) +
|
|
Math.pow((otherLocation.getY() - this.location.getY()), 2)) - radius - this.radius) * 10000.0) / 10000.0;
|
|
}
|
|
|
|
/**
|
|
* @param start
|
|
* @param end
|
|
*
|
|
* @return ...
|
|
* |result == Math.sqrt(Math.pow(Math.abs(start.getX() - end.getX()), 2) +
|
|
* | Math.pow(Math.abs(start.getY() - end.getY()), 2))
|
|
*/
|
|
public static double getDistance(Coordinate start, Coordinate end) {
|
|
return Math.sqrt(Math.pow(Math.abs(start.getX() - end.getX()), 2) +
|
|
Math.pow(Math.abs(start.getY() - end.getY()), 2));
|
|
}
|
|
|
|
/**
|
|
* @param o
|
|
*
|
|
* @return ...
|
|
* |if (o.equals(this))
|
|
* | result == Double.NaN
|
|
* |Coordinate otherLoc = o.getLocation()
|
|
* |result == Math.abs(Math.atan(Math.abs(this.location.getX() - otherLoc.getX()) /
|
|
* | Math.abs(this.location.getY() - otherLoc.getY())) - Math.PI / 2.0)
|
|
*/
|
|
public double getAngle(GameObject o) {
|
|
|
|
if (o.equals(this)) return Double.NaN;
|
|
|
|
Coordinate otherLoc = o.getLocation();
|
|
|
|
return Math.abs(Math.atan(Math.abs(this.location.getX() - otherLoc.getX()) /
|
|
Math.abs(this.location.getY() - otherLoc.getY())) - Math.PI / 2.0);
|
|
}
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
|
|
// region destructor
|
|
//===================================================================================
|
|
|
|
/**
|
|
* @return ...
|
|
* |result == this.terminated
|
|
*/
|
|
public boolean isTerminated() {
|
|
return this.terminated;
|
|
}
|
|
|
|
/**
|
|
* @post ...
|
|
* |new.isTerminated() == true
|
|
* @post ...
|
|
* |if (this.world != null)
|
|
* | this.world.remove(this)
|
|
*/
|
|
public void terminate() {
|
|
this.terminated = true;
|
|
if (this.world != null) {
|
|
this.world.remove(this);
|
|
}
|
|
}
|
|
|
|
private boolean terminated = false;
|
|
|
|
|
|
// ===================================================================================
|
|
// endregion
|
|
|
|
} |