Files
archived-L3-racing-game/src/model/car/BasicCar.java

261 lines
6.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model.car;
import java.awt.Color;
import java.awt.Point;
import java.util.Random;
import model.map.Circuit;
import model.map.Map;
/**
* {@link BasicCar} représente une voiture qui avance sur un circuit en boucles.
* Chaque appel à {@link #run()} avance la voiture d'une certaine position et
* fait perdre de l'essence.
* Quand la position atteint la fin de la boucle, un nouveau tour est compté.
* <p>
* La voiture consomme du carburant à chaque déplacement, et son score
* est calculé en fonction du nombre de tours complétés et de sa progression sur
* le tour actuel.
* </p>
*/
public class BasicCar implements Car {
/** Générateur de nombres aléatoires pour simuler la progression */
protected static final Random RANDOM = new Random();
/** Couleur de la voiture pour l'affichage */
private final Color COLOR;
/** Nom de la voiture */
private final String NAME;
/** Position actuelle dans la boucle (entre 0 et loop) */
private int pos = 0;
/** Nombre de tours complétés */
private int round = 0;
/** Nombre de cases dans une boucle (doit être > 0) */
private Map map;
/** Carburant restant */
private int fuel = 60;
private int movement = 1;
private boolean isConsuming = true;
/**
* Construit une nouvelle voiture.
*
* @param name nom de la voiture
* @param color couleur de la voiture
* @param map
*/
public BasicCar(String name, Color color, Map map) {
this.NAME = name;
this.COLOR = color;
this.map = map;
}
public BasicCar(String name, Color color) {
this.NAME = name;
this.COLOR = color;
}
/**
* Référence à l'état du jeu, pour récupérer les paramètres comme la
* consommation
*/
private State state = State.NORMAL;
private int damageRound = 0;
public void setDamage() {
damageRound = 5;
state = State.DAMAGED;
}
private void decreaseDamage() {
if (state.isDamaged()) {
if (--damageRound <= 0) {
state = state.onDamageEnd();
}
}
}
public BasicCar setState(State state) {
this.state = state;
return this;
}
/**
* Clique sur "Accelerer" : change d'état et retourne un message (si
* nécessaire).
*/
@Override
public String accelerate() {
// Si endommagée => l'énoncé dit qu'on ne peut pas bouger
if (state.isDamaged()) {
return "Voiture endommagée : impossible d'accélérer";
}
State next = state.accelerate();
// Énoncé : en BOOST, si on accélère encore => message "déjà max"
if (state == State.BOOST && next == State.BOOST) {
return "Déjà à la vitesse maximale";
}
state = next;
return "";
}
/**
* Clique sur "Rallentir" : change d'état et retourne un message (si
* nécessaire).
*/
@Override
public String decelerate() {
if (state.isDamaged()) {
return "Voiture endommagée : impossible de ralentir";
}
State next = state.decelerate();
// Énoncé : en STOPPED, si on ralentit encore => message "déjà arrêtée"
if (state == State.STOPPED && next == State.STOPPED) {
return "Déjà arrêtée";
}
state = next;
return "";
}
/**
* Fait avancer la voiture d'un certain nombre de positions.
* <p>
* Si la position atteint la fin de la boucle, le compteur de tours est
* incrémenté et
* la position revient à zéro.
* </p>
*
* @param move nombre de positions à avancer
* @return cette même instance (pour chaînage fluide)
*/
private void move() {
int jump = RANDOM.nextInt(state.MIN, state.MAX);
for (int i = 0; i < jump; i++) {
pos = state.move(pos, movement);
Point point = map.getPath(pos);
Circuit element = map.getElement(point.x, point.y);
if (hasAccident(element, jump)) {
setDamage();
return;
}
round = pos / map.getPathSize();
}
}
private boolean hasAccident(Circuit element, int jump) {
return element.isYRoad() && element.getValue() <= jump;
}
/**
* Consomme du carburant en fonction de l'état du jeu.
*
* @return cette même instance pour chaînage
*/
public void consumeFuel() {
fuel = state.fuelConsumption(fuel);
if (fuel < 0)
fuel = 0; // sécurité
}
public boolean hasFinished() {
return 3 < round;
}
/**
* Exécute une "étape" de la voiture : avance d'une position aléatoire et
* consomme du carburant.
* <p>
* La progression est déterminée par un intervalle aléatoire fourni par l'état
* du jeu.
* </p>
*/
@Override
public boolean apply() {
if (state.isDamaged()) {
decreaseDamage();
} else if (fuel > 0) {
move();
if (isConsuming)
consumeFuel();
}
return !hasFinished();
}
@Override
public void consumption(boolean active) {
isConsuming = active;
}
@Override
public Car remove() {
return this;
}
@Override
public void reverse(boolean active) {
movement = (active) ? -1 : 1;
}
/**
* @return la position actuelle dans la boucle
*/
public int getPosition() {
return Math.floorMod(pos, map.getPathSize());
}
/**
* @return le score de la voiture, calculé comme :
* (nombre de tours + progression du tour) × 100
*/
public int getScore() {
return (int) ((round + (float) pos / map.getPathSize()) * 100);
}
/**
* @return le nombre de tours complétés
*/
public int getRound() {
return round;
}
/**
* @return le carburant restant
*/
public int getFuel() {
return fuel;
}
/** Retourne l'état courant de la voiture. */
public State getState() {
return state;
}
/**
* @return la couleur de la voiture
*/
public Color getColor() {
return COLOR;
}
/**
* @return nom de la voiture
*/
public String getName() {
return NAME;
}
@Override
public void setMap(Map map) {
this.map = map;
}
}