diff --git a/src/Main.java b/src/Main.java index d041a04..fbd376f 100644 --- a/src/Main.java +++ b/src/Main.java @@ -5,6 +5,7 @@ import model.car.BasicCar; import model.car.DrunkCar; import model.car.HybridCar; import model.map.Map; +import visual.SelectionView; public class Main { public static void main(String[] args) throws InterruptedException { @@ -21,14 +22,12 @@ public class Main { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }); - Game game = new Game.Builder() - .car(new HybridCar(new BasicCar("Luwik", Color.RED))) - .car(new DrunkCar(new BasicCar("Charazade", Color.PINK))) + SelectionView game = new SelectionView(3); + + game.getGameBuilder() .track("Piste Formule 1", 1000, 500, 1, 1) .rankboard("Score", 200, 200, 0, 510) .dashboards(300, 200, 1000, 0) - .map(map) - .build(); - game.run(); + .map(map); } } \ No newline at end of file diff --git a/src/model/Game.java b/src/model/Game.java index fd3f262..789c240 100644 --- a/src/model/Game.java +++ b/src/model/Game.java @@ -39,19 +39,19 @@ public class Game { public Builder rankboard(String title, int width, int height, int x, int y) { - this.OBSERVERS.add(new Rankboard(null, title, width, height, x, y)); + this.OBSERVERS.add(new RankboardView(null, title, width, height, x, y)); return this; } public Builder track(String title, int width, int height, int x, int y) { - this.OBSERVERS.add(new Track(null, title, width, height, x, y)); + this.OBSERVERS.add(new TrackView(null, title, width, height, x, y)); return this; } public Builder dashboard(Car car, String title, int width, int height, int x, int y) { - this.OBSERVERS.add(new Dashboard(null, car, title, width, height, x, y)); + this.OBSERVERS.add(new DashboardView(null, car, title, width, height, x, y)); return this; } diff --git a/src/model/car/BasicCar.java b/src/model/car/BasicCar.java index f763059..51218b2 100644 --- a/src/model/car/BasicCar.java +++ b/src/model/car/BasicCar.java @@ -122,7 +122,7 @@ public class BasicCar implements Car { state = next; return ""; } - + /** * Fait avancer la voiture d'un certain nombre de positions. *

@@ -130,73 +130,78 @@ public class BasicCar implements Car { * incrémenté et * la position revient à zéro. *

- * - * @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; + * + * @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é - } + * + * @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; - } +public boolean hasFinished() { + return 3 < round; +} - /** - * Exécute une "étape" de la voiture : avance d'une position aléatoire et - * consomme du carburant. - *

- * La progression est déterminée par un intervalle aléatoire fourni par l'état - * du jeu. - *

- */ - @Override - public boolean apply() { - if (state.isDamaged()) { - decreaseDamage(); - } else if (fuel > 0) { - move(); - if (isConsuming) - consumeFuel(); - } - return !hasFinished(); +/** + * Exécute une "étape" de la voiture : avance d'une position aléatoire et + * consomme du carburant. + *

+ * La progression est déterminée par un intervalle aléatoire fourni par l'état + * du jeu. + *

+*/ +@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 void consumption(boolean active) { - isConsuming = active; + public Car remove() { + return this; } - @Override - public void reverse(boolean active) { +@Override +public void reverse(boolean active) { movement = (active) ? -1 : 1; } diff --git a/src/model/car/Car.java b/src/model/car/Car.java index 45af97d..cae6aac 100644 --- a/src/model/car/Car.java +++ b/src/model/car/Car.java @@ -13,18 +13,21 @@ public interface Car extends Observer { public void reverse(boolean active); public void consumption(boolean active); - + + public Car remove(); + public String getName(); - + public int getPosition(); - + public int getScore(); - + public int getRound(); - + public int getFuel(); - + public State getState(); + public Color getColor(); public void setMap(Map map); diff --git a/src/model/car/CarDecorator.java b/src/model/car/CarDecorator.java index 0ed8b92..49cbfc4 100644 --- a/src/model/car/CarDecorator.java +++ b/src/model/car/CarDecorator.java @@ -11,6 +11,11 @@ public abstract class CarDecorator implements Car { this.car = car; } + @Override + public Car remove() { + return car; + } + @Override public String accelerate() { return car.accelerate(); diff --git a/src/model/car/DrunkCar.java b/src/model/car/DrunkCar.java index b2cba16..0d984cc 100644 --- a/src/model/car/DrunkCar.java +++ b/src/model/car/DrunkCar.java @@ -1,7 +1,5 @@ package model.car; -import java.util.Random; - /** * DrunkCar = décorateur "pilote ivre". * @@ -14,8 +12,7 @@ import java.util.Random; * sans modifier la classe Car. */ public class DrunkCar extends CarDecorator { - /** Générateur de nombres aléatoires pour simuler la progression */ - protected static final Random RANDOM = new Random(); + private boolean reverse = false; public DrunkCar(Car car) { super(car); @@ -25,9 +22,9 @@ public class DrunkCar extends CarDecorator { // 50% : fait l'inverse @Override public boolean apply() { - car.reverse(RANDOM.nextBoolean()); + car.reverse(reverse); car.apply(); - car.reverse(false); + reverse = !reverse; return true; } } \ No newline at end of file diff --git a/src/model/car/Selection.java b/src/model/car/Selection.java new file mode 100644 index 0000000..78e1401 --- /dev/null +++ b/src/model/car/Selection.java @@ -0,0 +1,80 @@ +package model.car; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import model.Game; + +public class Selection { + private final Game.Builder gameBuilder; + private final List cars = new ArrayList<>(); + + public Selection(Game.Builder gameBuilder) { + this.gameBuilder = gameBuilder; + } + + public List getCars() { + return new ArrayList<>(cars); + } + + public Car addCar(String name, Color color) { + Car car = new BasicCar(name, color); + cars.add(car); + return car; + } + + public void removeCar(Car car) { + cars.remove(car); + } + + private Car addDecorator(Function fn, Car car) throws IllegalArgumentException { + int index = cars.indexOf(car); + + if (index < 0) { + throw new IllegalArgumentException( + "Aucune voiture dans la classe interne."); + } + + car = fn.apply(car); + cars.set(index, car); + return car; + } + + public Car addHybridCarDecorator(Car car) throws IllegalArgumentException { + return addDecorator(HybridCar::new, car); + } + + public Car addDrunkCarDecorator(Car car) throws IllegalArgumentException { + return addDecorator(DrunkCar::new, car); + } + + public Car addBoostCarDecorator(Car car) throws IllegalArgumentException { + return addDecorator(BoostCar::new, car); + } + + public Car removeDecorator(Car car) throws IllegalArgumentException { + int index = cars.indexOf(car); + + if (index < 0) { + throw new IllegalArgumentException( + "Aucune voiture dans la classe interne."); + } + car = car.remove(); + cars.set(index, car); + return car; + } + + public Game.Builder select() { + for (Car car : cars) { + gameBuilder.car(car); + System.out.println("hello world"); + } + return gameBuilder; + } + + public int size() { + return cars.size(); + } +} diff --git a/src/visual/Dashboard.java b/src/visual/DashboardView.java similarity index 97% rename from src/visual/Dashboard.java rename to src/visual/DashboardView.java index abce8e8..6a7aec1 100644 --- a/src/visual/Dashboard.java +++ b/src/visual/DashboardView.java @@ -24,7 +24,7 @@ import model.car.HybridCar; * - un bouton Accelerer * - un bouton Rallentir */ -public class Dashboard extends GameView { +public class DashboardView extends GameView { /** Label affichant carburant et nombre de tours */ private final JLabel infoLabel = new JLabel(); @@ -58,7 +58,7 @@ public class Dashboard extends GameView { * @param x position horizontale de la fenêtre * @param y position verticale de la fenêtre */ - public Dashboard(Game game, Car car, String title, int width, int height, int x, int y) { + public DashboardView(Game game, Car car, String title, int width, int height, int x, int y) { super(game, "Dashboard: " + title, width, height, x, y); this.car = car; diff --git a/src/visual/GameView.java b/src/visual/GameView.java index c07f2b3..5e60f31 100644 --- a/src/visual/GameView.java +++ b/src/visual/GameView.java @@ -66,7 +66,8 @@ public abstract class GameView extends JComponent implements Game.Observer { // mettre un layout (la disposition des elements de la fenetre) frame.setLayout(new BorderLayout()); - game.addObserver(this); + if (game != null) + game.addObserver(this); } protected GameView(Game game, String title, int width, int height, int x, int y) { diff --git a/src/visual/Rankboard.java b/src/visual/RankboardView.java similarity index 94% rename from src/visual/Rankboard.java rename to src/visual/RankboardView.java index 6839e8c..ab7a426 100644 --- a/src/visual/Rankboard.java +++ b/src/visual/RankboardView.java @@ -18,7 +18,7 @@ import model.car.Car; * Les scores sont triés du plus grand au plus petit. *

*/ -public class Rankboard extends GameView { +public class RankboardView extends GameView { /** Liste des voitures à afficher */ List cars; @@ -43,7 +43,7 @@ public class Rankboard extends GameView { * @param x Position horizontale de la fenêtre * @param y Position verticale de la fenêtre */ - public Rankboard(Game game, String title, int width, int height, int x, int y) { + public RankboardView(Game game, String title, int width, int height, int x, int y) { super(game, title, width, height, x, y); if (game != null) init(game); diff --git a/src/visual/SelectionView.java b/src/visual/SelectionView.java new file mode 100644 index 0000000..8b3b88c --- /dev/null +++ b/src/visual/SelectionView.java @@ -0,0 +1,84 @@ +package visual; + +import java.awt.*; +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JPanel; + +import model.Game; +import model.car.Car; +import model.car.Selection; + +public class SelectionView extends GameView { + private Game.Builder gameBuilder = new Game.Builder(); + private Selection selection = new Selection(gameBuilder); + private JPanel buttonPanel = new JPanel(); + + public Game.Builder getGameBuilder() { + return gameBuilder; + } + + public SelectionView(int ncar) { + super(null, "Menu de sélection", 500, 300, 400, 400); + init(null); // forcer le init + + buttonPanel.setLayout(new GridLayout(0, 3, 5, 5)); + frame.add(buttonPanel, BorderLayout.CENTER); + + for (int i = 1; i <= ncar; i++) { + Car car = selection.addCar("Car " + i, Color.getHSBColor(i / 3f, 0.8f, 0.8f)); + // bouton Hybrid + JButton hybridBtn = new JButton("Hybrid " + car.getName()); + // bouton Drunk + JButton drunkBtn = new JButton("Drunk " + car.getName()); + // bouton boost + JButton boostBtn = new JButton("Boost " + car.getName()); + + final int I = i; + hybridBtn.addActionListener((ActionEvent e) -> { + try { + Car current = selection.getCars().get(I-1); + selection.addHybridCarDecorator(current); + hybridBtn.setEnabled(false); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + + drunkBtn.addActionListener((ActionEvent e) -> { + try { + Car current = selection.getCars().get(I-1); + selection.addDrunkCarDecorator(current); + drunkBtn.setEnabled(false); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + + boostBtn.addActionListener((ActionEvent e) -> { + try { + Car current = selection.getCars().get(I-1); + selection.addBoostCarDecorator(current); + boostBtn.setEnabled(false); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + + buttonPanel.add(hybridBtn); + buttonPanel.add(drunkBtn); + buttonPanel.add(boostBtn); + } + + JButton startBtn = new JButton("Start"); + startBtn.addActionListener((ActionEvent e) -> { + frame.dispose(); + new Thread(() -> selection.select().build().run()).start(); + }); + + this.frame.add(startBtn, BorderLayout.SOUTH); + frame.revalidate(); + frame.repaint(); + } +} diff --git a/src/visual/Track.java b/src/visual/TrackView.java similarity index 97% rename from src/visual/Track.java rename to src/visual/TrackView.java index 4fbf2ae..3638520 100644 --- a/src/visual/Track.java +++ b/src/visual/TrackView.java @@ -23,7 +23,7 @@ import model.map.Map; * est dessinée selon son type. Les voitures sont superposées sur la grille. *

*/ -public class Track extends GameView { +public class TrackView extends GameView { /** La carte du circuit */ private Map map; /** Liste des voitures à dessiner */ @@ -49,7 +49,7 @@ public class Track extends GameView { * @param x Position X de la fenêtre * @param y Position Y de la fenêtre */ - public Track(Game game, String title, int width, int height, int x, int y) { + public TrackView(Game game, String title, int width, int height, int x, int y) { super(game, title, width, height, x, y); if (game != null) init(game);