package ch.zhaw.pm2.racetrack; import ch.zhaw.pm2.racetrack.given.CarSpecification; import ch.zhaw.pm2.racetrack.strategy.MoveStrategy; /** * Class representing a car on the racetrack. * Uses {@link PositionVector} to store current position on the track grid and current velocity vector. * Each car has an identifier character which represents the car on the racetrack board. * Also keeps the state, if the car is crashed (not active anymore). The state can not be changed back to uncrashed. * The velocity is changed by providing an acceleration vector. * The car is able to calculate the endpoint of its next position and on request moves to it. */ public class Car implements CarSpecification { /** * Car identifier used to represent the car on the track */ private final char id; /** * Current position of the car on the track grid using a {@link PositionVector} */ private PositionVector position; /** * Points that car is holding for determining winner. */ private int winPoints; /** * Current velocity of the car using a {@link PositionVector} */ private PositionVector velocity = new PositionVector(0, 0); /** * Indicator if the car has crashed */ private boolean crashed = false; /** * Current move strategy */ private MoveStrategy moveStrategy; /** * Constructor for class Car * * @param id unique Car identification * @param position initial position of the Car */ public Car(char id, PositionVector position) { this.id = id; setPosition(position); } /** * Returns the id of the car. * * @return id of the car. */ public char getID() { return id; } public void increaseWinPoints() { winPoints++; } public void deductWinPoints() { winPoints--; } public int getWinPoints() { return winPoints; } /** * Returns the current velocity of the car as a PositionVector. * * @return velocity current velocity of the car. */ public PositionVector getVelocity() { return velocity; } /** * Set this Car position directly, regardless of current position and velocity. * This should only be used by the game controller in rare cases to set the crash or winning position. * The next position is normaly automatically calculated and set in the {@link #move()} method. * * @param position The new position to set the car directly to. * @throws IllegalArgumentException if invalid PositionVector is given. */ @Override public void setPosition(final PositionVector position) { if (position.getX() < 0 || position.getY() < 0) { throw new IllegalArgumentException(); } else { this.position = position; } } /** * Return the position that will apply after the next move at the current velocity. * Does not complete the move, so the current position remains unchanged. * * @return Expected position after the next move */ @Override public PositionVector nextPosition() { return new PositionVector(position.getX() + velocity.getX(), position.getY() + velocity.getY()); } /** * Add the specified amounts to this cars's velocity. * The only acceleration values allowed are -1, 0 or 1 in both axis * There are 9 possible acceleration vectors, which are defined in {@link PositionVector.Direction}. * Changes only velocity, not position. * * @param acceleration A Direction vector containing the amounts to add to the velocity in x and y dimension * @throws IllegalArgumentException if PositionVector is not in allowed area. */ @Override public void accelerate(PositionVector.Direction acceleration) { if (acceleration.vector.getX() < -1 || acceleration.vector.getX() > 1 || acceleration.vector.getY() < -1 || acceleration.vector.getY() > 1) { throw new IllegalArgumentException(); } else { velocity = new PositionVector(velocity.getX() + acceleration.vector.getX(), velocity.getY() + acceleration.vector.getY()); } } /** * Update this Car's position based on its current velocity. */ @Override public void move() { position = new PositionVector(position.getX() + velocity.getX(), position.getY() + velocity.getY()); } /** * Mark this Car as being crashed. */ @Override public void crash() { crashed = true; } /** * Returns whether this Car has been marked as crashed. * * @return Returns true if crash() has been called on this Car, false otherwise. */ @Override public boolean isCrashed() { return crashed; } /** * Set move strategy * * @param moveStrategy Strategy to be implemented */ public void setMoveStrategy(MoveStrategy moveStrategy) { this.moveStrategy = moveStrategy; } /** * Get current move strategy * * @return MoveStrategy */ public MoveStrategy getMoveStrategy() { return this.moveStrategy; } }