Un peu de ménage dans le git

This commit is contained in:
2024-12-02 20:51:28 +01:00
parent 0e6450f8c8
commit 9b2a314262
102 changed files with 49818 additions and 27 deletions

View File

@@ -0,0 +1,29 @@
package fr.monkhanny.dorfromantik.game;
import java.util.ArrayList;
import java.util.List;
public class BiomeGroup {
private List<Pocket> pockets;
public BiomeGroup() {
pockets = new ArrayList<>();
}
public void addPocket(Pocket pocket) {
pockets.add(pocket);
}
public List<Pocket> getPockets() {
return pockets;
}
public int calculateTotalScore() {
int totalScore = 0;
for (Pocket pocket : pockets) {
totalScore += pocket.calculateScore();
}
return totalScore;
}
}

View File

@@ -0,0 +1,462 @@
package fr.monkhanny.dorfromantik.game;
import fr.monkhanny.dorfromantik.listeners.GameZoomListener;
import fr.monkhanny.dorfromantik.listeners.GameArrowKeyListener;
import fr.monkhanny.dorfromantik.listeners.GameSpaceKeyListener;
import fr.monkhanny.dorfromantik.listeners.GameMouseClickListener;
import fr.monkhanny.dorfromantik.listeners.GameMouseWheelListener;
import fr.monkhanny.dorfromantik.Options;
import fr.monkhanny.dorfromantik.enums.Biome;
import fr.monkhanny.dorfromantik.enums.Fonts;
import fr.monkhanny.dorfromantik.enums.TileOrientation;
import fr.monkhanny.dorfromantik.controller.GameModeController;
import fr.monkhanny.dorfromantik.utils.Database;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Point;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Font;
// TEMPORAIRE :
import java.awt.event.MouseMotionAdapter; // Import pour MouseMotionAdapter
import java.awt.AlphaComposite;
import java.util.HashMap;
import java.util.Map;
/**
* Représente le plateau de jeu.
*/
public class Board extends JPanel{
private List<Tile> tiles;
private List<Point> availablePositions;
private Random random;
private Game game;
private JFrame gameFrame;
private Tile centralTile;
private double zoomFactor = 1.0; // Facteur de zoom initial
private int offsetX = 0; // Décalage horizontal du plateau
private int offsetY = 0; // Décalage vertical du plateau
private Tile nextTile;
private Map<Biome, BiomeGroup> biomeGroups;
private Point mousePosition;
private ScoreManager scoreManager;
private int currentScore;
private Database database;
// Constructeur avec seed
public Board(JFrame gameFrame, long seed) {
this.gameFrame = gameFrame;
this.tiles = new ArrayList<>();
this.biomeGroups = new HashMap<>();
this.availablePositions = new ArrayList<>();
this.random = new Random(seed);
this.game = new Game(seed);
this.scoreManager = new ScoreManager(biomeGroups);
for (Biome biome : Biome.values()) {
biomeGroups.put(biome, new BiomeGroup());
}
// Placer une tuile centrale au démarrage
initializeCentralTile();
// Ajouter un écouteur de molette de souris pour gérer le zoom
gameFrame.addMouseWheelListener(new GameZoomListener(this));
// Ajouter un écouteur de clavier pour déplacer le plateau
gameFrame.addKeyListener(new GameArrowKeyListener(this));
gameFrame.setFocusable(true);
this.addMouseWheelListener(new GameMouseWheelListener(this));
gameFrame.addKeyListener(new GameSpaceKeyListener(this));
this.addMouseListener(new GameMouseClickListener(this));
this.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(java.awt.event.MouseEvent e) {
handleMouseMove(e);
}
});
}
public void handleMouseMove(java.awt.event.MouseEvent e) {
// Récupérer les coordonnées du curseur
Point cursorPoint = e.getPoint();
// Ajuster la position de la souris en fonction du zoom et des offsets
int adjustedX = (int)((cursorPoint.x - offsetX) / zoomFactor);
int adjustedY = (int)((cursorPoint.y - offsetY) / zoomFactor);
// Vérifier si la souris est proche d'une des positions disponibles
for (Point position : availablePositions) {
if (new Point(adjustedX, adjustedY).distance(position) < 20) {
mousePosition = position;
repaint(); // Redessiner le plateau avec la tuile transparente
return;
}
}
// Si la souris n'est pas proche d'une position valide, ne rien faire
mousePosition = null;
repaint(); // Redessiner sans la tuile transparente
}
private void initializeNextTile() {
int offsetX = 50; // Décalage pour la position en haut à gauche
int offsetY = 50; // Décalage pour la position en haut à gauche
this.nextTile = new Tile(this, offsetX, offsetY, 50); // Création de la nouvelle tuile
}
public Tile getNextTile() { return nextTile; }
public void handleSpaceKeyPress() {
// Calculer les dimensions totales du plateau (largeur et hauteur des tuiles)
int totalWidth = 0;
int totalHeight = 0;
// Calculer la largeur et la hauteur totale de toutes les tuiles
for (Tile tile : tiles) {
totalWidth = Math.max(totalWidth, tile.getXCoord() + tile.getRadius());
totalHeight = Math.max(totalHeight, tile.getYCoord() + tile.getRadius());
}
// Ajouter une petite marge pour les bords
totalWidth += 50; // Marge pour éviter que les tuiles ne soient collées au bord
totalHeight += 50; // Marge pour éviter que les tuiles ne soient collées au bord
// Calculer le facteur de zoom pour que toutes les tuiles tiennent sur l'écran
double horizontalZoom = (double) getWidth() / totalWidth;
double verticalZoom = (double) getHeight() / totalHeight;
// Choisir le zoom le plus petit pour éviter que les tuiles ne sortent de l'écran
zoomFactor = Math.min(horizontalZoom, verticalZoom);
// Ajuster les offsets pour centrer les tuiles après le dézoom
adjustOffsets(totalWidth, totalHeight);
// Recalculer les positions disponibles et redessiner le plateau
repaint();
}
private void adjustOffsets(int totalWidth, int totalHeight) {
// Calculer les décalages nécessaires pour centrer le plateau
int targetOffsetX = (int) ((getWidth() - totalWidth * zoomFactor) / 2);
int targetOffsetY = (int) ((getHeight() - totalHeight * zoomFactor) / 2);
// Appliquer les nouveaux offsets
setOffsetX(targetOffsetX);
setOffsetY(targetOffsetY);
}
public void handleMouseClick(java.awt.event.MouseEvent e) {
// Récupérer les coordonnées du clic
Point clickedPoint = e.getPoint();
// Ajuster les coordonnées du clic en tenant compte du zoom et des déplacements
// Annuler l'effet du zoom et du déplacement
int adjustedX = (int)((clickedPoint.x - offsetX) / zoomFactor);
int adjustedY = (int)((clickedPoint.y - offsetY) / zoomFactor);
// Vérifiez si la position ajustée est dans la liste des positions disponibles et si la distance est suffisante
for (Point position : availablePositions) {
// Vérifiez la distance entre le clic ajusté et la position
if (new Point(adjustedX, adjustedY).distance(position) < 20) {
placeTileAtPosition(position); // Place une tuile à cette position
break; // Si une tuile est ajoutée, on peut sortir de la boucle
}
}
}
private void initializeCentralTile() {
int centerX = gameFrame.getWidth() / 2;
int centerY = gameFrame.getHeight() / 2;
this.centralTile = new Tile(this, centerX, centerY, 50);
addTile(centralTile);
// Calculer les positions disponibles autour de la tuile centrale
calculateAvailablePositions(centralTile);
initializeNextTile();
}
public void addTile(Tile tile) {
tiles.add(tile);
updatePockets(tile);
calculateCurrentScore();
}
private void updatePockets(Tile newTile) {
for (TileOrientation orientation : TileOrientation.values()) {
Biome biome = newTile.getBiome(orientation);
BiomeGroup biomeGroup = biomeGroups.get(biome);
// Vérifier si la nouvelle tuile peut être connectée à une poche existante
Pocket connectedPocket = null;
for (Pocket pocket : biomeGroup.getPockets()) {
if (isConnectedToPocket(newTile, pocket)) {
connectedPocket = pocket;
break;
}
}
if (connectedPocket != null) {
// Connecte la tuile à une poche existante
connectedPocket.addTile(newTile);
} else {
// Crée une nouvelle poche pour ce biome
Pocket newPocket = new Pocket(biome);
newPocket.addTile(newTile);
biomeGroup.addPocket(newPocket);
}
}
}
// Méthode pour vérifier si une tuile est connectée à une poche existante
private boolean isConnectedToPocket(Tile tile, Pocket pocket) {
for (Tile connectedTile : pocket.getTiles()) {
if (areTilesConnected(tile, connectedTile)) {
return true;
}
}
return false;
}
// Vérifie si deux tuiles sont connectées par un même biome
private boolean areTilesConnected(Tile tile1, Tile tile2) {
for (TileOrientation orientation : TileOrientation.values()) {
if (tile1.getBiome(orientation).equals(tile2.getBiome(orientation.oppositeOrientation()))) {
// Vérifier si les tuiles sont adjacentes (logique à adapter selon vos besoins)
// Exemple : si elles partagent un côté commun
return tile1.isAdjacentTo(tile2);
}
}
return false;
}
private void calculateCurrentScore() {
scoreManager.updateScore(); // Met à jour le score
currentScore = scoreManager.getCurrentScore(); // Récupère le score actuel
}
public int getCurrentScore() {
return currentScore;
}
public Random getRandom() { return random; }
public Game getGame() { return game; }
/**
* Calcule les positions disponibles autour de la tuile donnée.
* Les points rouges seront générés autour de cette tuile.
*
* @param tile La tuile pour laquelle on calcule les positions disponibles
*/
private void calculateAvailablePositions(Tile tile) {
int tileX = tile.getXCoord();
int tileY = tile.getYCoord();
int radius = (int) (tile.getRadius() * 1.72); // Utiliser un rayon uniforme pour toutes les directions
// Définir les directions possibles autour de la tuile (6 directions pour une tuile hexagonale)
Point[] directions = {
new Point(0, -radius), // Nord
new Point((int)(radius * Math.sqrt(3) / 2), -radius / 2), // Nord-Est (ajuster horizontalement)
new Point((int)(radius * Math.sqrt(3) / 2), radius / 2), // Sud-Est (ajuster horizontalement)
new Point(0, radius), // Sud
new Point(-(int)(radius * Math.sqrt(3) / 2), radius / 2), // Sud-Ouest (ajuster horizontalement)
new Point(-(int)(radius * Math.sqrt(3) / 2), -radius / 2) // Nord-Ouest (ajuster horizontalement)
};
// Calculer les positions disponibles autour de la tuile
for (Point direction : directions) {
Point newPoint = new Point(tileX + direction.x, tileY + direction.y);
if (!isTileAtPosition(newPoint)) {
availablePositions.add(newPoint); // Ajouter la position si une tuile n'est pas déjà là
}
}
}
/**
* Vérifie si une tuile existe déjà à la position donnée.
*
* @param position La position à vérifier
* @return true si une tuile est présente à cette position, false sinon
*/
private boolean isTileAtPosition(Point position) {
for (Tile t : tiles) {
if (t.getXCoord() == position.x && t.getYCoord() == position.y) {
return true;
}
}
return false;
}
/**
* Lorsqu'un utilisateur clique, ajoute une nouvelle tuile à la position sélectionnée.
*
* @param position La position où ajouter la tuile
*/
public void placeTileAtPosition(Point position) {
// Vérifie si la position est disponible et que la tuile n'est pas déjà placée à cet endroit
if (availablePositions.contains(position) && !isTileAtPosition(position)) {
if (tiles.size() < Options.MAX_TILE_NUMBER) {
// Vérifiez si la nextTile existe, sinon on ignore
if (nextTile != null) {
// Place la nextTile à la position choisie
nextTile.setPosition(position.x, position.y);
addTile(nextTile); // Ajoute la nextTile au tableau des tuiles
calculateAvailablePositions(nextTile); // Calcule de nouvelles positions disponibles
repaint(); // Redessine le plateau
autoReFocus(nextTile);
// Initialiser une nouvelle nextTile pour le prochain tour
initializeNextTile();
}
} else {
try {
this.database = new Database();
} catch (Exception e) {
System.err.println("Erreur lors de la connexion à la base de données: " + e.getMessage());
}
GameOver gameOverPanel = new GameOver(gameFrame, currentScore, database,Options.mainMenu);
gameFrame.getContentPane().removeAll(); // Supprime l'ancien contenu
gameFrame.getContentPane().add(gameOverPanel); // Ajoute le GameOver
gameFrame.revalidate(); // Revalidate pour mettre à jour la fenêtre
gameFrame.repaint(); // Repaint pour afficher les modifications
}
}
}
public void autoReFocus(Tile newlyPlacedTile) {
if (Options.AUTO_FOCUS) {
// Récupérer les coordonnées de la nouvelle tuile
int newlyPlacedTileX = newlyPlacedTile.getXCoord();
int newlyPlacedTileY = newlyPlacedTile.getYCoord();
// Calculer les décalages nécessaires pour centrer la tuile
// Nous utilisons la largeur et la hauteur du panneau de jeu (getWidth et getHeight)
// Divisé par 2 pour centrer la nouvelle tuile dans la fenêtre.
int targetOffsetX = (int) ((getWidth() - newlyPlacedTile.getRadius() * 2) / 2 - newlyPlacedTileX);
int targetOffsetY = (int) ((getHeight() - newlyPlacedTile.getRadius() * 2) / 2 - newlyPlacedTileY);
TilePanningTransition panningTransition = new TilePanningTransition(this, targetOffsetX, targetOffsetY, 15);
panningTransition.start();
}
}
public double getZoomFactor() { return zoomFactor;}
public void setZoomFactor(double zoomFactor) { this.zoomFactor = zoomFactor; }
public int getOffsetX() { return offsetX; }
public void setOffsetX(int offsetX) { this.offsetX = offsetX; }
public int getOffsetY() { return offsetY; }
public void setOffsetY(int offsetY) { this.offsetY = offsetY; }
public void zoomIn() {
zoomFactor *= 1.1; // Augmenter le facteur de zoom
repaint();
}
public void zoomOut() {
zoomFactor /= 1.1; // Diminuer le facteur de zoom
repaint();
}
public void moveBoard(int dx, int dy) {
offsetX += dx;
offsetY += dy;
repaint();
}
/**
* Afficher les points rouges pour indiquer les positions disponibles.
*
* @param g Le contexte graphique
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// Appliquer l'échelle de zoom et le déplacement
g2d.scale(zoomFactor, zoomFactor); // Appliquer le zoom
g2d.translate(offsetX / zoomFactor, offsetY / zoomFactor); // Appliquer le déplacement (en tenant compte du zoom)
// Dessiner les points rouges pour les positions disponibles
for (Point position : availablePositions) {
g.setColor(Color.RED);
g.fillOval(position.x - 5, position.y - 5, 10, 10); // Dessiner un point rouge
}
// Dessiner les tuiles existantes
for (Tile tile : tiles) {
int tileX = tile.getXCoord();
int tileY = tile.getYCoord();
tile.drawTileAt(g,tileX-50,tileY-50,1f);
}
// Vérifier si la position de la souris est valide et ne pas dessiner si elle est occupée
if (mousePosition != null && nextTile != null && !isTileAtPosition(mousePosition)) {
int nextTileX = mousePosition.x;
int nextTileY = mousePosition.y;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); // Rendre la tuile transparente
nextTile.drawTileAt(g, nextTileX - 50, nextTileY - 50, 1f);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f)); // Rétablir l'opacité
}
// Obtenez la police SCORE avec une taille ajustée (par exemple, 30 points)
Font scoreFont = Fonts.SCORE.getFont(30f); // Vous pouvez ajuster la taille ici
g.setFont(scoreFont);
// Calculer la position du score (avec zoom et décalage)
g.setColor(Color.BLACK);
int scoreX = (int) ((getWidth() / (2 * zoomFactor) - offsetX / zoomFactor) - 20);
int scoreY = (int) (40 / zoomFactor - offsetY / zoomFactor);
// Dessiner le texte du score
g.drawString("Score : " + currentScore, scoreX, scoreY);
if (nextTile != null) {
// Calculer la position correcte de la nextTile (en tenant compte du zoom et des décalages)
int nextTileX = 0; // Position x dans l'espace global
int nextTileY = 0; // Position y dans l'espace global
// Appliquer la transformation inverse (ne pas zoomer ni déplacer la nextTile)
g2d.scale(1 / zoomFactor, 1 / zoomFactor); // Inverser le zoom
g2d.translate(-offsetX, -offsetY); // Inverser le décalage (revenir à l'espace global)
// Dessiner la nextTile à sa position d'origine (0,0)
nextTile.drawTileAt(g, nextTileX, nextTileY, 1f);
// Rétablir les transformations pour les autres éléments (tuiles existantes, etc.)
g2d.translate(offsetX / zoomFactor, offsetY / zoomFactor); // Re-appliquer le décalage
g2d.scale(zoomFactor, zoomFactor); // Re-appliquer le zoom
}
}
}

View File

@@ -0,0 +1,110 @@
package fr.monkhanny.dorfromantik.game;
import java.awt.*;
import javax.swing.*;
/**
* Représente une cellule de base sur le plateau de jeu.
* C'est la classe parente pour la classe Tile.
*/
public class Cell extends JComponent {
private Board board; // Le plateau de jeu auquel cette cellule appartient
public int x; // Coordonnée x du centre de la cellule
public int y; // Coordonnée y du centre de la cellule
public int radius; // Rayon de la cellule (si on parle d'un hexagone, c'est le rayon de l'hexagone)
/**
* Constructeur de la classe Cell.
*
* @param board Le plateau de jeu auquel cette cellule appartient
* @param x La coordonnée x du centre de la cellule
* @param y La coordonnée y du centre de la cellule
* @param radius Le rayon de la cellule
*/
public Cell(Board board, int x, int y, int radius) {
this.board = board;
this.x = x;
this.y = y;
this.radius = radius;
// Définir la taille du composant pour l'affichage
this.setSize(2 * radius, 2 * radius);
this.setLocation(x - radius, y - radius);
}
/**
* Récupère le plateau de jeu auquel cette cellule appartient.
*
* @return Le plateau de jeu
*/
public Board getBoard() {
return board;
}
/**
* Récupère la coordonnée x du centre de la cellule.
*
* @return La coordonnée x
*/
public int getXCoord() {
return x;
}
/**
* Récupère la coordonnée y du centre de la cellule.
*
* @return La coordonnée y
*/
public int getYCoord() {
return y;
}
/**
* Récupère le rayon de la cellule.
*
* @return Le rayon de la cellule
*/
public int getRadius() {
return radius;
}
/**
* Convertit une coordonnée en degrés en une valeur de 0 à 360.
*
* @param angle L'angle en degrés
* @return La valeur normalisée entre 0 et 360 degrés
*/
public static double to360Degrees(double angle) {
angle = angle % 360;
if (angle < 0) {
angle += 360;
}
return angle;
}
/**
* Permet de changer la position de la cellule.
* Cette méthode met à jour les coordonnées x et y et déplace la cellule dans le composant graphique.
*
* @param x La nouvelle coordonnée x du centre de la cellule
* @param y La nouvelle coordonnée y du centre de la cellule
*/
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
// Mettre à jour la position de la cellule sur le plateau
this.setLocation(x - radius, y - radius);
}
/**
* Méthode pour redessiner la cellule si nécessaire.
* Elle sera surchargée par les classes dérivées comme Tile.
*
* @param g Le contexte graphique
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}

View File

@@ -0,0 +1,27 @@
package fr.monkhanny.dorfromantik.game;
import java.util.Random;
/**
* Représente un objet de jeu qui gère les fonctionnalités générales.
*/
public class Game {
private Random random;
// Nouveau constructeur qui accepte un seed
public Game(long seed) {
this.random = new Random(seed);
}
// Constructeur par défaut pour conserver la flexibilité
public Game() {
this.random = new Random();
}
public int getRandomInt(int max) {
return random.nextInt(max);
}
}

View File

@@ -0,0 +1,236 @@
package fr.monkhanny.dorfromantik.game;
import fr.monkhanny.dorfromantik.utils.Database;
import fr.monkhanny.dorfromantik.gui.MainMenu;
import fr.monkhanny.dorfromantik.Main;
import fr.monkhanny.dorfromantik.Options;
import fr.monkhanny.dorfromantik.enums.Fonts;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.List;
public class GameOver extends JPanel {
private JFrame gameFrame;
private int finalScore;
private Database database;
private MainMenu mainMenu;
public GameOver(JFrame gameFrame, int finalScore, Database database, MainMenu mainMenu) {
this.gameFrame = gameFrame;
this.mainMenu = mainMenu;
this.finalScore = finalScore;
this.database = database;
setLayout(new BorderLayout());
// Background image setup
JLabel background = new JLabel(new ImageIcon("./ressources/images/MainMenu/backgroundBlured.jpg"));
background.setLayout(new BorderLayout());
this.add(background, BorderLayout.CENTER);
// Main content panel
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setOpaque(false);
background.add(mainPanel, BorderLayout.CENTER);
// Title for the Game Over message
JLabel titleLabel = new JLabel("Partie terminée !");
titleLabel.setFont(Fonts.TITLE.getFont(48)); // Using the TITLE font
titleLabel.setForeground(Color.WHITE);
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(titleLabel);
// Spacer
mainPanel.add(Box.createVerticalStrut(30));
// Display the final score
JLabel scoreLabel = new JLabel("Votre score est de : " + finalScore);
scoreLabel.setFont(Fonts.SCORE.getFont(36)); // Using the SCORE font
scoreLabel.setForeground(Color.WHITE);
scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
scoreLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); // Padding
scoreLabel.setOpaque(true);
scoreLabel.setBackground(new Color(0, 0, 0, 100)); // Background color with transparency
mainPanel.add(scoreLabel);
// Spacer
mainPanel.add(Box.createVerticalStrut(30));
// Grouping information and funny quote
try {
long seriesId = Options.SEED; // Get the correct seriesId
List<Integer> allScores = database.getScoresBySeriesId(seriesId);
// Calculate the groups
int totalPlayers = allScores.size();
int groupSize = totalPlayers / 10;
int playerGroup = 0;
// Check if there are less than 20 players
String funnyQuote = "";
if (totalPlayers < 20) {
// Only show the funny quote if there are less than 20 players
if(totalPlayers == 0){
funnyQuote = "Vous êtes le premier joueur à jouer à cette partie personalisée...";
}
if(totalPlayers == 1){
funnyQuote = "Vous êtes le deuxième joueur à jouer à cette partie personalisée...";
}
if(totalPlayers > 1){
funnyQuote = "À part vous, il y a " + totalPlayers + " joueurs qui à joué à cette partie personalisée...";
}
// Display the funny quote directly
JLabel quoteLabel = new JLabel(funnyQuote);
quoteLabel.setFont(Fonts.SCORE.getFont(24));
quoteLabel.setForeground(Color.WHITE);
quoteLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(quoteLabel);
} else {
// Calculate which group the player's score falls into
for (int i = 0; i < totalPlayers; i++) {
if (allScores.get(i) <= finalScore) {
playerGroup = i / groupSize + 1;
break;
}
}
// Group information
JPanel groupPanel = new JPanel();
groupPanel.setOpaque(false);
groupPanel.setLayout(new BoxLayout(groupPanel, BoxLayout.Y_AXIS));
JLabel groupTitleLabel = new JLabel("Vous êtes dans le groupe " + playerGroup + "/10 !");
groupTitleLabel.setFont(Fonts.SCORE.getFont(24));
groupTitleLabel.setForeground(Color.WHITE);
groupTitleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
groupPanel.add(groupTitleLabel);
JLabel groupSizeLabel = new JLabel("Il y a " + groupSize + " joueurs dans ce groupe.");
groupSizeLabel.setFont(Fonts.SCORE.getFont(24));
groupSizeLabel.setForeground(Color.WHITE);
groupSizeLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
groupPanel.add(groupSizeLabel);
// Show a funny quote based on the group
funnyQuote = getFunnyQuote(playerGroup);
JLabel quoteLabel = new JLabel(funnyQuote);
quoteLabel.setFont(Fonts.SCORE.getFont(24));
quoteLabel.setForeground(Color.WHITE);
quoteLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
groupPanel.add(quoteLabel);
// Add group information panel
mainPanel.add(groupPanel);
// Spacer
mainPanel.add(Box.createVerticalStrut(30));
}
} catch (SQLException e) {
e.printStackTrace();
}
// Input panel for username and submission
JPanel inputPanel = createInputPanel();
mainPanel.add(inputPanel);
// Spacer
mainPanel.add(Box.createVerticalStrut(30));
}
private String getFunnyQuote(int playerGroup) {
// A list of funny and motivational quotes based on the group
switch (playerGroup) {
case 1: return "Vous êtes officiellement un génie ! Peut-être même un super-héros...!";
case 2: return "Pas mal ! Mais attention, le groupe 1 vous attend avec des applaudissements !";
case 3: return "Vous êtes sur la bonne voie, mais vous avez encore un peu de chemin à parcourir !";
case 4: return "Il est encore temps d'appeler un coach... ou un ami pour vous aider !";
case 5: return "Vous êtes dans la bonne direction, mais votre GPS semble un peu perdu !";
case 6: return "Vous n'êtes pas loin du sommet, mais le sommet semble être dans un autre pays !";
case 7: return "C'est un bon début ! Peut-être qu'un peu de café améliorerait encore la situation ?!";
case 8: return "Sur le chemin de la gloire, mais vous êtes encore coincé dans les bouchons...";
case 9: return "Pas de panique, il y a encore de la place pour s'améliorer... à peu près toute la place.";
case 10: return "Félicitations ! Mais peut-être que vous voudriez réessayer sans les lunettes de soleil ?";
default: return "Hé, on progresse ! Peut-être qu'un jour, vous dominerez le monde... ou du moins ce jeu !";
}
}
private JPanel createInputPanel() {
JPanel inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
inputPanel.setOpaque(false);
// Username label and text field
JPanel namePanel = new JPanel();
namePanel.setOpaque(false);
JLabel nameLabel = new JLabel("Entrez votre pseudo :");
nameLabel.setForeground(Color.WHITE);
nameLabel.setFont(Fonts.SCORE.getFont(24));
namePanel.add(nameLabel);
JTextField nameField = new JTextField(20);
nameField.setFont(Fonts.SCORE.getFont(18));
nameField.setPreferredSize(new Dimension(250, 40));
nameField.setBorder(BorderFactory.createLineBorder(Color.WHITE, 2));
nameField.setText("Anonyme");
namePanel.add(nameField);
inputPanel.add(namePanel);
// Spacer between name field and button
inputPanel.add(Box.createVerticalStrut(20));
// Add flexible space at the bottom to push the button down
inputPanel.add(Box.createVerticalGlue());
// Submit button
JButton submitButton = new JButton("Soumettre");
submitButton.setFont(Fonts.BUTTON.getFont(24)); // Using the BUTTON font
submitButton.setBackground(new Color(0, 255, 0));
submitButton.setForeground(Color.WHITE);
submitButton.setBorder(BorderFactory.createLineBorder(Color.WHITE, 2));
submitButton.setPreferredSize(new Dimension(150, 50));
// Center the button horizontally using BoxLayout
submitButton.setAlignmentX(Component.CENTER_ALIGNMENT);
inputPanel.add(submitButton);
// Action to handle score submission
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String username = nameField.getText().trim();
if (username.isEmpty()) {
username = "Anonyme"; // Default to "Anonyme" if no name is given
}
// Save the score to the database
try {
long seriesId = Options.SEED; // Replace with the appropriate series ID
database.addScore(username, seriesId, finalScore);
// Débloquer les récompenses pour ce joueur
database.unlockRewards(username, finalScore);
JOptionPane.showMessageDialog(gameFrame, "Score enregistré et récompenses débloquées !");
} catch (Exception ex) {
JOptionPane.showMessageDialog(gameFrame, "Erreur lors de l'enregistrement du score : " + ex.getMessage());
}
// Fermer la fenêtre de jeu
Main.resetGame();
}
});
return inputPanel;
}
}

View File

@@ -0,0 +1,43 @@
package fr.monkhanny.dorfromantik.game;
import fr.monkhanny.dorfromantik.enums.Biome;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Pocket {
private Biome biome;
private Set<Tile> tiles; // Ensemble des tuiles de la poche
public Pocket(Biome biome) {
this.biome = biome;
this.tiles = new HashSet<>();
}
public void addTile(Tile tile) {
tiles.add(tile);
}
public boolean containsTile(Tile tile) {
return tiles.contains(tile);
}
public Biome getBiome() {
return biome;
}
public int getSize() {
return tiles.size();
}
public int calculateScore() {
// Calcul du score basé sur la taille de la poche
return getSize() * getSize();
}
public List<Tile> getTiles() {
return new ArrayList<>(tiles);
}
}

View File

@@ -0,0 +1,44 @@
package fr.monkhanny.dorfromantik.game;
import java.util.Map;
import fr.monkhanny.dorfromantik.enums.Biome;
/**
* Classe responsable du calcul et de la gestion du score.
*/
public class ScoreManager {
private int currentScore = 0;
private Map<Biome, BiomeGroup> biomeGroups;
// Constructeur avec la référence aux groupes de biomes
public ScoreManager(Map<Biome, BiomeGroup> biomeGroups) {
this.biomeGroups = biomeGroups;
}
// Méthode pour calculer le score en fonction des groupes de biomes
public void calculateScore() {
int totalScore = 0;
for (BiomeGroup group : biomeGroups.values()) {
totalScore += group.calculateTotalScore();
}
currentScore = totalScore;
}
// Récupérer le score actuel
public int getCurrentScore() {
return currentScore;
}
// Mettre à jour le score (si nécessaire)
public void updateScore() {
calculateScore();
}
// Réinitialiser le score
public void resetScore() {
currentScore = 0;
}
}

View File

@@ -0,0 +1,254 @@
package fr.monkhanny.dorfromantik.game;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Arrays;
import fr.monkhanny.dorfromantik.enums.Biome;
import fr.monkhanny.dorfromantik.enums.TileOrientation;
import fr.monkhanny.dorfromantik.utils.Hexagon;
public class Tile extends Cell {
private HashMap<TileOrientation, Biome> sideBiomes = new HashMap<>();
public Tile(Board board, int x, int y, int radius, Biome... biomes) {
super(board, x, y, radius);
TileOrientation[] sides = TileOrientation.values();
for (int i = 0; i < sides.length; i++) {
this.sideBiomes.put(sides[i], biomes[i]);
}
}
public Tile(Board board, int x, int y, int radius) {
super(board, x, y, radius);
this.assignRandomBiomes();
}
public Tile(Board board, Point center, int radius, Biome... biomes) {
this(board, center.x, center.y, radius, biomes);
}
public Tile(Board board, Point center, int radius) {
this(board, center.x, center.y, radius);
}
public void setBiomes(Biome... biomes) {
TileOrientation[] sides = TileOrientation.values();
for (int i = 0; i < sides.length; i++) {
this.sideBiomes.put(sides[i], biomes[i]);
}
}
public void assignRandomBiomes() {
Game game = this.getBoard().getGame();
Biome[] biomes = Biome.values();
TileOrientation[] sides = TileOrientation.values();
this.sideBiomes.clear();
Biome firstBiome = biomes[game.getRandomInt(biomes.length)];
biomes = Arrays.stream(biomes).filter(b -> b != firstBiome).toArray(Biome[]::new);
Biome secondBiome = biomes[game.getRandomInt(biomes.length)];
int firstBiomeSideCount = game.getRandomInt(sides.length + 1);
int firstBiomeSideOffset = game.getRandomInt(sides.length);
for (int i = 0; i < sides.length; i++) {
TileOrientation side = sides[(i + firstBiomeSideOffset) % sides.length];
Biome assignedBiome = (i < firstBiomeSideCount) ? firstBiome : secondBiome;
this.sideBiomes.put(side, assignedBiome);
}
}
public Biome getBiome(TileOrientation side) {
return this.sideBiomes.get(side);
}
private Biome getDominantBiome() {
TileOrientation[] sides = TileOrientation.values();
int firstBiomeCount = 0;
int secondBiomeCount = 0;
Biome firstBiome = this.getBiome(sides[0]);
Biome secondBiome = null;
for (TileOrientation side : sides) {
Biome currentBiome = this.getBiome(side);
if (currentBiome.equals(firstBiome)) {
firstBiomeCount++;
} else {
secondBiome = currentBiome;
secondBiomeCount++;
}
}
if (firstBiomeCount > secondBiomeCount) {
return firstBiome;
} else if (firstBiomeCount < secondBiomeCount) {
return secondBiome;
}
return null;
}
public Biome[] getBiomes() {
Biome[] biomes = new Biome[TileOrientation.values().length];
for (TileOrientation side : TileOrientation.values()) {
biomes[side.ordinal()] = this.getBiome(side);
}
return biomes;
}
public void rotate(boolean clockwise) {
TileOrientation[] sides = TileOrientation.values();
HashMap<TileOrientation, Biome> newBiomesMap = new HashMap<>();
for (int i = 0; i < sides.length; i++) {
TileOrientation side = sides[i];
TileOrientation newSide = clockwise ? sides[(i + 1) % sides.length] : sides[(i + sides.length - 1) % sides.length];
newBiomesMap.put(newSide, this.sideBiomes.get(side));
}
this.sideBiomes = newBiomesMap;
this.repaint();
}
public boolean containsBiome(Biome biome) {
for (TileOrientation side : TileOrientation.values()) {
if (this.getBiome(side) == biome) {
return true;
}
}
return false;
}
public boolean isAdjacentTo(Tile otherTile) {
// Obtenir le rayon de la tuile
int tileRadius = this.getRadius();
// Compute the distance between the center of this tile and the other tile
int deltaX = this.getX() - otherTile.getX();
int deltaY = this.getY() - otherTile.getY();
// Calculate the Euclidean distance between the two tiles
double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// In a hexagonal grid, two tiles are adjacent if their distance is equal to the diameter (2 * radius)
return distance <= (2 * tileRadius);
}
private TileOrientation determineSide(int x, int y) {
int radius = this.getRadius();
TileOrientation[] sides = TileOrientation.values();
double angle = Cell.to360Degrees(Math.toDegrees(Math.atan2(y - radius, x - radius)) + 120);
int floorSide = (int) Math.floor(Cell.to360Degrees(angle - 2) / 60);
int ceilSide = (int) Math.floor(Cell.to360Degrees(angle + 2) / 60);
if (floorSide == ceilSide) {
return sides[floorSide];
}
Biome floorBiome = this.getBiome(sides[floorSide]);
Biome dominantBiome = this.getDominantBiome();
if (dominantBiome == null && y > radius) {
return TileOrientation.SOUTH;
}
if (dominantBiome == null && y < radius) {
return TileOrientation.NORTH;
}
return floorBiome.equals(dominantBiome) ? sides[ceilSide] : sides[floorSide];
}
private void drawHexagonRow(Graphics2D g2d, double rowX, double rowY, double radius, int rowLength) {
int gRadius = this.getRadius();
for (int i = 0; i < rowLength; i++) {
Color[] colors;
int x = (int) Math.round(rowX + radius * Math.sqrt(3) * i);
int y = (int) Math.round(rowY);
if (x == Math.round(gRadius) && y == Math.round(gRadius)) {
Biome dominantBiome = this.getDominantBiome();
colors = (dominantBiome != null) ? dominantBiome.getBiomeColors() : this.getBiome(TileOrientation.SOUTH).getBiomeColors();
} else {
colors = this.getBiome(this.determineSide(x, y)).getBiomeColors();
}
g2d.setColor(colors[i % colors.length]);
g2d.fillPolygon(new Hexagon(x, y, (int) Math.ceil(radius), 90));
}
}
protected void drawTileAt(Graphics g, int x, int y, float scale) {
// Sauvegarde de l'état actuel du graphique
Graphics2D g2d = (Graphics2D) g.create();
// Déplacement du contexte graphique à la position souhaitée
g2d.translate(x, y);
// Appel de la méthode de dessin de la tuile à la nouvelle position
paintTile(g2d, scale);
g2d.dispose();
}
/**
* Méthode principale de dessin de la tuile.
*
* @param g Le contexte graphique
* @param scale L'échelle de la tuile
*/
protected void paintTile(Graphics g, float scale) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = this.getRadius();
Point center = new Point(radius, radius);
radius = (int) (radius * scale);
Hexagon hexagon = new Hexagon(center, radius);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setClip(hexagon);
double hexRadius = radius / Math.sqrt(3) / 3;
double paddingX = center.x - radius;
double paddingY = center.y - radius;
this.drawHexagonRow(g2d, paddingX + radius * 0.5, paddingY + radius - radius * Math.sqrt(3) / 2, hexRadius, 4);
this.drawHexagonRow(g2d, paddingX, paddingY + radius - radius * Math.sqrt(3) / 3, hexRadius, 6);
this.drawHexagonRow(g2d, paddingX - radius * 0.5, paddingY + radius - radius * Math.sqrt(3) / 6, hexRadius, 8);
this.drawHexagonRow(g2d, paddingX - radius, paddingY + radius, hexRadius, 10);
this.drawHexagonRow(g2d, paddingX - radius * 0.5, paddingY + radius + radius * Math.sqrt(3) / 6, hexRadius, 8);
this.drawHexagonRow(g2d, paddingX, paddingY + radius + radius * Math.sqrt(3) / 3, hexRadius, 6);
this.drawHexagonRow(g2d, paddingX + radius * 0.5, paddingY + radius + radius * Math.sqrt(3) / 2, hexRadius, 4);
g2d.setClip(null);
g2d.setStroke(new BasicStroke((int) radius / 15));
g2d.setColor(Color.BLACK);
g2d.drawPolygon(hexagon);
g2d.dispose();
}
}

View File

@@ -0,0 +1,25 @@
package fr.monkhanny.dorfromantik.game;
import fr.monkhanny.dorfromantik.listeners.TilePanningActionListener;
public class TilePanningTransition {
private Board board;
private int targetOffsetX, targetOffsetY;
private int steps;
public TilePanningTransition(Board board, int targetOffsetX, int targetOffsetY, int steps) {
this.board = board;
this.targetOffsetX = targetOffsetX;
this.targetOffsetY = targetOffsetY;
this.steps = steps;
}
public void start() {
// Créer un listener d'animation
TilePanningActionListener listener = new TilePanningActionListener(board, targetOffsetX, targetOffsetY, steps);
// Démarrer l'animation si aucune n'est en cours
listener.startAnimation();
}
}