diff --git a/bin/controller/GameController.class b/bin/controller/GameController.class index f6fe2f8..e1fb7ae 100644 Binary files a/bin/controller/GameController.class and b/bin/controller/GameController.class differ diff --git a/bin/controller/HowToPlayListener.class b/bin/controller/HowToPlayListener.class new file mode 100644 index 0000000..0e5f2ae Binary files /dev/null and b/bin/controller/HowToPlayListener.class differ diff --git a/bin/controller/MenuController.class b/bin/controller/MenuController.class index a0fdbcd..faf78fb 100644 Binary files a/bin/controller/MenuController.class and b/bin/controller/MenuController.class differ diff --git a/bin/controller/QuiListener.class b/bin/controller/QuiListener.class index 180a921..28b48c0 100644 Binary files a/bin/controller/QuiListener.class and b/bin/controller/QuiListener.class differ diff --git a/bin/controller/ScoreGameContext.class b/bin/controller/ScoreGameContext.class new file mode 100644 index 0000000..4b2cf7c Binary files /dev/null and b/bin/controller/ScoreGameContext.class differ diff --git a/bin/controller/SerieListener.class b/bin/controller/SerieListener.class new file mode 100644 index 0000000..33e4750 Binary files /dev/null and b/bin/controller/SerieListener.class differ diff --git a/bin/controller/SeriesSelector.class b/bin/controller/SeriesSelector.class new file mode 100644 index 0000000..4b9fc6a Binary files /dev/null and b/bin/controller/SeriesSelector.class differ diff --git a/bin/main/Main.class b/bin/main/Main.class index 9c0bb69..e9b291c 100644 Binary files a/bin/main/Main.class and b/bin/main/Main.class differ diff --git a/bin/model/Pocket.class b/bin/model/Pocket.class new file mode 100644 index 0000000..11cc732 Binary files /dev/null and b/bin/model/Pocket.class differ diff --git a/bin/model/Tile.class b/bin/model/Tile.class index 127aa6a..cd87738 100644 Binary files a/bin/model/Tile.class and b/bin/model/Tile.class differ diff --git a/bin/view/ButtonHoverListener.class b/bin/view/ButtonHoverListener.class index 6315df6..874630d 100644 Binary files a/bin/view/ButtonHoverListener.class and b/bin/view/ButtonHoverListener.class differ diff --git a/bin/view/GameView$1.class b/bin/view/GameView$1.class deleted file mode 100644 index 09a5b53..0000000 Binary files a/bin/view/GameView$1.class and /dev/null differ diff --git a/bin/view/GameView.class b/bin/view/GameView.class index 7671e64..ad40ca6 100644 Binary files a/bin/view/GameView.class and b/bin/view/GameView.class differ diff --git a/bin/view/HexagonTile$1.class b/bin/view/HexagonTile$1.class index 2997098..1927cf8 100644 Binary files a/bin/view/HexagonTile$1.class and b/bin/view/HexagonTile$1.class differ diff --git a/bin/view/HexagonTile.class b/bin/view/HexagonTile.class index 1d2ae2a..e4b508c 100644 Binary files a/bin/view/HexagonTile.class and b/bin/view/HexagonTile.class differ diff --git a/bin/view/HowToPlayView.class b/bin/view/HowToPlayView.class new file mode 100644 index 0000000..689894b Binary files /dev/null and b/bin/view/HowToPlayView.class differ diff --git a/bin/view/MenuView.class b/bin/view/MenuView.class index 6e6ee66..8fc0679 100644 Binary files a/bin/view/MenuView.class and b/bin/view/MenuView.class differ diff --git a/src/main/Main.java b/src/main/Main.java index b2ac1d9..af0d52f 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -1,7 +1,8 @@ package main; import model.MenuModel; -import controller.*; +import controller.MenuController; +import controller.SeriesSelector; import view.*; import javax.sound.sampled.AudioInputStream; @@ -16,31 +17,31 @@ public class Main { MenuModel model = new MenuModel(); MenuView view = new MenuView(); + // Initialiser SeriesSelector et le passer à MenuView + SeriesSelector seriesSelector = new SeriesSelector(); + view.setSeriesSelector(seriesSelector); + + // Créer MenuController avec model, view et seriesSelector + new MenuController(model, view, seriesSelector); + JFrame frame = App.getInstance(); frame.add(view); - - // Créer le contrôleur - new MenuController(model, view); - frame.setVisible(true); - // Chargement de la musique PlayMusic("/Music/audio.wav"); }); } - public static void PlayMusic(String location){ + public static void PlayMusic(String location) { try { - // Utilisation de getResource pour charger l'audio URL url = Main.class.getResource(location); - if (url != null) { AudioInputStream audioInput = AudioSystem.getAudioInputStream(url); Clip clip = AudioSystem.getClip(); clip.open(audioInput); clip.start(); } else { - System.out.println("fichier introuvable"); + System.out.println("Fichier audio introuvable"); } } catch (Exception e) { System.out.println(e); diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java index 7d49ad6..58b7fe6 100644 --- a/src/main/java/controller/GameController.java +++ b/src/main/java/controller/GameController.java @@ -20,8 +20,9 @@ public class GameController implements TilePlacer { private TileDatabaseManager dbManager; private List<Tile> currentTiles; private int tileIndex; + private ScoreGameContext scoreGameContext; // Nouveau contexte pour le score - public GameController(GameContext gameContext, JPanel gridPanel, HexagonTile nextTilePreview) { + public GameController(GameContext gameContext, JPanel gridPanel, HexagonTile nextTilePreview, JLabel scoreLabel) { this.gameContext = gameContext; this.gridPanel = gridPanel; this.hexagonMap = gameContext.getHexagonMap(); @@ -31,6 +32,9 @@ public class GameController implements TilePlacer { this.dbManager = new TileDatabaseManager(); this.tileIndex = 0; + // Initialisation de ScoreGameContext + this.scoreGameContext = new ScoreGameContext(gameContext, scoreLabel); + loadSeries(1); // Charger la série par défaut (ex. série 1) updatePreview(); } @@ -40,7 +44,6 @@ public class GameController implements TilePlacer { tileIndex = 0; System.out.println("Série " + idSeries + " chargée avec " + currentTiles.size() + " tuiles."); } - @Override public void placeTile(Point position) { @@ -52,7 +55,7 @@ public class GameController implements TilePlacer { } System.out.println("Placement de la tuile avec ID : " + (nextTile != null ? nextTile.getId() : "null") + " à la position : " + position); - + hexTile.setTile(nextTile); // Place la tuile actuelle gridPanel.revalidate(); gridPanel.repaint(); @@ -69,46 +72,49 @@ public class GameController implements TilePlacer { gameContext.repaintGrid(gridPanel); generateNextTile(); // Génère la tuile suivante + + // Calcul et mise à jour du score + scoreGameContext.calculateScore(); } } - - public void initializeGame(CameraController cameraController) { generateNextTile(); // Génère la première tuile et assigne une tuile valide à `nextTile` - + Tile initialTile = getNextTile(); // Récupère la tuile générée if (initialTile == null) { System.out.println("Erreur : aucune tuile initiale générée."); return; // Arrête l'initialisation si aucune tuile n'a été générée } - + System.out.println("ID de la tuile initiale générée : " + initialTile.getId()); // Affiche l'ID de la tuile initiale - + int centerX = gridPanel.getPreferredSize().width / 2; int centerY = gridPanel.getPreferredSize().height / 2; - + Point initialPosition = new Point(0, 0); initialPosition.setLocation(centerX / 50, centerY / 50); // Calcule la position centrale - + placeInitialTile(initialPosition, cameraController, initialTile); // Place la première tuile - generateNextTile(); + // Calculer et mettre à jour le score incluant la première tuile + scoreGameContext.calculateScore(); + + generateNextTile(); // Génère la tuile suivante } - public void placeInitialTile(Point position, CameraController cameraController, Tile tile) { if (tile == null) { System.out.println("Erreur : tuile initiale non définie."); return; } - + System.out.println("Placement de la tuile initiale avec ID : " + tile.getId() + " à la position : " + position); - + addHexagonTile(position, gridPanel, 50, cameraController, tile); // Place la première tuile availablePositions.remove(position); // Marque la position comme occupée - + Point[] adjacentPositions = getAdjacentPositions(position); for (Point adj : adjacentPositions) { if (!hexagonMap.containsKey(adj)) { @@ -123,38 +129,37 @@ public class GameController implements TilePlacer { System.out.println("Erreur : position ou panel est null"); return; } - + int xOffset = position.x * (int) (hexSize * 3 / 2); int yOffset = position.y * (int) (Math.sqrt(3) * hexSize); - + if (cameraController != null) { Point viewOffset = cameraController.getViewOffset(); xOffset += viewOffset.x; yOffset += viewOffset.y; } - + if (position.x % 2 != 0) { yOffset += (int) (Math.sqrt(3) * hexSize / 2); } - + boolean isPlaceholder = (tile == null); // Si tile est null, c'est un placeholder HexagonTile hexTile = new HexagonTile(position, isPlaceholder); - + if (tile != null) { hexTile.setTile(tile); } else { System.out.println("Aucun tile n'a été fourni pour cette position : " + position); } - + hexTile.setBounds(xOffset, yOffset, hexSize, hexSize); hexTile.addMouseListener(new HexagonMouseListener(hexTile, this, availablePositions)); - + hexagonMap.put(position, hexTile); panel.add(hexTile); panel.revalidate(); panel.repaint(); } - public void generateNextTile() { if (tileIndex < currentTiles.size()) { @@ -167,9 +172,6 @@ public class GameController implements TilePlacer { System.out.println("Fin de la série. Plus de tuiles à placer."); } } - - - private void updatePreview() { if (nextTilePreview != null) { @@ -181,7 +183,6 @@ public class GameController implements TilePlacer { nextTilePreview.repaint(); } } - public Tile getNextTile() { return nextTile; @@ -190,21 +191,21 @@ public class GameController implements TilePlacer { private Point[] getAdjacentPositions(Point position) { if (position.x % 2 == 0) { return new Point[]{ - new Point(position.x + 1, position.y), - new Point(position.x - 1, position.y), - new Point(position.x, position.y + 1), - new Point(position.x, position.y - 1), - new Point(position.x + 1, position.y - 1), - new Point(position.x - 1, position.y - 1) + new Point(position.x + 1, position.y), + new Point(position.x - 1, position.y), + new Point(position.x, position.y + 1), + new Point(position.x, position.y - 1), + new Point(position.x + 1, position.y - 1), + new Point(position.x - 1, position.y - 1) }; } else { return new Point[]{ - new Point(position.x + 1, position.y), - new Point(position.x - 1, position.y), - new Point(position.x, position.y + 1), - new Point(position.x, position.y - 1), - new Point(position.x + 1, position.y + 1), - new Point(position.x - 1, position.y + 1) + new Point(position.x + 1, position.y), + new Point(position.x - 1, position.y), + new Point(position.x, position.y + 1), + new Point(position.x, position.y - 1), + new Point(position.x + 1, position.y + 1), + new Point(position.x - 1, position.y + 1) }; } } diff --git a/src/main/java/controller/HowToPlayListener.java b/src/main/java/controller/HowToPlayListener.java new file mode 100644 index 0000000..d327a5a --- /dev/null +++ b/src/main/java/controller/HowToPlayListener.java @@ -0,0 +1,20 @@ +package controller; + +import view.HowToPlayView; +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class HowToPlayListener implements ActionListener { + private JFrame parent; + + public HowToPlayListener(JFrame parent) { + this.parent = parent; + } + + @Override + public void actionPerformed(ActionEvent e) { + HowToPlayView howToPlayDialog = new HowToPlayView(parent); + howToPlayDialog.setVisible(true); + } +} diff --git a/src/main/java/controller/MenuController.java b/src/main/java/controller/MenuController.java index 7596a77..998827d 100644 --- a/src/main/java/controller/MenuController.java +++ b/src/main/java/controller/MenuController.java @@ -1,15 +1,15 @@ package controller; -import model.*; -import view.*; +import model.MenuModel; +import view.MenuView; public class MenuController { - public MenuController(MenuModel model, MenuView view) { + public MenuController(MenuModel model, MenuView view, SeriesSelector seriesSelector) { + // Assignation des action listeners aux boutons du menu + view.getQuiButton().addActionListener(new QuiListener()); // Quitte l'application - view.getResumeButton().addActionListener(new ResListener()); - view.getNewGameButton().addActionListener(new NewListener()); - view.getQuiButton().addActionListener(new QuiListener()); + // Définir le sélecteur de séries + view.setSeriesSelector(seriesSelector); } } - diff --git a/src/main/java/controller/QuiListener.java b/src/main/java/controller/QuiListener.java index e42a344..c7c95b5 100644 --- a/src/main/java/controller/QuiListener.java +++ b/src/main/java/controller/QuiListener.java @@ -1,12 +1,11 @@ package controller; -import java.awt.event.ActionListener; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class QuiListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.exit(0); - } } diff --git a/src/main/java/controller/ResListener.java b/src/main/java/controller/ResListener.java deleted file mode 100644 index d53191e..0000000 --- a/src/main/java/controller/ResListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package controller; -import view.App; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.SwingUtilities; - -import view.GameView; - -public class ResListener implements ActionListener { - @Override - public void actionPerformed(ActionEvent e) { - SwingUtilities.invokeLater(() -> new GameView()); - App.getInstance().dispose(); - - } -} \ No newline at end of file diff --git a/src/main/java/controller/ScoreGameContext.java b/src/main/java/controller/ScoreGameContext.java new file mode 100644 index 0000000..f04a388 --- /dev/null +++ b/src/main/java/controller/ScoreGameContext.java @@ -0,0 +1,142 @@ +package controller; + +import model.Tile; +import model.TerrainType; +import model.Pocket; +import view.HexagonTile; + +import javax.swing.*; +import java.awt.Point; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class ScoreGameContext { + private GameContext gameContext; + private int score; + private JLabel scoreLabel; + private Map<Point, Pocket> pocketMap; // Map des Pockets pour chaque tuile + private Set<Pocket> pockets; // Ensemble de toutes les Pockets + + public ScoreGameContext(GameContext gameContext, JLabel scoreLabel) { + this.gameContext = gameContext; + this.scoreLabel = scoreLabel; + this.pocketMap = new HashMap<>(); + this.pockets = new HashSet<>(); + this.score = 0; + } + + // Méthode principale pour recalculer le score en reconstruisant toutes les Pockets + public void calculateScore() { + score = 0; + pockets.clear(); + pocketMap.clear(); + + // Parcourt chaque tuile dans la grille pour créer des Pockets par type de terrain + for (Map.Entry<Point, HexagonTile> entry : gameContext.getHexagonMap().entrySet()) { + Point position = entry.getKey(); + HexagonTile hexTile = entry.getValue(); + + if (hexTile.isFilled()) { + Tile tile = hexTile.getTile(); + + // Crée ou fusionne une Pocket pour chaque type de terrain de la tuile + for (int segment = 0; segment < 6; segment++) { + TerrainType terrainType = tile.getTerrainForSegment(segment); + if (terrainType != null) { + Pocket pocket = findOrCreatePocket(position, segment, terrainType); + pocketMap.put(position, pocket); + } + } + } + } + + // Calcule le score total en additionnant le score de chaque Pocket + System.out.println("Pockets and their sizes:"); + for (Pocket pocket : pockets) { + System.out.println("Pocket with terrain " + pocket.getTerrainType() + " has size " + pocket.getSize()); + score += pocket.calculateScore(); + } + + updateScoreDisplay(); + } + + // Recherche ou crée une Pocket pour un terrain spécifique dans une tuile + private Pocket findOrCreatePocket(Point position, int segment, TerrainType terrainType) { + Pocket newPocket = new Pocket(terrainType); + newPocket.addTile(position); + + // Vérifie les voisins pour fusionner les Pockets si les segments se touchent + for (int adjSegment = 0; adjSegment < 6; adjSegment++) { + Point neighborPos = getAdjacentPositionForSegment(position, adjSegment); + Pocket neighborPocket = pocketMap.get(neighborPos); + + if (neighborPocket != null && neighborPocket.getTerrainType() == terrainType) { + // Vérifie si les segments de terrain se touchent avant de fusionner les Pockets + if (areSegmentsConnected(position, neighborPos, segment, adjSegment, terrainType)) { + System.out.println("Merging pocket at " + position + " with pocket at " + neighborPos + " for terrain " + terrainType); + neighborPocket.merge(newPocket); + pockets.remove(newPocket); // Supprime la Pocket fusionnée + return neighborPocket; // Retourne la Pocket fusionnée + } + } + } + + System.out.println("New pocket created at " + position + " for terrain " + terrainType); + pockets.add(newPocket); // Ajoute la nouvelle Pocket si aucune fusion n'a eu lieu + return newPocket; + } + + // Vérifie si les segments de deux tuiles se touchent et partagent le même type de terrain + private boolean areSegmentsConnected(Point position1, Point position2, int segment1, int segment2, TerrainType terrainType) { + Tile tile1 = gameContext.getHexagonMap().get(position1).getTile(); + Tile tile2 = gameContext.getHexagonMap().get(position2).getTile(); + + if (tile1 == null || tile2 == null) return false; + + TerrainType terrainSegment1 = tile1.getTerrainForSegment(segment1); + TerrainType terrainSegment2 = tile2.getTerrainForSegment(segment2); + + boolean connected = terrainSegment1 == terrainType && terrainSegment2 == terrainType; + if (connected) { + System.out.println("Segments connected between " + position1 + " and " + position2 + " for terrain " + terrainType); + } + return connected; + } + + // Obtenir la position adjacente pour un segment spécifique (0 à 5) + private Point getAdjacentPositionForSegment(Point position, int segment) { + if (position.x % 2 == 0) { + switch (segment) { + case 0: return new Point(position.x + 1, position.y); + case 1: return new Point(position.x + 1, position.y - 1); + case 2: return new Point(position.x, position.y - 1); + case 3: return new Point(position.x - 1, position.y - 1); + case 4: return new Point(position.x - 1, position.y); + case 5: return new Point(position.x, position.y + 1); + default: return position; + } + } else { + switch (segment) { + case 0: return new Point(position.x + 1, position.y); + case 1: return new Point(position.x + 1, position.y + 1); + case 2: return new Point(position.x, position.y + 1); + case 3: return new Point(position.x - 1, position.y + 1); + case 4: return new Point(position.x - 1, position.y); + case 5: return new Point(position.x, position.y - 1); + default: return position; + } + } + } + + // Met à jour l'affichage du score dans GameView + private void updateScoreDisplay() { + System.out.println("Updated Score: " + score); // Débogage du score + scoreLabel.setText("Score: " + score); + } + + public int getScore() { + return score; + } +} diff --git a/src/main/java/controller/SerieListener.java b/src/main/java/controller/SerieListener.java new file mode 100644 index 0000000..6b60ead --- /dev/null +++ b/src/main/java/controller/SerieListener.java @@ -0,0 +1,19 @@ +package controller; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SerieListener implements ActionListener { + private final GameController gameController; + private final int seriesNumber; + + public SerieListener(GameController gameController, int seriesNumber) { + this.gameController = gameController; + this.seriesNumber = seriesNumber; + } + + @Override + public void actionPerformed(ActionEvent e) { + gameController.loadSeries(seriesNumber); + } +} diff --git a/src/main/java/controller/SeriesSelector.java b/src/main/java/controller/SeriesSelector.java new file mode 100644 index 0000000..a573282 --- /dev/null +++ b/src/main/java/controller/SeriesSelector.java @@ -0,0 +1,12 @@ +package controller; + +import view.GameView; +import javax.swing.SwingUtilities; + +public class SeriesSelector { + + public void startGameWithSeries(int seriesId) { + SwingUtilities.invokeLater(() -> new GameView(seriesId)); // Démarre GameView avec l'ID de série donné + System.out.println("Série " + seriesId + " sélectionnée et jeu démarré."); + } +} diff --git a/src/main/java/model/Pocket.java b/src/main/java/model/Pocket.java new file mode 100644 index 0000000..4ae2071 --- /dev/null +++ b/src/main/java/model/Pocket.java @@ -0,0 +1,41 @@ +package model; + +import java.awt.Point; +import java.util.HashSet; +import java.util.Set; + +public class Pocket { + private TerrainType terrainType; // Type de terrain de cette Pocket + private Set<Point> tiles; // Ensemble des positions des tuiles de la Pocket + + public Pocket(TerrainType terrainType) { + this.terrainType = terrainType; + this.tiles = new HashSet<>(); + } + + public TerrainType getTerrainType() { + return terrainType; + } + + public int getSize() { + return tiles.size(); + } + + public void addTile(Point position) { + tiles.add(position); + } + + public boolean containsTile(Point position) { + return tiles.contains(position); + } + + public void merge(Pocket other) { + if (this.terrainType == other.terrainType) { + this.tiles.addAll(other.tiles); + } + } + + public int calculateScore() { + return getSize() * getSize(); // La taille au carré donne le score + } +} diff --git a/src/main/java/model/Tile.java b/src/main/java/model/Tile.java index 29cbfa6..ff5048a 100644 --- a/src/main/java/model/Tile.java +++ b/src/main/java/model/Tile.java @@ -1,17 +1,34 @@ package model; public class Tile { - private int id; // Ajoute l'attribut id - private TerrainType[] terrains; // 2 terrains maximum par tuile - private int segmentsForTerrain1; - private int rotation; + private int id; // ID de la tuile + private TerrainType[] terrains; // Tableau contenant deux types de terrains (ex. MER, FORET) + private int segmentsForTerrain1; // Nombre de segments pour le premier terrain + private int rotation; // Rotation de la tuile (en multiple de 60 degrés) - // Constructeur modifié pour inclure l'ID public Tile(int id, TerrainType terrain1, TerrainType terrain2, int segmentsForTerrain1) { this.id = id; this.terrains = new TerrainType[]{terrain1, terrain2}; this.segmentsForTerrain1 = segmentsForTerrain1; - this.rotation = 0; + this.rotation = 0; // Initialisation de la rotation à 0 + } + + // Renvoie le terrain pour l'index donné (0 ou 1) + public TerrainType getTerrain(int index) { + if (index >= 0 && index < terrains.length) { + return terrains[index]; + } + return null; // Retourne null si l'index est invalide + } + + // Méthode pour obtenir le terrain associé à un segment spécifique (prend en compte la rotation) + public TerrainType getTerrainForSegment(int segmentIndex) { + int adjustedIndex = (segmentIndex - rotation + 6) % 6; + if (adjustedIndex < segmentsForTerrain1) { + return terrains[0]; + } else { + return terrains[1]; + } } public void rotateClockwise() { @@ -19,9 +36,8 @@ public class Tile { } public void rotateCounterClockwise() { - rotation = (rotation + 5) % 6; // Tourner dans le sens inverse, équivalent à -1 dans un modulo 6 + rotation = (rotation + 5) % 6; // Tourner dans le sens inverse } - public int getRotation() { return rotation; @@ -30,12 +46,4 @@ public class Tile { public int getId() { return id; } - - public TerrainType getTerrain(int index) { - return index >= 0 && index < 2 ? terrains[index] : null; - } - - public int getSegmentsForTerrain(int index) { - return index == 0 ? segmentsForTerrain1 : 6 - segmentsForTerrain1; - } } diff --git a/src/main/java/view/ButtonHoverListener.java b/src/main/java/view/ButtonHoverListener.java index a97fc0b..81cbf30 100644 --- a/src/main/java/view/ButtonHoverListener.java +++ b/src/main/java/view/ButtonHoverListener.java @@ -1,28 +1,27 @@ package view; -import javax.swing.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.Color; public class ButtonHoverListener extends MouseAdapter { - private Color hoverColor = new Color(200, 150, 100); - private Color normalColor = new Color(243, 171, 115, 150); + private final Color hoverColor = new Color(200, 150, 100, 200); // Couleur de hover avec transparence + private final Color normalColor = new Color(243, 171, 115, 150); // Couleur normale avec transparence @Override public void mouseEntered(MouseEvent e) { - if (e.getSource() instanceof JButton) { - JButton button = (JButton) e.getSource(); + if (e.getSource() instanceof BtnPerso) { // Applique uniquement aux boutons de type BtnPerso + BtnPerso button = (BtnPerso) e.getSource(); button.setBackground(hoverColor); } } @Override public void mouseExited(MouseEvent e) { - if (e.getSource() instanceof JButton) { - JButton button = (JButton) e.getSource(); + if (e.getSource() instanceof BtnPerso) { // Applique uniquement aux boutons de type BtnPerso + BtnPerso button = (BtnPerso) e.getSource(); button.setBackground(normalColor); } } -} \ No newline at end of file +} diff --git a/src/main/java/view/GameView.java b/src/main/java/view/GameView.java index 62469a2..dea6cc1 100644 --- a/src/main/java/view/GameView.java +++ b/src/main/java/view/GameView.java @@ -14,52 +14,48 @@ public class GameView extends JFrame { private GameController gameController; private CameraController cameraController; private GameContext gameContext; + private JLabel scoreLabel; - public GameView() { + // Couleurs pour le style + private final Color hoverColor = new Color(200, 150, 100); // Couleur de hover avec transparence + private final Color normalColor = new Color(243, 171, 115); // Couleur normale avec transparence + + public GameView(int seriesId) { setTitle("Jeu de Tuiles"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); setSize(1500, 750); setLocationRelativeTo(null); - // Initialiser le contexte de jeu gameContext = new GameContext(); - - // Créer la grille d'hexagones gridPanel = createHexagonGrid(); - - // Calculer et centrer la grille dans GameView centerGridPanel(); - add(gridPanel, BorderLayout.CENTER); - // Initialiser la preview pour la prochaine tuile nextTilePreview = new HexagonTile(null, false); + scoreLabel = new JLabel("Score: 0"); + scoreLabel.setForeground(Color.BLACK); // Texte noir pour contraste JPanel controlPanel = createControlPanel(); controlPanel.setPreferredSize(new Dimension(200, 600)); add(controlPanel, BorderLayout.EAST); - // Initialiser les contrôleurs avec le contexte de jeu - gameController = new GameController(gameContext, gridPanel, nextTilePreview); + gameController = new GameController(gameContext, gridPanel, nextTilePreview, scoreLabel); + gameController.loadSeries(seriesId); // Charge la série cameraController = new CameraController(gridPanel, gameContext); - // Ajouter un écouteur pour la molette de la souris MouseWheelController wheelController = new MouseWheelController(nextTilePreview, gameController); - addMouseWheelListener(wheelController); - // Appeler l'initialisation du jeu gameController.initializeGame(cameraController); - setVisible(true); } private JPanel createHexagonGrid() { JPanel panel = new JPanel(); - panel.setLayout(null); // Permet de placer des composants avec des coordonnées absolues - panel.setBackground(Color.WHITE); - panel.setPreferredSize(new Dimension(800, 800)); // Peut être ajusté si nécessaire + panel.setLayout(null); + panel.setBackground(normalColor); // Couleur de fond de la grille + panel.setPreferredSize(new Dimension(800, 800)); return panel; } @@ -67,23 +63,28 @@ public class GameView extends JFrame { int centerX = (getWidth() - gridPanel.getPreferredSize().width) / 2; int centerY = (getHeight() - gridPanel.getPreferredSize().height) / 2; gameContext.updateOffset(centerX, centerY); - gameContext.repaintGrid(gridPanel); // Rappel pour centrer initialement les tuiles + gameContext.repaintGrid(gridPanel); } private JPanel createControlPanel() { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - panel.setBackground(Color.LIGHT_GRAY); + panel.setBackground(normalColor); // Couleur normale pour le panneau de contrôle panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - panel.add(new JLabel("Prochaine tuile : ")); + JLabel nextTileLabel = new JLabel("Prochaine tuile : "); + nextTileLabel.setForeground(Color.BLACK); // Texte noir pour contraste + panel.add(nextTileLabel); panel.add(Box.createRigidArea(new Dimension(0, 10))); nextTilePreview.setPreferredSize(new Dimension(150, 150)); - nextTilePreview.setBackground(Color.GRAY); + nextTilePreview.setBackground(hoverColor); // Couleur hover pour différencier nextTilePreview.setOpaque(true); panel.add(nextTilePreview); + panel.add(Box.createRigidArea(new Dimension(0, 30))); + panel.add(scoreLabel); + return panel; } } diff --git a/src/main/java/view/HexagonTile.java b/src/main/java/view/HexagonTile.java index 09e7362..28945ee 100644 --- a/src/main/java/view/HexagonTile.java +++ b/src/main/java/view/HexagonTile.java @@ -10,7 +10,7 @@ import java.awt.geom.Path2D; public class HexagonTile extends JPanel { private Tile tile; private Point position; - private boolean isPlaceholder; // Nouveau champ pour indiquer si l'hexagone est un placeholder + private boolean isPlaceholder; // Indicateur si l'hexagone est un placeholder public HexagonTile(Point position, boolean isPlaceholder) { this.position = position; @@ -50,7 +50,7 @@ public class HexagonTile extends JPanel { g2d.setClip(largeHexagon); if (tile != null) { - drawTerrainSegments(g2d, centerX, centerY, largeRadius, tile.getRotation()); + drawTerrainSegments(g2d, centerX, centerY, largeRadius); } else { g2d.setColor(Color.LIGHT_GRAY); g2d.fill(largeHexagon); @@ -62,13 +62,11 @@ public class HexagonTile extends JPanel { g2d.draw(largeHexagon); } - private void drawTerrainSegments(Graphics2D g2d, int centerX, int centerY, int radius, int rotation) { - int segmentsTerrain1 = tile.getSegmentsForTerrain(0); + private void drawTerrainSegments(Graphics2D g2d, int centerX, int centerY, int radius) { + // Parcourt les segments de 0 à 5 pour dessiner chaque segment en fonction du terrain associé for (int i = 0; i < 6; i++) { - int segmentIndex = (i + rotation) % 6; - g2d.setColor(segmentIndex < segmentsTerrain1 ? - getTerrainColor(tile.getTerrain(0)) : - getTerrainColor(tile.getTerrain(1))); + TerrainType terrain = tile.getTerrainForSegment(i); // Récupère le terrain du segment, en prenant en compte la rotation + g2d.setColor(getTerrainColor(terrain)); g2d.fillArc(centerX - radius, centerY - radius, 2 * radius, 2 * radius, 60 * i, 60); } } diff --git a/src/main/java/view/HowToPlayView.java b/src/main/java/view/HowToPlayView.java new file mode 100644 index 0000000..e0fee4d --- /dev/null +++ b/src/main/java/view/HowToPlayView.java @@ -0,0 +1,35 @@ +package view; + +import javax.swing.*; +import java.awt.*; + +public class HowToPlayView extends JDialog { + + public HowToPlayView(JFrame parent) { + super(parent, "Comment Jouer", true); + + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBackground(new Color(243, 171, 115, 200)); + + JLabel titleLabel = new JLabel("COMMENT JOUER"); + titleLabel.setFont(new Font("Helvetica", Font.BOLD, 30)); + titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + panel.add(titleLabel); + + JLabel instruction1 = new JLabel("Déplacer la caméra : clique droit enfoncé"); + JLabel instruction2 = new JLabel("Poser des tuiles : clique gauche sur un petit hexagone"); + JLabel instruction3 = new JLabel("Orientation des tuiles : Molette de la souris"); + + for (JLabel label : new JLabel[]{instruction1, instruction2, instruction3}) { + label.setFont(new Font("Helvetica", Font.PLAIN, 20)); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(label); + } + + add(panel); + setSize(600, 400); + setLocationRelativeTo(parent); + } +} diff --git a/src/main/java/view/MenuView.java b/src/main/java/view/MenuView.java index 2a28573..c91e3fe 100644 --- a/src/main/java/view/MenuView.java +++ b/src/main/java/view/MenuView.java @@ -2,79 +2,177 @@ package view; import javax.swing.*; import java.awt.*; +import controller.SeriesSelector; public class MenuView extends JComponent { + private BtnPerso resumeButton; private BtnPerso newGameButton; private JButton quitButton; + private JPanel panelCote; + private JPanel howToPlayPanel; + private JPanel centeredPanel; + private JPanel seriesPanel; + private SeriesSelector seriesSelector; private Image backgroundImage; private ImageIcon logo; private ImageIcon quit; - private JPanel panelCoté; - private JLabel labelImg; + private JLabel labelImg; // Déclaration de labelImg public MenuView() { + initMenu(); + } - panelCoté = new JPanel(new GridBagLayout()); + public void setSeriesSelector(SeriesSelector seriesSelector) { + this.seriesSelector = seriesSelector; + } + + // Méthode pour afficher les boutons de sélection de série + public void showSeriesButtons() { + howToPlayPanel.setVisible(false); + centeredPanel.removeAll(); + centeredPanel.add(seriesPanel); + seriesPanel.setVisible(true); + + revalidate(); + repaint(); + } + + // Méthode pour afficher/masquer le panneau "Comment jouer" + private void toggleHowToPlay() { + seriesPanel.setVisible(false); + howToPlayPanel.setVisible(!howToPlayPanel.isVisible()); + centeredPanel.removeAll(); + centeredPanel.add(howToPlayPanel); + + revalidate(); + repaint(); + } + + private void initMenu() { + // Initialisation du panneau latéral + panelCote = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); - panelCoté.setBackground(new Color(243, 171, 115, 150)); - panelCoté.setPreferredSize(new Dimension(300, 0)); + panelCote.setBackground(new Color(243, 171, 115, 150)); + panelCote.setPreferredSize(new Dimension(300, 0)); - // Utilisation de getResource pour charger les images + // Charger les images backgroundImage = new ImageIcon(getClass().getResource("/java/view/img/bg.png")).getImage(); logo = new ImageIcon(getClass().getResource("/java/view/img/D.png")); quit = new ImageIcon(getClass().getResource("/java/view/img/quit.png")); - + // Redimensionnement des images Image quit1 = quit.getImage(); Image lg = logo.getImage(); Image resizedlg = lg.getScaledInstance(300, 300, Image.SCALE_SMOOTH); - ImageIcon logoIcon = new ImageIcon(resizedlg); - - labelImg = new JLabel(logoIcon); - - resumeButton = new BtnPerso("RESUME"); - newGameButton = new BtnPerso("NEW GAME"); + labelImg = new JLabel(new ImageIcon(resizedlg)); // Initialisation de labelImg + // Configuration du bouton "Quitter" avec une icône redimensionnée int buttonWidth = 65; int buttonHeight = 40; Image resizedImage = quit1.getScaledInstance(buttonWidth, buttonHeight, Image.SCALE_SMOOTH); ImageIcon resizedIcon = new ImageIcon(resizedImage); + // Boutons + resumeButton = new BtnPerso("JOUER"); + newGameButton = new BtnPerso("COMMENT JOUER"); quitButton = new JButton(resizedIcon); + + // Configurer le bouton "Quitter" pour enlever le fond et la bordure quitButton.setPreferredSize(new Dimension(buttonWidth, buttonHeight)); - quitButton.setPreferredSize(new Dimension(50, 50)); - quitButton.setBackground(new Color(243, 171, 115, 150)); - quitButton.setBorderPainted(false); - quitButton.setOpaque(true); - quitButton.setFocusPainted(false); + quitButton.setBackground(new Color(243, 171, 115, 150)); // Fond transparent similaire + quitButton.setBorderPainted(false); // Enlever la bordure pour un look plus propre + quitButton.setOpaque(true); // Rendre le fond visible + quitButton.setFocusPainted(false); // Enlever le focus autour du bouton - ButtonHoverListener hoverListener = new ButtonHoverListener(); - resumeButton.addMouseListener(hoverListener); - newGameButton.addMouseListener(hoverListener); - quitButton.addMouseListener(hoverListener); + // Ajout des listeners pour les boutons + resumeButton.addActionListener(e -> showSeriesButtons()); + newGameButton.addActionListener(e -> toggleHowToPlay()); + // Créer le panneau "Comment jouer" et le panneau de séries + howToPlayPanel = createHowToPlayPanel(); + howToPlayPanel.setVisible(false); + + seriesPanel = createSeriesPanel(); + seriesPanel.setVisible(false); + + // Panneau centré pour le contenu dynamique + centeredPanel = new JPanel(new GridBagLayout()); + centeredPanel.setOpaque(false); + centeredPanel.add(howToPlayPanel); + + // Ajout des composants au panneau latéral gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(10, 10, 10, 10); gbc.weightx = 1.0; - gbc.gridx = 0; + + // Ajouter l'image de logo gbc.gridy = 0; + panelCote.add(labelImg, gbc); // Ajout de labelImg ici - panelCoté.add(labelImg, gbc); - + // Ajouter les boutons gbc.gridy = 1; - panelCoté.add(resumeButton, gbc); + panelCote.add(resumeButton, gbc); gbc.gridy = 2; - panelCoté.add(newGameButton, gbc); + panelCote.add(newGameButton, gbc); gbc.gridy = 3; - panelCoté.add(quitButton, gbc); + panelCote.add(quitButton, gbc); setLayout(new BorderLayout()); - add(panelCoté, BorderLayout.WEST); + add(panelCote, BorderLayout.WEST); + add(centeredPanel, BorderLayout.CENTER); + } + + private JPanel createHowToPlayPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBackground(new Color(243, 171, 115, 200)); + panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + JLabel titleLabel = new JLabel("COMMENT JOUER"); + titleLabel.setFont(new Font("Helvetica", Font.BOLD, 30)); + titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + panel.add(titleLabel); + + String[] instructions = { + "Déplacer la caméra : clique droit enfoncé", + "Poser des tuiles : clique gauche sur un petit hexagone", + "Orientation des tuiles : Molette de la souris" + }; + + for (String text : instructions) { + JLabel label = new JLabel(text); + label.setFont(new Font("Helvetica", Font.PLAIN, 20)); + label.setAlignmentX(Component.CENTER_ALIGNMENT); + panel.add(Box.createRigidArea(new Dimension(0, 10))); + panel.add(label); + } + + panel.setPreferredSize(new Dimension(700, 350)); + return panel; + } + + private JPanel createSeriesPanel() { + JPanel panel = new JPanel(new GridLayout(2, 2, 10, 10)); + panel.setOpaque(false); + + for (int i = 1; i <= 4; i++) { + int seriesId = i; + BtnPerso seriesButton = new BtnPerso("Série " + seriesId); + seriesButton.addActionListener(e -> { + if (seriesSelector != null) { + seriesSelector.startGameWithSeries(seriesId); + } + }); + + seriesButton.addMouseListener(new ButtonHoverListener()); + panel.add(seriesButton); + } + return panel; } @Override