package vooga.rts.gamedesign.sprite.gamesprites;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import vooga.rts.gamedesign.state.EntityState;
import vooga.rts.gamedesign.state.MovementState;
import vooga.rts.util.Location3D;
import vooga.rts.util.Pixmap;
import vooga.rts.util.Vector;
/**
* This class encompasses all classes that can affect the game directly through
* specific behavior. This class has the health behavior (can �die�) and
* velocity (can move and collide), and belong to a certain team. Setting the
* health to zero sets the isVisible boolean to false, not allowing the
* GameEntity to be painted.
*
* @author Ryan Fishel
* @author Kevin Oh
* @author Francesco Agosti
* @author Wenshun Liu
*
*/
public class GameEntity extends GameSprite {
// Default velocity magnitude
public static int DEFAULT_SPEED = 100;
private Vector myVelocity;
private int myMaxHealth;
private int myCurrentHealth;
private int myPlayerID;
private Location3D myGoal;
private Vector myOriginalVelocity;
private EntityState myEntityState;
private int mySpeed;
public GameEntity(Pixmap image, Location3D center, Dimension size,
int playerID, int health) {
super(image, center, size);
myMaxHealth = health;
myCurrentHealth = myMaxHealth;
myPlayerID = playerID;
// ALERT THIS IS JUST FOR TESTING
myOriginalVelocity = new Vector(0, 0);
myVelocity = new Vector(0, 0);
myGoal = new Location3D(center);
myEntityState = new EntityState();
mySpeed = DEFAULT_SPEED;
}
public boolean reachedGoal(double elapsedTime) {
final int CHECK_SQUARE = 6;
Vector v = getWorldLocation().difference(myGoal.to2D());
if (v.getMagnitude() < Location3D.APPROX_EQUAL) {
return true;
}
v.scale(elapsedTime);
Location3D future = new Location3D(getWorldLocation());
future.translate(v);
Line2D lineTest = new Line2D.Double(getWorldLocation().to2D(),
future.to2D());
if (lineTest.intersects(myGoal.getX() - CHECK_SQUARE / 2, myGoal.getY()
- CHECK_SQUARE / 2, CHECK_SQUARE, CHECK_SQUARE)) {
return true;
}
return false;
}
/**
* Updates the shape's location.
*/
public void update(double elapsedTime) {
if (isDead()) {
setChanged();
notifyObservers();
setVisible(true);
}
Vector v = getWorldLocation().difference(myGoal.to2D());
if (reachedGoal(elapsedTime)) {
setVelocity(v.getAngle(), 0);
myEntityState.stop();
} else {
setVelocity(v.getAngle(), getSpeed());
myEntityState.setMovementState(MovementState.MOVING);
}
Vector velocity = new Vector(myVelocity);
velocity.scale(elapsedTime);
translate(velocity);
stopMoving();
myEntityState.update(elapsedTime);
super.update(elapsedTime);
}
/**
* Moves the Unit only. Updates first the angle the Unit is facing, and then
* its location. Possible design choice error.
*/
public void move(Location3D loc) {
myGoal = loc;
}
/**
* Returns shape's velocity.
*/
public Vector getVelocity() {
return myVelocity;
}
/**
* Resets shape's velocity.
*/
public void setVelocity(double angle, double magnitude) {
myVelocity = new Vector(angle, magnitude);
}
/**
* Returns the current health of the entity.
*
* @return the current health of the entity
*/
public int getHealth() {
return myCurrentHealth;
}
/**
* Sets the health of the entity.
*
* @param health
* is the amount of health the entity will have
*/
public void setHealth(int health) {
myCurrentHealth = health;
}
/**
* Increases the max health of the entity.
*
* @param health
* is the amount of additional health the entity will get
*/
public void addMaxHealth(int health) {
myMaxHealth += health;
}
/**
* Returns the max health of the entity.
*
* @return the max health of the entity
*/
public int getMaxHealth() {
return myMaxHealth;
}
/**
* Returns the teamID the shape belongs to.
*/
public int getPlayerID() {
return myPlayerID;
}
/**
* Sets which team the entity will be on.
*
* @param playerID
* is the ID for the team that the entity is on
*/
public void setPlayerID(int playerID) {
myPlayerID = playerID;
}
/**
* Rotates the Unit by the given angle.
*
* @param angle
*/
public void turn(double angle) {
myVelocity.turn(angle);
}
/**
* Specifies whether or not two entities collide.
*
* @param gameEntity
* is the entity that is being checked for a collision
* @return true if the bounds of the two entites intersect and false if the
* bounds of the entities do not interesct
*/
public boolean collidesWith(GameEntity gameEntity) {
return getBounds().intersects(gameEntity.getBounds());
}
/**
* Translates the current center by vector v
*
* @param vector
*/
public void translate(Vector vector) {
if (vector.getMagnitude() != 0) {
getWorldLocation().translate(vector);
resetBounds();
setChanged();
notifyObservers(getWorldLocation());
}
}
/**
* Reset shape back to its original values.
*/
@Override
public void reset() {
super.reset();
myVelocity = myOriginalVelocity;
}
/**
* Returns the speed of the entity.
*
* @return the speed of the entity
*/
public int getSpeed() {
return mySpeed;
}
/**
* Sets the speed of the entity.
*
* @param speed
* is the speed that the entity will have
*/
public void setSpeed(int speed) {
mySpeed = speed;
}
public void changeHealth(int change) {
myCurrentHealth -= change;
}
/**
* Checks to see if an GameEntity is dead.
*
* @return true if the GameEntity has been killed and false if the
* GameEntity is still alive.
*/
public boolean isDead() {
return myCurrentHealth <= 0;
}
/**
* Kills the GameEntity by setting its current health value to zero.
*/
public void die() {
myCurrentHealth = 0;
}
@Override
public void paint(Graphics2D pen) {
if (!isDead()) {
super.paint(pen);
}
}
/**
* Returns the state of the entity such as its attacking state or movement
* state.
*
* @return the state of the entity.
*/
public EntityState getEntityState() {
return myEntityState;
}
/**
* If the entity is in a stationary state, it stops moving.
*/
public void stopMoving() {
if (!myEntityState.canMove()) {
setVelocity(getVelocity().getAngle(), 0);
myGoal = new Location3D(getWorldLocation());
}
}
/**
* Sets the goal location that the entity will move to.
*
* @param goal
* is the location that the entity wants to move to
*/
public void setGoalLocation(Location3D goal) {
myGoal = goal;
}
}