Ajouts de deux mode de leaderboard

This commit is contained in:
2024-11-23 16:03:08 +01:00
parent 42c52e011c
commit 35bb9dfec4
11 changed files with 395 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,12 @@
package fr.monkhanny.dorfromantik.gui;
import javax.swing.*;
import java.awt.*;
public abstract class Leaderboard extends JPanel {
public Leaderboard() {
setLayout(new BorderLayout());
}
public abstract void refresh(); // Méthode pour actualiser le contenu
}

View File

@@ -0,0 +1,40 @@
package fr.monkhanny.dorfromantik.gui;
import javax.swing.*;
import java.awt.*;
public class LeaderboardBarChartPanel extends JPanel {
private int totalPlayers;
private int rank;
public LeaderboardBarChartPanel(int totalPlayers, int rank) {
this.totalPlayers = totalPlayers;
this.rank = rank;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int barWidth = 30; // Largeur des barres
int spacing = 10; // Espacement entre les barres
int barHeight = 20; // Hauteur de la barre
int totalBars = 10; // Nombre de tranches
int maxWidth = (getWidth() - (totalBars + 1) * spacing) / totalBars;
// Dessiner chaque barre pour chaque tranche
for (int i = 0; i < totalBars; i++) {
int x = spacing + i * (maxWidth + spacing);
int y = 50; // Position verticale de la barre
// Déterminer la couleur : colorier la tranche actuelle
if (i == (rank - 1) / (totalPlayers / 10)) {
g.setColor(new Color(0, 255, 0)); // Vert pour la tranche actuelle
} else {
g.setColor(new Color(255, 0, 0)); // Rouge pour les autres tranches
}
// Dessiner la barre
g.fillRect(x, y, maxWidth, barHeight);
}
}
}

View File

@@ -0,0 +1,64 @@
package fr.monkhanny.dorfromantik.gui;
import javax.swing.*;
import java.awt.*;
// @TODO : MODIFIER CAR C'EST PAS BEAU + BDD
public class LeaderboardByTier extends Leaderboard {
public LeaderboardByTier() {
super();
refresh(); // Charge les données initiales
}
@Override
public void refresh() {
removeAll(); // Supprime tout contenu existant
setBackground(new Color(64, 0, 128));
// Titre
JLabel titleLabel = new JLabel("CLASSEMENT PAR TRANCHE");
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(new Font("Arial", Font.BOLD, 24));
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
add(titleLabel, BorderLayout.NORTH);
// Contenu
JPanel tierPanel = new JPanel();
tierPanel.setLayout(new BoxLayout(tierPanel, BoxLayout.Y_AXIS));
tierPanel.setBackground(new Color(64, 0, 128));
// Exemple de tranche
int totalPlayers = 1000;
int rank = 237; // Exemple : rang du joueur
int tierSize = totalPlayers / 10;
int tier = (rank - 1) / tierSize + 1;
// Label indiquant la tranche dans laquelle le joueur se trouve
JLabel infoLabel = new JLabel("Vous êtes dans la tranche : " + tier);
infoLabel.setFont(new Font("Arial", Font.PLAIN, 18));
infoLabel.setForeground(Color.WHITE);
infoLabel.setAlignmentX(CENTER_ALIGNMENT);
// Pourcentage du joueur
double percentage = (double) rank / totalPlayers * 100;
JLabel percentageLabel = new JLabel(String.format("Vous faites partie des %.2f%% des joueurs", percentage));
percentageLabel.setFont(new Font("Arial", Font.PLAIN, 18));
percentageLabel.setForeground(Color.WHITE);
percentageLabel.setAlignmentX(CENTER_ALIGNMENT);
// Ajouter les labels à la JPanel
tierPanel.add(Box.createVerticalStrut(20));
tierPanel.add(infoLabel);
tierPanel.add(percentageLabel);
// Ajouter le diagramme en barres pour les tranches
LeaderboardBarChartPanel barChartPanel = new LeaderboardBarChartPanel(totalPlayers, rank);
tierPanel.add(Box.createVerticalStrut(20)); // Espacement
tierPanel.add(barChartPanel);
add(tierPanel, BorderLayout.CENTER);
revalidate();
repaint();
}
}

View File

@@ -0,0 +1,160 @@
package fr.monkhanny.dorfromantik.gui;
import fr.monkhanny.dorfromantik.utils.Database;
import fr.monkhanny.dorfromantik.utils.PlayerScore;
import javax.swing.*;
import java.awt.*;
import java.sql.SQLException;
import java.util.List;
public class LeaderboardWorldWide extends Leaderboard {
public LeaderboardWorldWide() {
super();
refresh(); // Charge les données initiales
}
@Override
public void refresh() {
removeAll(); // Supprime tout contenu existant
setBackground(new Color(238, 238, 238)); // Gris clair moderne
// Panel principal pour centrer le leaderboard
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBackground(new Color(238, 238, 238)); // Gris clair
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Titre
JLabel titleLabel = new JLabel("Classement mondial");
titleLabel.setForeground(new Color(34, 139, 34)); // Vert forêt pour le titre
titleLabel.setFont(new Font("Roboto", Font.BOLD, 32)); // Police moderne
titleLabel.setAlignmentX(CENTER_ALIGNMENT);
// Panel pour les trois premiers
JPanel topThreePanel = new JPanel(new GridBagLayout());
topThreePanel.setBackground(new Color(238, 238, 238)); // Gris clair
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(0, 10, 0, 10);
// Récupérer les meilleurs joueurs depuis la base de données
Database db = null;
List<PlayerScore> topPlayers = null;
try {
db = new Database();
topPlayers = db.getTopPlayers();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (db != null) {
db.close();
}
}
if (topPlayers != null && topPlayers.size() >= 3) {
// Ajout des trois premiers joueurs avec médailles
gbc.gridx = 0;
gbc.weightx = 0.4;
topThreePanel.add(createTopPlayerPanel(topPlayers.get(1).getUsername(), topPlayers.get(1).getScore(),
"./ressources/images/MainMenu/Leaderboard/2.png", false), gbc);
gbc.gridx = 1;
gbc.weightx = 0.5;
topThreePanel.add(createTopPlayerPanel(topPlayers.get(0).getUsername(), topPlayers.get(0).getScore(),
"./ressources/images/MainMenu/Leaderboard/1.png", true), gbc);
gbc.gridx = 2;
gbc.weightx = 0.4;
topThreePanel.add(createTopPlayerPanel(topPlayers.get(2).getUsername(), topPlayers.get(2).getScore(),
"./ressources/images/MainMenu/Leaderboard/3.png", false), gbc);
}
// Panel pour les autres joueurs
JPanel playersPanel = new JPanel();
playersPanel.setLayout(new BoxLayout(playersPanel, BoxLayout.Y_AXIS));
playersPanel.setBackground(new Color(255, 255, 255)); // Blanc cassé
// Ajout des joueurs restants (de 4 à 10)
if (topPlayers != null) {
for (int i = 3; i < topPlayers.size(); i++) {
PlayerScore player = topPlayers.get(i);
playersPanel.add(createPlayerPanel(player.getUsername(), player.getScore(), i + 1));
}
}
// Ajoute tout au panneau principal
mainPanel.add(titleLabel);
mainPanel.add(Box.createRigidArea(new Dimension(0, 20)));
mainPanel.add(topThreePanel);
mainPanel.add(Box.createRigidArea(new Dimension(0, 20)));
mainPanel.add(playersPanel);
add(mainPanel, BorderLayout.CENTER);
revalidate();
repaint();
}
private JPanel createPlayerPanel(String playerName, int score, int rank) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBackground(new Color(250, 250, 250)); // Blanc cassé
panel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(200, 200, 200))); // Bordure gris clair
JLabel rankLabel = new JLabel(rank + ". ");
rankLabel.setFont(new Font("Roboto", Font.BOLD, 18));
rankLabel.setForeground(new Color(34, 139, 34)); // Vert forêt pour le rang
rankLabel.setPreferredSize(new Dimension(40, 40));
JLabel nameLabel = new JLabel(playerName);
nameLabel.setFont(new Font("Roboto", Font.PLAIN, 18));
nameLabel.setForeground(new Color(58, 58, 58)); // Gris clair
JLabel scoreLabel = new JLabel(Integer.toString(score));
scoreLabel.setFont(new Font("Roboto", Font.BOLD, 18));
scoreLabel.setForeground(new Color(255, 165, 0)); // Orange moderne
panel.add(rankLabel, BorderLayout.WEST);
panel.add(nameLabel, BorderLayout.CENTER);
panel.add(scoreLabel, BorderLayout.EAST);
return panel;
}
private ImageIcon resizeIcon(String path, int width, int height) {
ImageIcon icon = new ImageIcon(path);
Image img = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
return new ImageIcon(img);
}
private JPanel createTopPlayerPanel(String playerName, int score, String medalPath, boolean isFirst) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(isFirst ? new Color(255, 223, 0) : new Color(144, 238, 144)); // Doré pour le premier
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Ajout de l'icône de médaille redimensionnée
JLabel medalLabel = new JLabel(resizeIcon(medalPath, isFirst ? 80 : 60, isFirst ? 80 : 60));
medalLabel.setAlignmentX(CENTER_ALIGNMENT);
JLabel nameLabel = new JLabel(playerName);
nameLabel.setFont(new Font("Roboto", isFirst ? Font.BOLD : Font.PLAIN, 20));
nameLabel.setForeground(new Color(34, 139, 34)); // Vert forêt pour le nom
nameLabel.setAlignmentX(CENTER_ALIGNMENT);
JLabel scoreLabel = new JLabel(Integer.toString(score));
scoreLabel.setFont(new Font("Roboto", Font.BOLD, isFirst ? 32 : 28));
scoreLabel.setForeground(new Color(58, 58, 58));
scoreLabel.setAlignmentX(CENTER_ALIGNMENT);
panel.add(medalLabel);
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(nameLabel);
panel.add(Box.createRigidArea(new Dimension(0, 5)));
panel.add(scoreLabel);
return panel;
}
}

View File

@@ -8,13 +8,17 @@ import fr.monkhanny.dorfromantik.Options;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainMenu extends JFrame {
private Title titleLabel;
private ButtonPanel buttonPanel;
private JPanel leaderboardContainer; // Conteneur pour le leaderboard
private Leaderboard currentLeaderboard; // Référence au leaderboard actuel
private JButton toggleLeaderboardButton; // Bouton pour basculer entre les leaderboards
public MainMenu() {
// Charger les polices pour le titre et les boutons
@@ -39,10 +43,39 @@ public class MainMenu extends JFrame {
this.titleLabel = new Title("Dorfromantik", Options.BASE_TITLE_FONT_SIZE);
background.add(titleLabel, BorderLayout.NORTH);
// Panneau des boutons avec style personnalisé
// Panneau des boutons avec style personnalisé (à gauche)
this.buttonPanel = new ButtonPanel(Options.BASE_BUTTON_FONT_SIZE);
background.add(buttonPanel, BorderLayout.WEST);
// Panel contenant le leaderboard avec espace à droite (pour pas qu'il soit collé au bord)
JPanel leaderboardWrapper = new JPanel();
leaderboardWrapper.setLayout(new BorderLayout());
leaderboardWrapper.setOpaque(false); // Fond transparent pour laisser voir le background
leaderboardWrapper.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 20)); // Ajout de marges internes
// Conteneur du leaderboard
leaderboardContainer = new JPanel();
leaderboardContainer.setLayout(new BorderLayout());
leaderboardContainer.setOpaque(false); // Fond transparent pour laisser voir le background
leaderboardWrapper.add(leaderboardContainer, BorderLayout.CENTER);
background.add(leaderboardWrapper, BorderLayout.EAST);
// Initialisation du premier leaderboard (LeaderboardWorldwide)
currentLeaderboard = new LeaderboardWorldWide();
leaderboardContainer.add(currentLeaderboard, BorderLayout.CENTER);
// Bouton pour basculer entre les leaderboards
toggleLeaderboardButton = new JButton("Changement de classement");
toggleLeaderboardButton.setFont(new Font("Arial", Font.BOLD, 16));
toggleLeaderboardButton.setBackground(new Color(64, 0, 128));
toggleLeaderboardButton.setForeground(Color.WHITE);
toggleLeaderboardButton.setFocusPainted(false);
toggleLeaderboardButton.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
leaderboardContainer.add(toggleLeaderboardButton, BorderLayout.SOUTH);
// Ajouter l'action du bouton
toggleLeaderboardButton.addActionListener(new LeaderboardToggleActionListener(leaderboardContainer, currentLeaderboard));
setVisible(true);
}

View File

@@ -0,0 +1,35 @@
package fr.monkhanny.dorfromantik.gui;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
public class LeaderboardToggleActionListener implements ActionListener {
private boolean showingWorldwide = true;
private JPanel leaderboardContainer;
private Leaderboard currentLeaderboard;
// Constructeur qui reçoit le conteneur du leaderboard
public LeaderboardToggleActionListener(JPanel leaderboardContainer, Leaderboard currentLeaderboard) {
this.leaderboardContainer = leaderboardContainer;
this.currentLeaderboard = currentLeaderboard;
}
@Override
public void actionPerformed(ActionEvent e) {
// Basculer entre les deux leaderboards
leaderboardContainer.remove(currentLeaderboard);
if (showingWorldwide) {
currentLeaderboard = new LeaderboardByTier(); // Leaderboard par tranche
} else {
currentLeaderboard = new LeaderboardWorldWide(); // Leaderboard avec les meilleurs joueurs du monde
}
showingWorldwide = !showingWorldwide;
leaderboardContainer.add(currentLeaderboard, BorderLayout.CENTER);
leaderboardContainer.revalidate();
leaderboardContainer.repaint();
}
}

View File

@@ -1,11 +1,14 @@
package fr.monkhanny.dorfromantik.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
public class Database {
// Chargement des variables d'environnement
@@ -102,6 +105,29 @@ public class Database {
}
/**
* Récupère les meilleurs scores des joueurs (limite de 10 scores)
* @return une liste de résultats sous forme de tableau d'objets contenant le nom du joueur et son score
*/
public List<PlayerScore> getTopPlayers() throws SQLException {
List<PlayerScore> topPlayers = new ArrayList<>();
String query = "SELECT username, score FROM Scores ORDER BY score DESC LIMIT 10";
try (Statement stmt = this.database.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
String username = rs.getString("username");
if (username == null || username.trim().isEmpty()) {
username = "Joueur Anonyme"; // Remplacer par "Joueur Anonyme" si le pseudo est vide ou nul
}
int score = rs.getInt("score");
topPlayers.add(new PlayerScore(username, score));
}
}
return topPlayers;
}
public void close() {
try {

View File

@@ -0,0 +1,22 @@
package fr.monkhanny.dorfromantik.utils;
/**
* Représente un score d'un joueur avec son nom et son score.
*/
public class PlayerScore {
private String username;
private int score;
public PlayerScore(String username, int score) {
this.username = username;
this.score = score;
}
public String getUsername() {
return username;
}
public int getScore() {
return score;
}
}