Files
Projet-Dev/linea/Jeu.java
2026-03-28 17:19:34 +01:00

558 lines
20 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package linea;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
public class Jeu implements KeyListener, ActionListener {
//-------------------------------------------------------------------------
// PROPRIETES
//-------------------------------------------------------------------------
protected ZoneDessin ecran = new ZoneDessin();
protected Cercle demiCercleAvant;
protected Cercle demiCercleArriere;
protected Ligne ligne;
private int _niv;
protected Timer horloge;
protected JFrame fenetre;
protected double score = 0;
protected JLabel labScore;
protected JLabel labMeilleurScore;
protected JLabel labNiveau;
private DatabaseConnection db;
private int idCompte;
private int meilleurSansCompte = 0;
private int mortsSansCompte = 0;
private int tempsSansCompteSec = 0;
private int niveauMaxAtteintSansCompte = 1;
private long debutPartieMs = 0;
private boolean immortel = false;
private final boolean modeCampagne;
private void mettreAJourNiveauMaxSansCompte(int niveau) {
if (idCompte <= 0) {
niveauMaxAtteintSansCompte = Math.max(niveauMaxAtteintSansCompte, niveau);
}
}
private int meilleurActuel() {
return idCompte > 0 ? db.getMeilleurScoreParCompte(idCompte) : meilleurSansCompte;
}
private String statsActuelles() {
if (idCompte > 0) {
return db.getStatsParCompte(idCompte) + "\n\n" + db.getStatsCampagneParCompte(idCompte);
}
return "💀 Nombre de morts: " + mortsSansCompte
+ "\n⏱ Temps total: " + tempsSansCompteSec + "s"
+ "\n📈 Niveau max atteint: " + niveauMaxAtteintSansCompte
+ "\n🏆 Meilleur score: " + meilleurSansCompte;
}
private void enregistrerPartie(int scoreActuel, int tempsPartieSec) {
if (idCompte > 0) {
db.sauvegarderScore(scoreActuel, idCompte, 1, tempsPartieSec);
return;
}
meilleurSansCompte = Math.max(meilleurSansCompte, scoreActuel);
mortsSansCompte += 1;
tempsSansCompteSec += tempsPartieSec;
}
//-------------------------------------------------------------------------
// CONSTRUCTEUR
//-------------------------------------------------------------------------
public Jeu(DatabaseConnection db, int idCompte, int niveau) {
this(db, idCompte, niveau, false);
}
public Jeu(DatabaseConnection db, int idCompte, int niveau, boolean modeCampagne) {
this.db = db;
this.idCompte = idCompte;
this._niv = niveau;
this.modeCampagne = modeCampagne;
mettreAJourNiveauMaxSansCompte(_niv);
labScore = new JLabel();
labScore.setText("<html><h3>score : 0</h3></html>");
labMeilleurScore = new JLabel();
labNiveau = new JLabel();
JPanel panneauScores = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0));
panneauScores.setOpaque(false);
panneauScores.add(labScore);
panneauScores.add(labMeilleurScore);
panneauScores.add(labNiveau);
ecran.add(panneauScores, BorderLayout.NORTH);
rafraichirMeilleurScore();
rafraichirNiveau();
}
private void rafraichirMeilleurScore() {
labMeilleurScore.setText("<html><h3>meilleur : " + meilleurActuel() + "</h3></html>");
}
private void rafraichirNiveau() {
labNiveau.setText("<html><h3>niveau : " + _niv + "</h3></html>");
}
private void rafraichirTitreFenetre() {
if (fenetre == null) {
return;
}
String titre = modeCampagne ? "Linea Game [CAMPAGNE]" : "Linea Game";
fenetre.setTitle(titre + (immortel ? " [MODE IMMORTEL 🛡️]" : ""));
}
private String categorieNiveau(int niveau) {
if (niveau <= 2) return "Facile";
if (niveau <= 4) return "Moyen";
if (niveau <= 6) return "Difficile";
if (niveau <= 8) return "Tres Difficile";
if (niveau <= 10) return "Expert";
if (niveau <= 12) return "Cauchemar";
if (niveau <= 14) return "Chaos";
if (niveau <= 16) return "Infernal";
if (niveau <= 18) return "Apocalypse";
if (niveau <= 20) return "Extreme";
if (niveau <= 30) return "Infini";
if (niveau <= 50) return "Au-dela";
return "Cosmos";
}
private void appliquerThemeNiveau() {
String categorie = categorieNiveau(_niv);
Color fond;
Color couleurLigne;
Color couleurAvant;
Color couleurArriere;
Color couleurTexte;
switch (categorie) {
case "Facile":
fond = new Color(225, 245, 225);
couleurLigne = new Color(45, 120, 45);
couleurAvant = new Color(55, 185, 80);
couleurArriere = new Color(175, 70, 70);
couleurTexte = new Color(20, 50, 20);
break;
case "Moyen":
fond = new Color(215, 235, 250);
couleurLigne = new Color(40, 95, 150);
couleurAvant = new Color(50, 165, 120);
couleurArriere = new Color(185, 80, 85);
couleurTexte = new Color(20, 45, 80);
break;
case "Difficile":
fond = new Color(250, 235, 200);
couleurLigne = new Color(155, 95, 40);
couleurAvant = new Color(195, 145, 55);
couleurArriere = new Color(175, 70, 40);
couleurTexte = new Color(85, 55, 20);
break;
case "Tres Difficile":
fond = new Color(245, 215, 195);
couleurLigne = new Color(145, 70, 40);
couleurAvant = new Color(185, 110, 65);
couleurArriere = new Color(175, 55, 45);
couleurTexte = new Color(80, 35, 25);
break;
case "Expert":
fond = new Color(210, 190, 235);
couleurLigne = new Color(105, 55, 160);
couleurAvant = new Color(130, 85, 200);
couleurArriere = new Color(170, 60, 95);
couleurTexte = new Color(45, 20, 70);
break;
case "Cauchemar":
fond = new Color(175, 160, 210);
couleurLigne = new Color(85, 65, 150);
couleurAvant = new Color(120, 90, 190);
couleurArriere = new Color(155, 55, 110);
couleurTexte = new Color(245, 245, 245);
break;
case "Chaos":
fond = new Color(205, 120, 120);
couleurLigne = new Color(170, 40, 45);
couleurAvant = new Color(225, 115, 40);
couleurArriere = new Color(200, 30, 60);
couleurTexte = new Color(245, 245, 245);
break;
case "Infernal":
fond = new Color(165, 70, 55);
couleurLigne = new Color(190, 35, 25);
couleurAvant = new Color(235, 95, 25);
couleurArriere = new Color(210, 25, 20);
couleurTexte = new Color(245, 245, 245);
break;
case "Apocalypse":
fond = new Color(120, 40, 45);
couleurLigne = new Color(210, 30, 40);
couleurAvant = new Color(245, 95, 35);
couleurArriere = new Color(225, 20, 35);
couleurTexte = new Color(245, 245, 245);
break;
case "Extreme":
fond = new Color(70, 70, 70);
couleurLigne = new Color(225, 225, 225);
couleurAvant = new Color(255, 235, 70);
couleurArriere = new Color(240, 80, 80);
couleurTexte = new Color(245, 245, 245);
break;
case "Infini":
fond = new Color(35, 55, 85);
couleurLigne = new Color(95, 170, 255);
couleurAvant = new Color(70, 220, 255);
couleurArriere = new Color(180, 80, 255);
couleurTexte = new Color(245, 245, 245);
break;
case "Au-dela":
fond = new Color(20, 30, 70);
couleurLigne = new Color(120, 155, 255);
couleurAvant = new Color(80, 205, 255);
couleurArriere = new Color(205, 95, 255);
couleurTexte = new Color(245, 245, 245);
break;
default:
fond = new Color(10, 15, 45);
couleurLigne = new Color(140, 120, 255);
couleurAvant = new Color(120, 225, 255);
couleurArriere = new Color(235, 95, 255);
couleurTexte = new Color(245, 245, 245);
break;
}
ecran.setCouleurFond(fond);
ligne.setCouleurLigne(couleurLigne);
demiCercleAvant.setCouleur(couleurAvant);
demiCercleArriere.setCouleur(couleurArriere);
labScore.setForeground(couleurTexte);
labMeilleurScore.setForeground(couleurTexte);
labNiveau.setForeground(couleurTexte);
}
private boolean choisirNouveauCompte() {
List<String> pseudos = new ArrayList<>(db.getPseudos());
pseudos.add(0, "Sans compte");
String choix = (String) JOptionPane.showInputDialog(
null,
"Choisissez le compte pour la prochaine partie :",
"Changer de compte",
JOptionPane.QUESTION_MESSAGE,
null,
pseudos.toArray(String[]::new),
pseudos.get(0)
);
if (choix == null) {
return false;
}
if ("Sans compte".equals(choix)) {
idCompte = -1;
meilleurSansCompte = 0;
mortsSansCompte = 0;
tempsSansCompteSec = 0;
niveauMaxAtteintSansCompte = Math.max(1, _niv);
} else {
idCompte = db.getIdParPseudo(choix);
}
rafraichirMeilleurScore();
return true;
}
private int choisirNouveauNiveau() {
// Générer les niveaux dynamiquement jusqu'à 100
String[] niveaux = new String[100];
for (int i = 1; i <= 100; i++) {
niveaux[i - 1] = genererLabelNiveau(i);
}
JList<String> list = new JList<>(niveaux);
list.setSelectedIndex(_niv - 1);
list.setVisibleRowCount(15);
JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setPreferredSize(new java.awt.Dimension(350, 350));
int result = JOptionPane.showConfirmDialog(
null,
scrollPane,
"🎮 Sélection du Niveau - Linea",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE
);
if (result == JOptionPane.OK_OPTION) {
return list.getSelectedIndex() + 1;
}
return -1;
}
private String genererLabelNiveau(int niveau) {
if (niveau <= 2) {
return "⭐ Niveau " + niveau + " - Facile" + (niveau == 2 ? "+" : "");
} else if (niveau <= 4) {
return "⭐⭐ Niveau " + niveau + " - Moyen" + (niveau == 4 ? "+" : "");
} else if (niveau <= 6) {
return "⭐⭐⭐ Niveau " + niveau + " - Difficile" + (niveau == 6 ? "+" : "");
} else if (niveau <= 8) {
return "⭐⭐⭐⭐ Niveau " + niveau + " - Très Difficile" + (niveau == 8 ? "+" : "");
} else if (niveau <= 10) {
return "⭐⭐⭐⭐⭐ Niveau " + niveau + " - Expert" + (niveau == 10 ? "+" : "");
} else if (niveau <= 12) {
return "🔥 Niveau " + niveau + " - Cauchemar" + (niveau == 12 ? "+" : "");
} else if (niveau <= 14) {
return "🔥 Niveau " + niveau + " - Chaos" + (niveau == 14 ? "+" : "");
} else if (niveau <= 16) {
return "💀 Niveau " + niveau + " - Infernal" + (niveau == 16 ? "+" : "");
} else if (niveau <= 18) {
return "💀 Niveau " + niveau + " - Apocalypse" + (niveau == 18 ? "+" : "");
} else if (niveau <= 20) {
return "⚡ Niveau " + niveau + " - Extrême" + (niveau == 20 ? "+" : "");
} else if (niveau <= 30) {
return "⚡ Niveau " + niveau + " - Infini";
} else if (niveau <= 50) {
return "∞ Niveau " + niveau + " - Au-delà";
} else {
return "🌌 Niveau " + niveau + " - Cosmos";
}
}
private void choisirModeImmortel() {
int result = JOptionPane.showConfirmDialog(
null,
"Activer le mode IMMORTEL ? 🛡️\n(Vous ne pourrez pas mourir)",
"Mode Immortel",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE
);
immortel = (result == JOptionPane.YES_OPTION);
}
//-------------------------------------------------------------------------
// METHODES DE GESTION DU JEU
//-------------------------------------------------------------------------
/**
* Centralise la création et la configuration des objets du jeu.
* Évite de répéter ce code dans demarrer() et resetLevel().
*/
private void initialiserPartie() {
ecran.reinitialiser();
// Création des instances
demiCercleAvant = new Cercle(90, -180);
demiCercleArriere = new Cercle(90, 180);
ligne = new Ligne(_niv);
ecran.setNiveau(_niv);
if (immortel) {
demiCercleAvant.y = -300;
demiCercleArriere.y = 300;
}
appliquerThemeNiveau();
ecran.ajouterObjet(demiCercleArriere);
ecran.ajouterObjet(ligne);
ecran.ajouterObjet(demiCercleAvant);
rafraichirNiveau();
}
public void demarrer() {
// Demander si le mode immortel est activé
choisirModeImmortel();
// Passer le flag immortel à l'écran
ecran.setImmortel(immortel);
fenetre = new JFrame();
rafraichirTitreFenetre();
// Initialise les objets une première fois
initialiserPartie();
ecran.addKeyListener(this);
ecran.setFocusable(true);
fenetre.setContentPane(ecran);
fenetre.pack();
fenetre.setLocation(100, 100);
fenetre.setVisible(true);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Création et lancement du timer
horloge = new Timer(40, this);
horloge.start();
debutPartieMs = System.currentTimeMillis();
}
private void resetLevel() {
// Réinitialisation des variables de jeu
score = 0;
labScore.setText("<html><h3>score : 0</h3></html>");
// Passer le flag immortel à l'écran
ecran.setImmortel(immortel);
rafraichirTitreFenetre();
// Ré-initialisation des objets graphiques
initialiserPartie();
debutPartieMs = System.currentTimeMillis();
// Relance le timer existant et redonne le focus
if (horloge != null) horloge.restart();
ecran.requestFocusInWindow();
}
//-------------------------------------------------------------------------
// EVENEMENTS (Timer & Clavier)
//-------------------------------------------------------------------------
@Override
public void actionPerformed(ActionEvent e) {
ecran.traiterBoucleAnimation();
// Vérifier si un bonus a été récupéré
int bonus = ecran.getBonusRecupere();
if (bonus != 0) {
ecran.reinitialiserBonus();
int niveauActuel = _niv;
int nouveauNiveau = _niv + bonus;
// Limiter le niveau entre 1 et 100
if (nouveauNiveau < 1) {
nouveauNiveau = 1;
} else if (nouveauNiveau > 100) {
nouveauNiveau = 100;
}
if (modeCampagne && idCompte > 0 && bonus > 0) {
db.debloquerNiveauCampagne(idCompte, niveauActuel);
}
_niv = nouveauNiveau;
mettreAJourNiveauMaxSansCompte(_niv);
resetLevel();
return;
}
if (ecran.aCollision() && !immortel) {
horloge.stop();
int scoreActuel = (int) score;
int tempsPartieSec = (int) ((System.currentTimeMillis() - debutPartieMs) / 1000L);
enregistrerPartie(scoreActuel, tempsPartieSec);
rafraichirMeilleurScore();
while (true) {
Object[] options = modeCampagne
? new Object[]{"▶️ Relancer", "📊 Statistiques", "❌ Quitter"}
: new Object[]{"▶️ Relancer", "👤 Compte", "📈 Niveau", "📊 Statistiques", "❌ Quitter"};
String message = "🏁 GAME OVER\n\n"
+ "Score: " + scoreActuel + "\n"
+ "Meilleur: " + meilleurActuel() + "\n"
+ "Durée: " + tempsPartieSec + "s";
int choix = JOptionPane.showOptionDialog(null,
message,
"🏁 Fin de Partie",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null, options, options[0]);
if (choix == 0) {
int modeRelance = JOptionPane.showConfirmDialog(
null,
"Relancer en mode immortel ?",
"Relancer",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE
);
if (modeRelance == JOptionPane.CANCEL_OPTION || modeRelance == JOptionPane.CLOSED_OPTION) {
continue;
}
immortel = (modeRelance == JOptionPane.YES_OPTION);
ecran.setImmortel(immortel);
resetLevel();
break;
}
if (modeCampagne) {
if (choix == 1) {
JOptionPane.showMessageDialog(null, statsActuelles(), "📊 Statistiques", JOptionPane.INFORMATION_MESSAGE);
continue;
}
System.exit(0);
}
if (choix == 1) {
if (choisirNouveauCompte()) {
resetLevel();
break;
}
continue;
}
if (choix == 2) {
int nouveauNiveau = choisirNouveauNiveau();
if (nouveauNiveau > 0) {
_niv = nouveauNiveau;
mettreAJourNiveauMaxSansCompte(_niv);
resetLevel();
break;
}
continue;
}
if (choix == 3) {
JOptionPane.showMessageDialog(null, statsActuelles(), "📊 Statistiques", JOptionPane.INFORMATION_MESSAGE);
continue;
}
System.exit(0);
}
return;
}
// Calcul du score basé sur le temps écoulé
score += (0.05 + (0.05 * horloge.getDelay() / 100.0));
labScore.setText("<html><h3>score : " + (int)score + "</h3></html>");
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
demiCercleAvant.Monter();
demiCercleArriere.Monter();
}
}
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
demiCercleAvant.ArreterMonter();
demiCercleArriere.ArreterMonter();
}
}
@Override
public void keyTyped(KeyEvent e) {}
}