Amélioration du code et des menus

This commit is contained in:
2024-12-06 21:18:17 +01:00
parent 0720699f10
commit 0d4106f562
6 changed files with 210 additions and 125 deletions

View File

@@ -7,17 +7,61 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Listener pour animer un bouton lorsqu'il est survolé par la souris.
* Cette classe permet d'agrandir ou de réduire la taille de la police et de changer la couleur du bouton
* lorsque la souris entre ou sort de la zone du bouton.
*
* @version 1.0
* @author Moncef STITI, Lenny FOULOU
*/
public class ButtonHoverAnimationListener implements ActionListener {
private int step = 0;
/*
* Compteur d'étapes pour l'animation
*/
private int step;
/*
* Incrément de mise à l'échelle à chaque étape
*/
private final float scaleIncrement;
/*
* Indique si la souris entre ou quitte le bouton
*/
private final boolean entering;
/*
* Référence au bouton à animer
*/
private final JButton button;
/*
* Couleur d'origine du bouton
*/
private final Color originalColor;
/*
* Police d'origine du bouton
*/
private final Font originalFont;
/*
* Échelle actuelle de la police
*/
private float currentScale = 1.0f;
/**
* Constructeur pour initialiser les variables du listener.
*
* @param entering Indique si la souris entre ou quitte le bouton
* @param button Référence au bouton à animer
* @param originalColor Couleur d'origine du bouton
* @param originalFont Police d'origine du bouton
*/
public ButtonHoverAnimationListener(boolean entering, JButton button, Color originalColor, Font originalFont) {
this.step = 0;
this.entering = entering;
this.button = button;
this.originalColor = originalColor;
@@ -25,18 +69,29 @@ public class ButtonHoverAnimationListener implements ActionListener {
this.scaleIncrement = (Options.HOVER_FONT_SCALE - 1.0f) / Options.ANIMATION_STEPS;
}
/**
* Méthode appelée à chaque étape de l'animation.
* Modifie la taille de la police et la couleur du bouton en fonction de l'état de l'animation.
*
* @param e l'événement d'action qui est émis par le Timer
*/
@Override
public void actionPerformed(ActionEvent e) {
// Calcul de la nouvelle échelle en fonction de l'état "entrant" ou "sortant"
currentScale = entering ? (1.0f + step * scaleIncrement) : (Options.HOVER_FONT_SCALE - step * scaleIncrement);
// Modification de la couleur du bouton en fonction de l'état "entrant" ou "sortant"
button.setForeground(entering ? Options.BUTTON_HOVER_COLOR : originalColor);
// Application de la nouvelle taille de police au bouton
button.setFont(originalFont.deriveFont(originalFont.getSize2D() * currentScale));
// Incrémente le compteur d'étapes
step++;
// Si le nombre d'étapes est atteint, arrête le Timer et réinitialise les éléments si la souris sort
if (step >= Options.ANIMATION_STEPS) {
((Timer) e.getSource()).stop();
if (!entering) {
button.setFont(originalFont); // Restore the original font
button.setFont(originalFont); // Restauration de la police originale si la souris quitte le bouton
}
}
}

View File

@@ -1,8 +1,6 @@
package fr.monkhanny.dorfromantik.game;
import fr.monkhanny.dorfromantik.enums.Biome;
import fr.monkhanny.dorfromantik.enums.TileOrientation;
import java.awt.Point;
import java.util.*;
/**

View File

@@ -57,14 +57,12 @@ public class ScoreManager {
newPocket.addTile(tile);
pockets.add(newPocket);
biomeToPocketMap.put(biome, newPocket);
System.out.println("New pocket created with biome: " + biome);
}
}
}
// Recalculer le score après avoir ajouté la tuile
recalculateScore();
System.out.println("Current Score: " + currentScore);
}
/**
@@ -83,46 +81,6 @@ public class ScoreManager {
return null;
}
/**
* Finds a pocket connected to the given tile with the specified biome.
*
* @param tile The tile to check connections for.
* @param biome The biome to match.
* @return The connected pocket, or null if none found.
*/
private Pocket findConnectedPocket(Tile tile, Biome biome) {
for (Pocket pocket : pockets) {
if (pocket.getBiome() == biome) {
for (Tile pocketTile : pocket.getTiles()) {
if (pocketTile.isAdjacentTo(tile) && sharesBiome(tile, pocketTile, biome)) {
return pocket;
}
}
}
}
return null;
}
/**
* Checks if two tiles share a biome on any of their sides.
*
* @param tile1 The first tile.
* @param tile2 The second tile.
* @param biome The biome to match.
* @return True if the tiles share the given biome on a connecting side.
*/
private boolean sharesBiome(Tile tile1, Tile tile2, Biome biome) {
for (TileOrientation orientation : TileOrientation.values()) {
if (tile1.getBiome(orientation) == biome && tile2.getBiome(orientation.oppositeOrientation()) == biome) {
return true;
}
}
return false;
}
/**
* Recalculates the score based on the current pockets.
*/

View File

@@ -33,6 +33,7 @@ public class GameModeSelectionPanel extends JPanel {
private JSpinner startDateSpinner;
private JSpinner endDateSpinner;
private ActionListener buttonListener;
private JCheckBox developerSeriesCheckBox;
public GameModeSelectionPanel(ActionListener buttonListener, JFrame gameModeFrame, MainMenu mainMenu) {
this.buttonListener = buttonListener;
@@ -62,7 +63,7 @@ public class GameModeSelectionPanel extends JPanel {
background.add(mainPanel, BorderLayout.CENTER);
// Title
titleLabel = new Title("Choisissez un série", 60f, Color.WHITE);
titleLabel = new Title("Choisissez une série", 60f, Color.WHITE);
mainPanel.add(titleLabel, createGridBagConstraints(0, 0, 2));
mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 1, 1));
@@ -76,6 +77,7 @@ public class GameModeSelectionPanel extends JPanel {
modePanel.setOpaque(false);
seriesButtons = new ArrayList<>();
// Pagination panel
JPanel paginationPanel = createPaginationPanel();
@@ -87,9 +89,9 @@ public class GameModeSelectionPanel extends JPanel {
mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 5, 1));
// Seed input and start button
// Seed input and start button anchored at the bottom
JPanel seedPanel = createSeedPanel(buttonListener);
mainPanel.add(seedPanel, createGridBagConstraints(0, 6, 2));
background.add(seedPanel, BorderLayout.SOUTH);
}
public void loadSeriesForCurrentPage() {
@@ -104,27 +106,29 @@ public class GameModeSelectionPanel extends JPanel {
// Calculer le lendemain de la date de fin
Calendar cal = Calendar.getInstance();
cal.setTime(endDate);
cal.add(Calendar.DAY_OF_MONTH, 1); // Ajouter un jour pour obtenir le lendemain
Date nextDay = cal.getTime(); // Le lendemain de endDate
cal.add(Calendar.DAY_OF_MONTH, 1);
Date nextDay = cal.getTime();
// Vérifier si la case à cocher est sélectionnée
boolean onlyDeveloperCreated = developerSeriesCheckBox.isSelected();
// Get paginated series
List<String> series = database.getSeriesByDateRangePaginated(startDate, nextDay,
currentPage,
itemsPerPage);
List<String> series = database.getSeriesByDateRangePaginated(startDate, nextDay, currentPage, itemsPerPage, onlyDeveloperCreated);
// Si aucune série n'est trouvée pour la période donnée, afficher un message
if (series.isEmpty()) {
JOptionPane.showMessageDialog(this, "Aucune série pour la période donnée",
"Avertissement", JOptionPane.WARNING_MESSAGE);
JOptionPane.showMessageDialog(this, "Aucune série pour la période donnée", "Avertissement", JOptionPane.WARNING_MESSAGE);
currentPage = 1; // Reset current page to 1 if no series is available
updatePageLabelAndButtons(1, 1); // Mettre à jour le label et désactiver les boutons
return;
}
// Calculate grid layout dimensions
int buttonCount = series.size();
int columns = Math.min(buttonCount, 5); // Maximum 5 buttons per row
int columns = Math.min(buttonCount, 5);
int rows = (int) Math.ceil((double) buttonCount / columns);
modePanel.setLayout(new GridLayout(rows, columns, 20, 10)); // Add spacing between buttons
modePanel.setLayout(new GridLayout(rows, columns, 20, 10));
for (String seriesName : series) {
JButton seriesButton = createGameModeButton(seriesName, buttonListener);
@@ -133,13 +137,13 @@ public class GameModeSelectionPanel extends JPanel {
}
// Update page label
int totalSeries = database.countSeriesByDateRange(startDate, nextDay);
int totalSeries = database.countSeriesByDateRange(startDate, nextDay, onlyDeveloperCreated);
int totalPages = (int) Math.ceil((double) totalSeries / itemsPerPage);
pageLabel.setText("Page " + currentPage + " / " + totalPages);
// Enable/disable pagination buttons
prevButton.setEnabled(currentPage > 1);
nextButton.setEnabled(currentPage < totalPages);
// Assurez-vous que totalPages est au moins 1
totalPages = Math.max(totalPages, 1);
currentPage = Math.min(currentPage, totalPages); // Assurez-vous que la page actuelle ne dépasse pas le nombre total de pages
updatePageLabelAndButtons(currentPage, totalPages);
// Refresh the panel
modePanel.revalidate();
@@ -147,52 +151,108 @@ public class GameModeSelectionPanel extends JPanel {
}
private void updatePageLabelAndButtons(int currentPage, int totalPages) {
pageLabel.setText("Page " + currentPage + " / " + totalPages);
// Enable/disable pagination buttons
prevButton.setEnabled(currentPage > 1);
nextButton.setEnabled(currentPage < totalPages);
// Show/Hide pagination buttons if there is only one page
boolean multiplePages = totalPages > 1;
prevButton.setVisible(multiplePages);
nextButton.setVisible(multiplePages);
pageLabel.setVisible(multiplePages);
}
private JPanel createDateFilterPanel() {
JPanel datePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
// Création du panneau de date avec un BoxLayout vertical pour un meilleur agencement
JPanel datePanel = new JPanel();
datePanel.setOpaque(false);
datePanel.setLayout(new BoxLayout(datePanel, BoxLayout.Y_AXIS));
// Panneau contenant les spinners de date
JPanel dateSpinnersPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
dateSpinnersPanel.setOpaque(false);
JLabel startLabel = new JLabel("Date de début:");
startLabel.setForeground(Color.WHITE);
startLabel.setFont(new Font("Arial", Font.BOLD, 16));
JLabel endLabel = new JLabel("Date de fin:");
endLabel.setForeground(Color.WHITE);
endLabel.setFont(new Font("Arial", Font.BOLD, 16));
// Créer des spinners pour les dates de début et de fin
// Créer les spinners pour les dates de début et de fin
Calendar cal = Calendar.getInstance();
Date endDate = cal.getTime();
cal.add(Calendar.DAY_OF_YEAR, -30);
Date startDate = cal.getTime();
SpinnerDateModel startDateModel = new SpinnerDateModel(
startDate, // Date par défaut (30 jours avant aujourd'hui)
null, // Pas de date minimale
endDate, // Date maximale = aujourd'hui
Calendar.DAY_OF_MONTH // Unité de changement
);
SpinnerDateModel startDateModel = new SpinnerDateModel(startDate, null, endDate, Calendar.DAY_OF_MONTH);
startDateSpinner = new JSpinner(startDateModel);
startDateSpinner.setEditor(new JSpinner.DateEditor(startDateSpinner, "yyyy-MM-dd"));
startDateSpinner.setEditor(new JSpinner.DateEditor(startDateSpinner, "dd-MM-yyyy"));
stylizeDateSpinner(startDateSpinner);
SpinnerDateModel endDateModel = new SpinnerDateModel(
endDate, // Date par défaut = aujourd'hui
null, // Pas de date minimale
endDate, // Date maximale = aujourd'hui
Calendar.DAY_OF_MONTH // Unité de changement
);
SpinnerDateModel endDateModel = new SpinnerDateModel(endDate, null, endDate, Calendar.DAY_OF_MONTH);
endDateSpinner = new JSpinner(endDateModel);
endDateSpinner.setEditor(new JSpinner.DateEditor(endDateSpinner, "yyyy-MM-dd"));
endDateSpinner.setEditor(new JSpinner.DateEditor(endDateSpinner, "dd-MM-yyyy"));
stylizeDateSpinner(endDateSpinner);
dateSpinnersPanel.add(startLabel);
dateSpinnersPanel.add(startDateSpinner);
dateSpinnersPanel.add(endLabel);
dateSpinnersPanel.add(endDateSpinner);
// Ajouter la case à cocher pour les séries créées par les développeurs
developerSeriesCheckBox = new JCheckBox("Inclure seulement les séries créées par les développeurs");
developerSeriesCheckBox.setOpaque(false);
developerSeriesCheckBox.setForeground(Color.WHITE);
developerSeriesCheckBox.setFont(new Font("Arial", Font.BOLD, 16));
developerSeriesCheckBox.setAlignmentX(Component.CENTER_ALIGNMENT);
// Créer un bouton de filtre
JButton filterButton = new JButton("Filtrer");
filterButton.setFont(new Font("Arial", Font.BOLD, 16));
filterButton.setBackground(new Color(70, 130, 180));
filterButton.setForeground(Color.WHITE);
filterButton.setFocusPainted(false);
filterButton.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(255, 255, 255, 120), 2),
BorderFactory.createEmptyBorder(5, 15, 5, 15)
));
filterButton.setAlignmentX(Component.CENTER_ALIGNMENT);
filterButton.addActionListener(new GameModeFilterButtonActionListener(this));
datePanel.add(startLabel);
datePanel.add(startDateSpinner);
datePanel.add(endLabel);
datePanel.add(endDateSpinner);
// Ajouter les composants au panneau principal de filtre
datePanel.add(dateSpinnersPanel);
datePanel.add(Box.createVerticalStrut(10));
datePanel.add(developerSeriesCheckBox);
datePanel.add(Box.createVerticalStrut(15));
datePanel.add(filterButton);
return datePanel;
}
private void stylizeDateSpinner(JSpinner spinner) {
JComponent editor = spinner.getEditor();
if (editor instanceof JSpinner.DefaultEditor) {
JSpinner.DefaultEditor defaultEditor = (JSpinner.DefaultEditor) editor;
JTextField textField = defaultEditor.getTextField();
textField.setFont(new Font("Arial", Font.PLAIN, 16));
textField.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(255, 255, 255, 120), 2),
BorderFactory.createEmptyBorder(5, 10, 5, 10)
));
textField.setBackground(new Color(40, 40, 40)); // Fond doux pour les spinners
textField.setForeground(Color.WHITE); // Texte blanc pour une meilleure lisibilité
textField.setCaretColor(Color.WHITE); // Curseur blanc
}
}
private JPanel createPaginationPanel() {
JPanel paginationPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
paginationPanel.setOpaque(false);

View File

@@ -5,6 +5,9 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import fr.monkhanny.dorfromantik.enums.Sounds;
import fr.monkhanny.dorfromantik.utils.MusicPlayer;
public class GameModeHoverEffectMouseListener extends MouseAdapter {
private Color defaultColor;
private Color hoverColor;
@@ -20,6 +23,8 @@ public class GameModeHoverEffectMouseListener extends MouseAdapter {
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof JButton button) {
button.setBackground(hoverColor);
MusicPlayer.loadSound(Sounds.SOUNDS1); // Charge le son
MusicPlayer.playSound(); // Joue le son
}
}

View File

@@ -133,14 +133,19 @@ public class Database {
}
// New method to count series within a date range
public int countSeriesByDateRange(Date startDate, Date endDate) {
public int countSeriesByDateRange(Date startDate, Date endDate, boolean onlyDeveloperCreated) {
int count = 0;
try {
String query = "SELECT COUNT(*) as series_count FROM Series WHERE creation_date BETWEEN ? AND ?";
// Construire la requête SQL en fonction du filtre "created_by_developer"
String query = "SELECT COUNT(*) as series_count FROM Series WHERE creation_date BETWEEN ? AND ? " +
(onlyDeveloperCreated ? "AND created_by_developer = TRUE " : "");
// Préparer l'instruction
PreparedStatement statement = this.database.prepareStatement(query);
statement.setDate(1, new java.sql.Date(startDate.getTime()));
statement.setDate(2, new java.sql.Date(endDate.getTime()));
// Exécuter la requête et récupérer le résultat
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
count = resultSet.getInt("series_count");
@@ -151,37 +156,41 @@ public class Database {
return count;
}
// New method to get paginated series within a date range
public List<String> getSeriesByDateRangePaginated(Date startDate, Date endDate,
int page, int itemsPerPage) {
List<String> series = new ArrayList<>();
try {
String query = "SELECT name FROM Series " +
int page, int itemsPerPage,
boolean onlyDeveloperCreated) {
List<String> series = new ArrayList<>();
try {
String query = "SELECT name FROM Series " +
"WHERE creation_date BETWEEN ? AND ? " +
(onlyDeveloperCreated ? "AND created_by_developer = TRUE " : "") +
"ORDER BY " +
" CASE " +
" WHEN name LIKE 'Série custom%' THEN CAST(REGEXP_SUBSTR(name, '[0-9]+') AS UNSIGNED) " + // Extraction numérique pour 'Série custom'
" WHEN name LIKE 'Série custom%' THEN CAST(REGEXP_SUBSTR(name, '[0-9]+') AS UNSIGNED) " +
" ELSE NULL " +
" END ASC, " + // Tri par numéro pour 'Série custom'
" created_by_developer DESC, " + // Tri par développeur ou joueur
" name ASC " + // Tri alphabétique
" END ASC, " +
" created_by_developer DESC, " +
" name ASC " +
"LIMIT ? OFFSET ?";
PreparedStatement statement = this.database.prepareStatement(query);
statement.setDate(1, new java.sql.Date(startDate.getTime()));
statement.setDate(2, new java.sql.Date(endDate.getTime()));
statement.setInt(3, itemsPerPage);
statement.setInt(4, (page - 1) * itemsPerPage);
PreparedStatement statement = this.database.prepareStatement(query);
statement.setDate(1, new java.sql.Date(startDate.getTime()));
statement.setDate(2, new java.sql.Date(endDate.getTime()));
statement.setInt(3, itemsPerPage);
statement.setInt(4, (page - 1) * itemsPerPage);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
series.add(resultSet.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
series.add(resultSet.getString("name"));
}
return series;
} catch (SQLException e) {
e.printStackTrace();
}
return series;
}
// Optional: Method to get series within a specific number of days
public List<String> getRecentSeries(int days) {