Compare commits
30 Commits
65a99a3e3e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ed39dd92a | |||
|
|
5660a6c5c6 | ||
|
|
607ee1fff4 | ||
|
|
f295a34ca5 | ||
|
|
6de8ca830e | ||
|
|
a01e27ad2c | ||
| 16787a4113 | |||
|
|
d69b806001 | ||
| 2c93a102f2 | |||
|
|
ba78c22e91 | ||
| e1e0ef5054 | |||
| eb74186d05 | |||
|
|
732d29dad6 | ||
|
|
0b82113441 | ||
| 0a4825d9ef | |||
|
|
eab0280f5e | ||
|
|
f8c74c4306 | ||
|
|
b37f6cb881 | ||
|
|
9ec6f0ebfa | ||
| b4ff63e92c | |||
|
|
dbafa23b4d | ||
|
|
7639df7abd | ||
|
|
8126007805 | ||
|
|
3dd0408323 | ||
| 2017bd1907 | |||
|
|
4e5ab18694 | ||
|
|
2b52a88132 | ||
|
|
5d1c525890 | ||
|
|
c15787681f | ||
|
|
5a58534a40 |
Binary file not shown.
@@ -2,78 +2,36 @@ package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.util.List;
|
||||
|
||||
public class Bonus extends ObjetGraphique {
|
||||
public class Bonus extends ObjetCollectible {
|
||||
|
||||
protected double taille = 10;
|
||||
protected boolean actif = false;
|
||||
protected int compteurFrames = 0;
|
||||
public Bonus(Ligne l, List<Joueur> joueurs, Jeu j) {
|
||||
super(l, joueurs, j);
|
||||
this.taille = 10;
|
||||
this.couleur = Color.GREEN;
|
||||
}
|
||||
|
||||
protected Ligne maLigne;
|
||||
protected Cercle monCercle;
|
||||
protected Jeu monJeu;
|
||||
@Override protected int getSeuilActivation() { return 220; }
|
||||
|
||||
public Bonus(Ligne l, Cercle c, Jeu j) {
|
||||
this.maLigne = l;
|
||||
this.monCercle = c;
|
||||
this.monJeu = j;
|
||||
this.couleur = Color.RED;
|
||||
@Override protected Color getCouleurCapture() { return Color.BLUE; } // couleur après avoir été ramasssé
|
||||
|
||||
@Override
|
||||
protected double calculerY(double hauteurLigne) {
|
||||
if (Math.random() > 0.5) return hauteurLigne - 10 - (Math.random() * 50); // position du bonus
|
||||
else return hauteurLigne + 10 + (Math.random() * 50);
|
||||
}
|
||||
|
||||
@Override
|
||||
void Afficher(Graphics g) {
|
||||
if (actif) {
|
||||
g.setColor(this.couleur);
|
||||
protected void appliquerEffet(Joueur joueur) {
|
||||
if (!monJeu.cheatMode) joueur.ajouterVie();
|
||||
} // En cheat mode, le bonus ne sert à rien (on a déjà l'invincibilité)
|
||||
|
||||
|
||||
@Override
|
||||
protected void dessiner(Graphics g) {
|
||||
g.fillRect((int)Math.round(x), (int)Math.round(y), (int)taille, (int)taille);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void Animer() {
|
||||
// On compte le temps uniquement si le bonus n'est pas déjà sur l'écran
|
||||
if (!actif) {
|
||||
compteurFrames++;
|
||||
}
|
||||
|
||||
// TEMPS RÉDUIT POUR TESTER : 50 frames = 2 secondes (au lieu de 375)
|
||||
if (compteurFrames >= 100 && !actif) {
|
||||
actif = true;
|
||||
x = 800;
|
||||
|
||||
double hauteurLigne = 300;
|
||||
if (maLigne.dernierSegment != null) {
|
||||
hauteurLigne = maLigne.dernierSegment.y;
|
||||
}
|
||||
|
||||
double decalage = (Math.random() * 80) - 40;
|
||||
y = hauteurLigne + decalage;
|
||||
|
||||
// Ce message s'affichera dans ta console Eclipse/IntelliJ/VSCode
|
||||
System.out.println("DEBUG : Le bonus apparait à Y = " + y);
|
||||
|
||||
compteurFrames = 0;
|
||||
}
|
||||
|
||||
if (actif) {
|
||||
x -= 10;
|
||||
|
||||
// --- VÉRIFICATION DE LA COLLISION ---
|
||||
double centreX = x + (taille / 2.0);
|
||||
double centreY = y + (taille / 2.0);
|
||||
double dx = centreX - monCercle.x;
|
||||
double dy = centreY - monCercle.y;
|
||||
double distance = Math.sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
if (distance < monCercle.getRayon()) {
|
||||
System.out.println("DEBUG : Bonus attrapé ! +1 Vie");
|
||||
monJeu.vies += 1;
|
||||
actif = false;
|
||||
}
|
||||
|
||||
if (x + taille < 0) {
|
||||
System.out.println("DEBUG : Bonus raté, il est sorti de l'écran");
|
||||
actif = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/BonusTaille.java
Normal file
35
src/BonusTaille.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.util.List;
|
||||
|
||||
public class BonusTaille extends ObjetCollectible {
|
||||
|
||||
public BonusTaille(Ligne l, List<Joueur> joueurs, Jeu j) {
|
||||
super(l, joueurs, j);
|
||||
this.taille = 12;
|
||||
this.couleur = Color.CYAN;
|
||||
this.compteurFrames = 200; // démarre déjà à 200 pour apparaître plus tôt
|
||||
}
|
||||
|
||||
@Override protected int getSeuilActivation() { return 320; }
|
||||
|
||||
@Override protected Color getCouleurCapture() { return new Color(255, 255, 255, 100); }
|
||||
|
||||
@Override
|
||||
protected double calculerY(double hauteurLigne) {
|
||||
if (Math.random() > 0.5) return hauteurLigne - 8 - (Math.random() * 45); // position du bonus
|
||||
else return hauteurLigne + 8 + (Math.random() * 45);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appliquerEffet(Joueur joueur) {
|
||||
joueur.activerBonusTaille();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dessiner(Graphics g) {
|
||||
g.fillOval((int)Math.round(x), (int)Math.round(y), (int)taille, (int)taille);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Arc2D;
|
||||
|
||||
public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cercle
|
||||
// Gère l'affichage et le déplacement du demi-cercle
|
||||
public class Cercle extends ObjetGraphique {
|
||||
|
||||
protected double rayon = 50;
|
||||
protected double depY = 0;
|
||||
@@ -20,7 +21,8 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc
|
||||
|
||||
// pas = "delta t", permet de régler la jouabilité
|
||||
protected double pas = 0.2;
|
||||
protected double impulsion = 2;
|
||||
protected double impulsion = 6;
|
||||
protected double gravite = 1;
|
||||
|
||||
public static int xCercle = 400;
|
||||
|
||||
@@ -70,6 +72,9 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc
|
||||
|
||||
@Override
|
||||
void Animer() {
|
||||
// gravite
|
||||
vitesse += gravite * pas;
|
||||
|
||||
// acceleration vers le haut
|
||||
if (montee == true) {
|
||||
vitesse -= impulsion * pas;
|
||||
@@ -91,17 +96,18 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc
|
||||
y += vitesse;
|
||||
}
|
||||
|
||||
// Recadre le cercle dans la ligne si il le dépasse
|
||||
public void ResterDansLigne(Ligne li) {
|
||||
double collisionHautPos = y + rayon;
|
||||
double collisionBasPos = y - rayon;
|
||||
double yLigne = li.GetHauteurPointCercle();
|
||||
|
||||
if (yLigne < collisionBasPos) {
|
||||
if (yLigne < collisionBasPos) { // Dépassement par le bas
|
||||
y = yLigne + rayon;
|
||||
if (vitesse > 0)
|
||||
vitesse = 0;
|
||||
}
|
||||
if (yLigne > collisionHautPos) {
|
||||
if (yLigne > collisionHautPos) {// Dépassement par le haut
|
||||
y = yLigne - rayon;
|
||||
if (vitesse < 0)
|
||||
vitesse = 0;
|
||||
|
||||
39
src/GestionnaireFinDePartie.java
Normal file
39
src/GestionnaireFinDePartie.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package linea;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class GestionnaireFinDePartie {
|
||||
|
||||
private boolean estGameOver = false;
|
||||
private JLabel labGameOver;
|
||||
private GestionnaireScore gestionnaireBDD;
|
||||
private GestionnaireHistorique gestionnaireHistorique;
|
||||
|
||||
public GestionnaireFinDePartie(JLabel labGameOver, GestionnaireScore gestionnaireBDD, GestionnaireHistorique gestionnaireHistorique) {
|
||||
this.labGameOver = labGameOver;
|
||||
this.gestionnaireBDD = gestionnaireBDD;
|
||||
this.gestionnaireHistorique = gestionnaireHistorique;
|
||||
}
|
||||
|
||||
public void declencherGameOver(ZoneDessin ecran, String pseudo, int score) {
|
||||
estGameOver = true;
|
||||
ecran.arreter(); // on fige tout, plus d'animation
|
||||
labGameOver.setVisible(true);
|
||||
|
||||
// on enregistre dans le classement seulement si y'a un pseudo
|
||||
if (pseudo != null && !pseudo.isEmpty()) {
|
||||
gestionnaireBDD.sauvegarderScore(pseudo, score);
|
||||
}
|
||||
// score == durée en secondes (1 pt par seconde, voir Jeu.actionPerformed)
|
||||
gestionnaireHistorique.sauvegarderPartie(pseudo, score, score);
|
||||
}
|
||||
|
||||
public boolean estGameOver() {
|
||||
return estGameOver;
|
||||
}
|
||||
|
||||
public void reinitialiser() {
|
||||
estGameOver = false;
|
||||
labGameOver.setVisible(false);
|
||||
}
|
||||
}
|
||||
72
src/GestionnaireHistorique.java
Normal file
72
src/GestionnaireHistorique.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package linea;
|
||||
|
||||
import java.sql.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
public class GestionnaireHistorique {
|
||||
|
||||
private static final String URL = "jdbc:sqlite:linea_bdd.db";
|
||||
|
||||
public GestionnaireHistorique() {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// enregistre la partie peu importe si le joueur a mis un pseudo ou pas
|
||||
public void sauvegarderPartie(String nom, int points, int duree) {
|
||||
String pseudoFinal = (nom == null || nom.trim().isEmpty()) ? "Anonyme" : nom.trim();
|
||||
String dateActuelle = new SimpleDateFormat("dd/MM/yyyy HH:mm").format(new Date());
|
||||
String sql = "INSERT INTO historique(nom, points, date_partie, duree) VALUES(?, ?, ?, ?)";
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(URL);
|
||||
PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
|
||||
pstmt.setString(1, pseudoFinal);
|
||||
pstmt.setInt(2, points);
|
||||
pstmt.setString(3, dateActuelle);
|
||||
pstmt.setInt(4, duree);
|
||||
pstmt.executeUpdate();
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.err.println("impossible de sauvegarder l historique");
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultTableModel getModeleTableau() {
|
||||
// colonnes affichées dans la popup historique du menu
|
||||
String[] nomsColonnes = { "Partie N°", "Date", "Pseudo", "Score", "Durée (s)" };
|
||||
DefaultTableModel modele = new DefaultTableModel(nomsColonnes, 0);
|
||||
// les plus récentes en haut
|
||||
String sql = "SELECT id, date_partie, nom, points, duree FROM historique ORDER BY id DESC";
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(URL);
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(sql)) {
|
||||
|
||||
while (rs.next()) {
|
||||
String dateRecup = rs.getString("date_partie");
|
||||
if (dateRecup == null)
|
||||
dateRecup = "Inconnue";
|
||||
|
||||
Object[] ligne = {
|
||||
rs.getInt("id"),
|
||||
dateRecup,
|
||||
rs.getString("nom"),
|
||||
rs.getInt("points"),
|
||||
rs.getInt("duree")
|
||||
};
|
||||
modele.addRow(ligne);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.err.println("erreur lecture historique");
|
||||
}
|
||||
|
||||
return modele;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,66 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GestionnaireNiveau {
|
||||
|
||||
public static final int FRAMES_PAR_NIVEAU = 25 * 10; // 10s a 25 FPS (timer 40ms)
|
||||
public static final int FRAMES_PAR_NIVEAU = 25 * 10; // 10 secondes
|
||||
|
||||
private final List<Niveau> niveaux = new ArrayList<>();
|
||||
private int indexNiveau = 0;
|
||||
private int framesDepuisDebut = 0;
|
||||
private int framesDansNiveau = 0;
|
||||
|
||||
// Duree du fade en frames
|
||||
private static final int DUREE_FADE = 75; // 3 secondes
|
||||
private static final int DUREE_FADE = 25 * 3; // 3 secondes
|
||||
|
||||
private static final String URL_BDD = "jdbc:sqlite:linea_bdd.db";
|
||||
|
||||
public GestionnaireNiveau() {
|
||||
|
||||
// Niveau 1 : lisse, cercle large
|
||||
niveaux.add(new Niveau(1,
|
||||
new Color(0, 73, 220),
|
||||
8, 1 / 80.0, 80, 100, 500));
|
||||
|
||||
// Niveau 2
|
||||
niveaux.add(new Niveau(2,
|
||||
new Color(75, 0, 180),
|
||||
10, 1 / 60.0, 60, 100, 500));
|
||||
|
||||
// Niveau 3
|
||||
niveaux.add(new Niveau(3,
|
||||
new Color(83, 30, 39),
|
||||
12, 1 / 40.0, 50, 100, 500));
|
||||
|
||||
// Niveau 4
|
||||
niveaux.add(new Niveau(4,
|
||||
new Color(20, 100, 40),
|
||||
14, 1 / 30.0, 40, 100, 500));
|
||||
|
||||
// Niveau 5 : chaos, cercle petit
|
||||
niveaux.add(new Niveau(5,
|
||||
new Color(30, 30, 30),
|
||||
16, 1 / 20.0, 30, 100, 500));
|
||||
try {
|
||||
//chargement driver
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("[BDD] Impossible de charger le driver SQLite.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
chargerNiveaux();
|
||||
}
|
||||
|
||||
private void chargerNiveaux() {
|
||||
String sql = "SELECT * FROM niveaux ORDER BY numero ASC";
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(URL_BDD);
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(sql)) {
|
||||
|
||||
while (rs.next()) {
|
||||
int numero = rs.getInt("numero");
|
||||
int r = rs.getInt("couleur_r");
|
||||
int g = rs.getInt("couleur_g");
|
||||
int b = rs.getInt("couleur_b");
|
||||
double vitesse = rs.getDouble("vitesse_scroll");
|
||||
double freq = rs.getDouble("noise_frequence");
|
||||
double rayon = rs.getDouble("rayon_cercle");
|
||||
double haut = rs.getDouble("limite_haut");
|
||||
double bas = rs.getDouble("limite_bas");
|
||||
|
||||
niveaux.add(new Niveau(numero, new Color(r, g, b), vitesse, freq, rayon, haut, bas));
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.err.println("[BDD] Erreur lors du chargement des niveaux.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (niveaux.isEmpty()) {
|
||||
niveaux.add(new Niveau(1, new Color(112, 158, 251), 8, 1.0/80.0, 70, 100, 500));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean niveauVientDeChanger = false;
|
||||
|
||||
public void mettreAJour() {
|
||||
framesDepuisDebut++;
|
||||
@@ -51,9 +69,19 @@ public class GestionnaireNiveau {
|
||||
if (framesDansNiveau >= FRAMES_PAR_NIVEAU && indexNiveau < niveaux.size() - 1) {
|
||||
indexNiveau++;
|
||||
framesDansNiveau = 0;
|
||||
niveauVientDeChanger = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean aChangeDeNiveau() {
|
||||
if (niveauVientDeChanger) {
|
||||
niveauVientDeChanger = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//transition smooth entre les niveau
|
||||
|
||||
public Niveau getNiveauActuel() {
|
||||
return niveaux.get(indexNiveau);
|
||||
}
|
||||
|
||||
@@ -4,47 +4,20 @@ import java.sql.*;
|
||||
|
||||
public class GestionnaireScore {
|
||||
|
||||
private static final String URL = "jdbc:sqlite:linea_scores.db";
|
||||
private static final String URL = "jdbc:sqlite:linea_bdd.db";
|
||||
|
||||
public GestionnaireScore() {
|
||||
// 1) Charger explicitement le driver SQLite JDBC
|
||||
try {
|
||||
//chargement driver SQLite
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
System.out.println("[BDD] Driver SQLite JDBC chargé correctement (org.sqlite.JDBC).");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("[BDD] ERREUR : impossible de charger le driver SQLite JDBC (org.sqlite.JDBC).");
|
||||
System.err.println("Vérifie que le fichier sqlite-jdbc-xxx.jar est bien présent dans le classpath.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 2) Créer / vérifier la table au démarrage
|
||||
try (Connection conn = DriverManager.getConnection(URL)) {
|
||||
if (conn == null) {
|
||||
System.err.println("[BDD] ERREUR : connexion JDBC nulle lors de l'initialisation.");
|
||||
return;
|
||||
}
|
||||
|
||||
String sql = "CREATE TABLE IF NOT EXISTS scores (" +
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
"nom TEXT NOT NULL," +
|
||||
"points INTEGER NOT NULL" +
|
||||
");";
|
||||
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute(sql);
|
||||
}
|
||||
|
||||
System.out.println("[BDD] Table 'scores' vérifiée/créée avec succès.");
|
||||
} catch (SQLException e) {
|
||||
System.err.println("[BDD] ERREUR SQL lors de la création ou vérification de la table 'scores'.");
|
||||
System.err.println("Message SQL : " + e.getMessage());
|
||||
System.err.println("[BDD] Impossible de charger le driver SQLite.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sauvegarderScore(String nom, int points) {
|
||||
if (nom == null || nom.trim().isEmpty()) {
|
||||
System.err.println("[BDD] Tentative d'enregistrer un score avec un nom vide. Opération annulée.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,15 +26,13 @@ public class GestionnaireScore {
|
||||
try (Connection conn = DriverManager.getConnection(URL);
|
||||
PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||
|
||||
//contre injection SQL
|
||||
pstmt.setString(1, nom.trim());
|
||||
pstmt.setInt(2, points);
|
||||
int lignes = pstmt.executeUpdate();
|
||||
pstmt.executeUpdate();
|
||||
|
||||
System.out.println("[BDD] Score enregistré pour '" + nom + "' (" + points +
|
||||
" points). Lignes affectées : " + lignes);
|
||||
} catch (SQLException e) {
|
||||
System.err.println("[BDD] ERREUR SQL lors de l'enregistrement du score.");
|
||||
System.err.println("Message SQL : " + e.getMessage());
|
||||
System.err.println("[BDD] Erreur lors de l'enregistrement du score.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -89,13 +60,9 @@ public class GestionnaireScore {
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.err.println("[BDD] ERREUR SQL lors de la lecture des scores.");
|
||||
System.err.println("Message SQL : " + e.getMessage());
|
||||
System.err.println("[BDD] Erreur lors de la lecture des scores.");
|
||||
e.printStackTrace();
|
||||
|
||||
return "Erreur lors de la lecture des scores.\n" +
|
||||
"Détail : " + e.getMessage() + "\n" +
|
||||
"Consulte la console pour la pile complète (stack trace).";
|
||||
return "Erreur lors de la lecture des scores.";
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
182
src/Jeu.java
182
src/Jeu.java
@@ -8,6 +8,8 @@ import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
@@ -18,36 +20,39 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
|
||||
protected ZoneDessin ecran = new ZoneDessin();
|
||||
|
||||
protected Cercle demiCercleAvant = new Cercle(90, -180); // celui qui est sur la ligne
|
||||
protected Cercle demiCercleArriere = new Cercle(90, 180); // celui qui est derrière la ligne
|
||||
|
||||
protected GestionnaireNiveau gestionnaireNiveau = new GestionnaireNiveau();
|
||||
protected Ligne lili = new Ligne(new NoiseGenerator(0), gestionnaireNiveau);
|
||||
|
||||
protected List<Joueur> joueurs = new ArrayList<>();
|
||||
protected boolean deuxJoueurs = false;
|
||||
|
||||
protected Timer horloge;
|
||||
|
||||
protected double score = 1;
|
||||
protected JLabel labScore;
|
||||
protected int vies = 3;
|
||||
|
||||
protected GestionnaireScore gestionnaireBDD = new GestionnaireScore();
|
||||
|
||||
// pour gestionnaire historique
|
||||
protected GestionnaireHistorique gestionnaireHistorique = new GestionnaireHistorique();
|
||||
|
||||
protected GestionnaireFinDePartie gestionnaireFinDePartie;
|
||||
|
||||
protected int compteurFrames = 0;
|
||||
protected boolean enCollision = false;
|
||||
protected boolean estGameOver = false;
|
||||
protected JLabel labGameOver;
|
||||
protected int compteurInvincible = 0;
|
||||
|
||||
protected String pseudo = "";
|
||||
protected JFrame fenetre;
|
||||
protected MenuPrincipal menu;
|
||||
|
||||
public boolean cheatMode = false;
|
||||
|
||||
public Jeu() {
|
||||
labScore = new JLabel();
|
||||
labScore.setForeground(Color.WHITE);
|
||||
labScore.setText("<html><h3>" + (int) score + "</h3></html>");
|
||||
labScore.setBounds(20, 0, 200, 50);
|
||||
labScore.setBounds(20, 0, 600, 50);
|
||||
ecran.add(labScore);
|
||||
|
||||
labGameOver = new JLabel("GAME OVER", SwingConstants.CENTER);
|
||||
@@ -57,35 +62,37 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
labGameOver.setVisible(false);
|
||||
ecran.add(labGameOver);
|
||||
|
||||
gestionnaireFinDePartie = new GestionnaireFinDePartie(labGameOver, gestionnaireBDD, gestionnaireHistorique);
|
||||
|
||||
ecran.addMouseListener(this);
|
||||
ecran.traiterBoucleAnimation();
|
||||
}
|
||||
|
||||
private Joueur creerJoueur1() {
|
||||
return new Joueur(
|
||||
new Color(0.0f, 0.5f, 0.0f), new Color(0.8f, 0.0f, 0.0f),
|
||||
KeyEvent.VK_UP, KeyEvent.VK_DOWN
|
||||
);
|
||||
}
|
||||
|
||||
private Joueur creerJoueur2() {
|
||||
return new Joueur(
|
||||
new Color(0.0f, 0.3f, 0.8f), new Color(0.6f, 0.0f, 0.6f),
|
||||
KeyEvent.VK_Z, KeyEvent.VK_S
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
int keyCode = e.getKeyCode();
|
||||
|
||||
if (keyCode == 38) { // flèche haut
|
||||
demiCercleAvant.Monter();
|
||||
demiCercleArriere.Monter();
|
||||
}
|
||||
if (keyCode == 40) { // flèche bas
|
||||
demiCercleAvant.Descendre();
|
||||
demiCercleArriere.Descendre();
|
||||
for (Joueur joueur : joueurs) {
|
||||
joueur.appliquerTouche(e.getKeyCode(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
int keyCode = e.getKeyCode();
|
||||
|
||||
if (keyCode == 38) { // flèche haut
|
||||
demiCercleAvant.ArreterMonter();
|
||||
demiCercleArriere.ArreterMonter();
|
||||
}
|
||||
if (keyCode == 40) { // flèche bas
|
||||
demiCercleAvant.ArreterDescendre();
|
||||
demiCercleArriere.ArreterDescendre();
|
||||
for (Joueur joueur : joueurs) {
|
||||
joueur.appliquerTouche(e.getKeyCode(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,18 +113,29 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
public void lancerPartie(String pseudoSaisi) {
|
||||
public void lancerPartie(String pseudoSaisi, boolean modeDeuxJoueurs) {
|
||||
pseudo = pseudoSaisi;
|
||||
deuxJoueurs = modeDeuxJoueurs;
|
||||
|
||||
// C'est cette ligne qui donne vie au bonus !
|
||||
ecran.ajouterObjet(new Bonus(lili, demiCercleAvant, this));
|
||||
joueurs.clear();
|
||||
joueurs.add(creerJoueur1());
|
||||
if (deuxJoueurs) {
|
||||
joueurs.add(creerJoueur2());
|
||||
}
|
||||
|
||||
for (Joueur joueur : joueurs) {
|
||||
ecran.ajouterObjet(joueur.demiCercleArriere);
|
||||
}
|
||||
|
||||
// A FAIRE : placer dans l'écran tous les objets graphiques nécessaires
|
||||
ecran.ajouterObjet(demiCercleArriere);
|
||||
ecran.ajouterObjet(lili);
|
||||
ecran.ajouterObjet(demiCercleAvant);
|
||||
demiCercleArriere.setCouleur(new Color(0.0f, 0.4f, 0.0f));
|
||||
demiCercleAvant.setCouleur(new Color(0.0f, 0.5f, 0.0f));
|
||||
|
||||
for (Joueur joueur : joueurs) {
|
||||
ecran.ajouterObjet(joueur.demiCercleAvant);
|
||||
}
|
||||
|
||||
ecran.ajouterObjet(new Bonus(lili, joueurs, this));
|
||||
ecran.ajouterObjet(new Malus(lili, joueurs, this));
|
||||
ecran.ajouterObjet(new BonusTaille(lili, joueurs, this));
|
||||
|
||||
ecran.addKeyListener(this);
|
||||
ecran.setFocusable(true);
|
||||
@@ -129,74 +147,81 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
|
||||
score = 1;
|
||||
compteurFrames = 0;
|
||||
vies = 3;
|
||||
enCollision = false;
|
||||
estGameOver = false;
|
||||
compteurInvincible = 0;
|
||||
gestionnaireNiveau.reinitialiser();
|
||||
labGameOver.setVisible(false);
|
||||
gestionnaireFinDePartie.reinitialiser();
|
||||
|
||||
double posY = deuxJoueurs ? 250 : 200;
|
||||
for (int i = 0; i < joueurs.size(); i++) {
|
||||
joueurs.get(i).reinitialiser(posY + i * 100);
|
||||
}
|
||||
|
||||
ecran.demarrer();
|
||||
|
||||
if (horloge == null) {
|
||||
// 40ms par frame, environ 25fps
|
||||
horloge = new Timer(40, this);
|
||||
}
|
||||
horloge.start();
|
||||
|
||||
// A FAIRE : donner la couleur des 2 demi-cercles
|
||||
// demiCercleArriere.setCouleur(new Color(0.8f, 0.0f, 0.0f));
|
||||
demiCercleArriere.setCouleur(new Color(0.8f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (estGameOver == true) {
|
||||
return;
|
||||
}
|
||||
if (estGameOver) return;
|
||||
|
||||
gestionnaireNiveau.mettreAJour();
|
||||
if (gestionnaireNiveau.aChangeDeNiveau()) {
|
||||
for (Joueur joueur : joueurs) {
|
||||
joueur.resetInvincibilite();
|
||||
}
|
||||
}
|
||||
ecran.setCouleurFond(gestionnaireNiveau.getCouleurFondInterpolee());
|
||||
|
||||
double rayon = gestionnaireNiveau.getRayonCercle();
|
||||
demiCercleAvant.setRayon(rayon);
|
||||
demiCercleArriere.setRayon(rayon);
|
||||
double rayonBase = gestionnaireNiveau.getRayonCercle();
|
||||
|
||||
for (Joueur joueur : joueurs) {
|
||||
joueur.mettreAJourRayon(rayonBase);
|
||||
joueur.mettreAJourInvincibilite();
|
||||
if (!cheatMode) joueur.verifierCollisionLigne(lili); // si cheat mode activé : plus de perte de vie
|
||||
joueur.resterDansLigne(lili);
|
||||
}
|
||||
|
||||
ecran.traiterBoucleAnimation();
|
||||
|
||||
compteurFrames = compteurFrames + 1;
|
||||
compteurFrames++;
|
||||
// 25 frames à 40ms = 1 seconde, donc score ≈ durée en secondes
|
||||
if (compteurFrames >= 25) {
|
||||
score = score + 1;
|
||||
score++;
|
||||
compteurFrames = 0;
|
||||
}
|
||||
|
||||
if (compteurInvincible < 75) {
|
||||
compteurInvincible = compteurInvincible + 1;
|
||||
} else {
|
||||
if (demiCercleArriere.VerifierCollision(lili)) {
|
||||
if (enCollision == false) {
|
||||
vies = vies - 1; // La nouvelle logique : on perd 1 vie
|
||||
enCollision = true;
|
||||
compteurInvincible = 0;
|
||||
}
|
||||
} else {
|
||||
enCollision = false;
|
||||
boolean tousMotrs = true;
|
||||
for (Joueur joueur : joueurs) {
|
||||
if (!joueur.estMort) {
|
||||
tousMotrs = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vies <= 0) {
|
||||
vies = 0;
|
||||
if (tousMotrs) {
|
||||
// tous les joueurs sont morts, on déclenche le game over
|
||||
estGameOver = true;
|
||||
ecran.arreter();
|
||||
labGameOver.setVisible(true);
|
||||
|
||||
if (pseudo != null && !pseudo.isEmpty()) {
|
||||
gestionnaireBDD.sauvegarderScore(pseudo, (int) score);
|
||||
}
|
||||
gestionnaireFinDePartie.declencherGameOver(ecran, pseudo, (int) score);
|
||||
}
|
||||
|
||||
labScore.setText("<html><h3>Score : " + (int) score + " | Vies : " + vies + " | Niv. " + gestionnaireNiveau.getNumeroNiveau() + "</h3></html>");
|
||||
mettreAJourLabel();
|
||||
}
|
||||
|
||||
demiCercleArriere.ResterDansLigne(lili);
|
||||
demiCercleAvant.ResterDansLigne(lili);
|
||||
private void mettreAJourLabel() {
|
||||
StringBuilder sb = new StringBuilder("<html><h3>Score : " + (int) score + " | ");
|
||||
if (deuxJoueurs) {
|
||||
sb.append("J1 : ").append(joueurs.get(0).vies).append(" | ");
|
||||
sb.append("J2 : ").append(joueurs.get(1).vies).append(" | ");
|
||||
} else {
|
||||
sb.append("Vies : ").append(joueurs.get(0).vies).append(" | ");
|
||||
}
|
||||
sb.append("Niv. ").append(gestionnaireNiveau.getNumeroNiveau()).append("</h3></html>");
|
||||
labScore.setText(sb.toString());
|
||||
}
|
||||
|
||||
private void retourMenu() {
|
||||
@@ -204,13 +229,10 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
horloge.stop();
|
||||
}
|
||||
|
||||
// on repart de zéro : nouvelle ligne, nouveaux joueurs
|
||||
gestionnaireNiveau.reinitialiser();
|
||||
lili = new Ligne(new NoiseGenerator(0), gestionnaireNiveau);
|
||||
|
||||
demiCercleAvant.y = 200;
|
||||
demiCercleAvant.vitesse = -1.0;
|
||||
demiCercleArriere.y = 200;
|
||||
demiCercleArriere.vitesse = -1.0;
|
||||
joueurs.clear();
|
||||
|
||||
ecran.viderObjets();
|
||||
menu.afficher(pseudo);
|
||||
@@ -222,7 +244,8 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (estGameOver == true) {
|
||||
// un clic n'importe où à la fin de la partie pour revenir au menu
|
||||
if (estGameOver) {
|
||||
retourMenu();
|
||||
}
|
||||
}
|
||||
@@ -238,7 +261,12 @@ public class Jeu implements KeyListener, ActionListener, MouseListener {
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
|
||||
public GestionnaireScore getGestionnaireBDD() {
|
||||
return gestionnaireBDD;
|
||||
}
|
||||
|
||||
public GestionnaireHistorique getGestionnaireHistorique() {
|
||||
return gestionnaireHistorique;
|
||||
}
|
||||
}
|
||||
190
src/Joueur.java
Normal file
190
src/Joueur.java
Normal file
@@ -0,0 +1,190 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
// Gère le fonctionnement du joueur (vie, collision, déplacement)
|
||||
public class Joueur {
|
||||
|
||||
protected Cercle demiCercleAvant;
|
||||
protected Cercle demiCercleArriere;
|
||||
|
||||
protected int vies = 3;
|
||||
protected boolean enCollision = false;
|
||||
protected int compteurInvincible = 0;
|
||||
protected boolean invincibiliteRouge = false;
|
||||
|
||||
protected boolean bonusTailleActif = false;
|
||||
protected int compteurBonusTaille = 0;
|
||||
|
||||
protected boolean estMort = false;
|
||||
|
||||
protected Color couleurAvant;
|
||||
protected Color couleurArriere;
|
||||
|
||||
protected int toucheHaut;
|
||||
protected int toucheBas;
|
||||
|
||||
public Joueur(Color couleurAvant, Color couleurArriere, int toucheHaut, int toucheBas) {
|
||||
this.demiCercleAvant = new Cercle(90, -180);
|
||||
this.demiCercleArriere = new Cercle(90, 180);
|
||||
this.couleurAvant = couleurAvant;
|
||||
this.couleurArriere = couleurArriere;
|
||||
this.toucheHaut = toucheHaut;
|
||||
this.toucheBas = toucheBas;
|
||||
appliquerCouleurs();
|
||||
}
|
||||
|
||||
// Gère les contrôles du joueur
|
||||
public void appliquerTouche(int keyCode, boolean pressed) {
|
||||
if (estMort) return;
|
||||
|
||||
if (keyCode == toucheHaut) {
|
||||
if (pressed) {
|
||||
demiCercleAvant.Monter();
|
||||
demiCercleArriere.Monter();
|
||||
} else {
|
||||
demiCercleAvant.ArreterMonter();
|
||||
demiCercleArriere.ArreterMonter();
|
||||
}
|
||||
}
|
||||
if (keyCode == toucheBas) {
|
||||
if (pressed) {
|
||||
demiCercleAvant.Descendre();
|
||||
demiCercleArriere.Descendre();
|
||||
} else {
|
||||
demiCercleAvant.ArreterDescendre();
|
||||
demiCercleArriere.ArreterDescendre();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mettreAJourRayon(double rayonBase) {
|
||||
double rayon = rayonBase;
|
||||
if (bonusTailleActif) {
|
||||
rayon += 30;
|
||||
compteurBonusTaille--;
|
||||
if (compteurBonusTaille <= 0) {
|
||||
bonusTailleActif = false;
|
||||
}
|
||||
}
|
||||
demiCercleAvant.setRayon(rayon);
|
||||
demiCercleArriere.setRayon(rayon);
|
||||
}
|
||||
|
||||
//Appelé chaque frame et permet d'avancer le timer d'invincibilité et de mettre à jour l'effet visuel
|
||||
public void mettreAJourInvincibilite() {
|
||||
if (estMort) {
|
||||
demiCercleAvant.setCouleur(new Color(0, 0, 0, 0));
|
||||
demiCercleArriere.setCouleur(new Color(0, 0, 0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (compteurInvincible < 75) {
|
||||
compteurInvincible++;
|
||||
|
||||
if (compteurInvincible % 10 < 5) {
|
||||
if (invincibiliteRouge) {
|
||||
demiCercleArriere.setCouleur(new Color(1f, 0f, 0f));
|
||||
demiCercleAvant.setCouleur(new Color(1f, 0f, 0f));
|
||||
} else {
|
||||
demiCercleArriere.setCouleur(new Color(255, 255, 255, 150));
|
||||
demiCercleAvant.setCouleur(new Color(255, 255, 255, 150));
|
||||
}
|
||||
} else {
|
||||
appliquerCouleurs();
|
||||
}
|
||||
} else {
|
||||
appliquerCouleurs();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean estInvincible() {
|
||||
return compteurInvincible < 75;
|
||||
}
|
||||
|
||||
public void verifierCollisionLigne(Ligne li) {
|
||||
if (estMort || estInvincible()) return;
|
||||
|
||||
if (demiCercleArriere.VerifierCollision(li)) {
|
||||
if (!enCollision) {
|
||||
vies--;
|
||||
enCollision = true;
|
||||
compteurInvincible = 0;
|
||||
invincibiliteRouge = true;
|
||||
}
|
||||
} else {
|
||||
enCollision = false;
|
||||
}
|
||||
|
||||
if (vies <= 0) {
|
||||
vies = 0;
|
||||
estMort = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifierCollisionCollectible(double itemX, double itemY, double itemTaille, double vitesseLigne) {
|
||||
if (estMort) return false;
|
||||
double centreX = itemX + (itemTaille / 2.0);
|
||||
if (centreX <= demiCercleAvant.x && centreX > demiCercleAvant.x - vitesseLigne) {
|
||||
double hautCercle = demiCercleAvant.y - demiCercleAvant.getRayon();
|
||||
double basCercle = demiCercleAvant.y + demiCercleAvant.getRayon();
|
||||
return itemY > hautCercle && (itemY + itemTaille) < basCercle;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resterDansLigne(Ligne li) {
|
||||
if (estMort) return;
|
||||
demiCercleArriere.ResterDansLigne(li);
|
||||
demiCercleAvant.ResterDansLigne(li);
|
||||
}
|
||||
|
||||
public void activerBonusTaille() {
|
||||
bonusTailleActif = true;
|
||||
compteurBonusTaille = 150;
|
||||
}
|
||||
|
||||
public void ajouterVie() {
|
||||
vies++;
|
||||
}
|
||||
|
||||
public void retirerVie() {
|
||||
vies--;
|
||||
invincibiliteRouge = true;
|
||||
compteurInvincible = 0;
|
||||
if (vies <= 0) {
|
||||
vies = 0;
|
||||
estMort = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void resetInvincibilite() {
|
||||
compteurInvincible = 0;
|
||||
invincibiliteRouge = false;
|
||||
}
|
||||
|
||||
public void appliquerCouleurs() {
|
||||
demiCercleArriere.setCouleur(couleurArriere);
|
||||
demiCercleAvant.setCouleur(couleurAvant);
|
||||
}
|
||||
|
||||
public void ajouterDansEcran(ZoneDessin ecran) {
|
||||
ecran.ajouterObjet(demiCercleArriere);
|
||||
ecran.ajouterObjet(demiCercleAvant);
|
||||
}
|
||||
|
||||
public void reinitialiser(double posY) {
|
||||
vies = 3;
|
||||
enCollision = false;
|
||||
compteurInvincible = 0;
|
||||
invincibiliteRouge = false;
|
||||
bonusTailleActif = false;
|
||||
compteurBonusTaille = 0;
|
||||
estMort = false;
|
||||
demiCercleAvant.y = posY;
|
||||
demiCercleAvant.vitesse = -1.0;
|
||||
demiCercleArriere.y = posY;
|
||||
demiCercleArriere.vitesse = -1.0;
|
||||
appliquerCouleurs();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import java.util.ArrayList;
|
||||
|
||||
public class Ligne extends ObjetGraphique {
|
||||
|
||||
protected int nbSegments = 80;
|
||||
protected int nbSegments = 50;
|
||||
protected Segment SegCourant;
|
||||
|
||||
protected ArrayList<Segment> listeSegments = new ArrayList<Segment>();
|
||||
@@ -31,10 +31,9 @@ public class Ligne extends ObjetGraphique {
|
||||
this.gestionnaireNiveau = gestionnaireNiveau;
|
||||
|
||||
double dx = GetLargeurSegment();
|
||||
double freq = gestionnaireNiveau.getNoiseFrequence();
|
||||
|
||||
for (int i = 0; i < nbSegments; i++) {
|
||||
double noiseStep = dx * freq;
|
||||
double noiseStep = getNoiseStep();
|
||||
double yDebut = CalculerY(noiseCurseur);
|
||||
double yFin = CalculerY(noiseCurseur + noiseStep);
|
||||
|
||||
@@ -57,28 +56,32 @@ public class Ligne extends ObjetGraphique {
|
||||
return (double)ZoneDessin.largeur / nbSegments;
|
||||
}
|
||||
|
||||
private double getNoiseStep() {
|
||||
return GetLargeurSegment() / gestionnaireNiveau.getNoiseFrequence();
|
||||
}
|
||||
|
||||
// Quand un segment sort de l'écran, génère un nouveau segment à la fin de la ligne.
|
||||
protected Segment CreerSegmentSuivant(){
|
||||
double dx = GetLargeurSegment();
|
||||
double freq = gestionnaireNiveau.getNoiseFrequence();
|
||||
double noiseStep = dx * freq;
|
||||
double noiseStep = getNoiseStep();
|
||||
|
||||
double yDebut = CalculerY(noiseCurseur);
|
||||
double yFin = CalculerY(noiseCurseur + noiseStep);
|
||||
|
||||
noiseCurseur += noiseStep;
|
||||
|
||||
Segment s = new Segment(0, yDebut, dx, yFin - yDebut);
|
||||
Segment s = new Segment(0, yDebut, GetLargeurSegment(), yFin - yDebut);
|
||||
s.setCouleur(new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// Calcule la hauteur de la ligne à un point X.
|
||||
protected double CalculerY(double noisePos){
|
||||
double limiteHaut = gestionnaireNiveau.getLimiteHaut();
|
||||
double limiteBas = gestionnaireNiveau.getLimiteBas();
|
||||
double hauteur = limiteBas - limiteHaut;
|
||||
|
||||
double bruit = noiseGenerator.noise(noisePos);
|
||||
double bruit = noiseGenerator.noise(noisePos, 1);
|
||||
double normalise = (bruit + 1) / 2;
|
||||
|
||||
return limiteBas - normalise * hauteur;
|
||||
@@ -117,6 +120,7 @@ public class Ligne extends ObjetGraphique {
|
||||
UpdateSegments();
|
||||
}
|
||||
|
||||
// Permet de réutiliser les segments sortis de l'écran au debut
|
||||
private void UpdateSegments(){
|
||||
|
||||
if (dernierSegment == null) throw new RuntimeException("dernierSegment n'existe pas");
|
||||
@@ -124,7 +128,7 @@ public class Ligne extends ObjetGraphique {
|
||||
for (int i = 0; i < listeSegments.size(); i++) {
|
||||
|
||||
Segment s = listeSegments.get(i);
|
||||
if (s.x + s.xLong < 0) {
|
||||
if (s.x + s.xLong < 0) { // le segment est ENTIEREMENT hors de l'écran
|
||||
Segment nouveauSegment = CreerSegmentSuivant();
|
||||
nouveauSegment.x = dernierSegment.x + dernierSegment.xLong;
|
||||
listeSegments.set(i, nouveauSegment);
|
||||
@@ -135,6 +139,7 @@ public class Ligne extends ObjetGraphique {
|
||||
}
|
||||
}
|
||||
|
||||
// Renvoie la hauteur à laquelle doit etre le cercle. Utilisé pour la collision
|
||||
public double GetHauteurPointCercle(){
|
||||
double t = (400 - SegCourant.x) / SegCourant.xLong;
|
||||
|
||||
|
||||
36
src/Malus.java
Normal file
36
src/Malus.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.util.List;
|
||||
|
||||
public class Malus extends ObjetCollectible {
|
||||
|
||||
|
||||
public Malus(Ligne l, List<Joueur> joueurs, Jeu j) {
|
||||
super(l, joueurs, j);
|
||||
this.taille = 10;
|
||||
this.couleur = Color.RED;
|
||||
}
|
||||
|
||||
@Override protected int getSeuilActivation() { return 250; }
|
||||
|
||||
@Override protected Color getCouleurCapture() { return Color.BLACK; }
|
||||
|
||||
@Override
|
||||
protected double calculerY(double hauteurLigne) {
|
||||
if (Math.random() > 0.5) return hauteurLigne - 75 - (Math.random() * 30); // position du malus
|
||||
else return hauteurLigne + 75 + (Math.random() * 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appliquerEffet(Joueur joueur) {
|
||||
// On ne punit pas si le joueur est en cheat mode ou en période d'invincibilité (clignotement)
|
||||
if (!monJeu.cheatMode && !joueur.estInvincible()) joueur.retirerVie();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dessiner(Graphics g) {
|
||||
g.fillRect((int)Math.round(x), (int)Math.round(y), (int)taille, (int)taille);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -10,10 +11,12 @@ import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
// Classe qui représente le menu principal du jeu (affiché au lancement).
|
||||
public class MenuPrincipal {
|
||||
|
||||
private JFrame fenetre;
|
||||
@@ -25,37 +28,64 @@ public class MenuPrincipal {
|
||||
this.jeu = jeu;
|
||||
}
|
||||
|
||||
// Construit et affiche le panneau du menu dans la fenêtre
|
||||
public void afficher(String pseudoActuel) {
|
||||
|
||||
JPanel panneau = new JPanel(new GridLayout(6, 1, 10, 10));
|
||||
JPanel panneau = new JPanel(new GridLayout(9, 1, 10, 10));
|
||||
|
||||
JLabel titre = new JLabel("LINEA", SwingConstants.CENTER);
|
||||
champPseudo = new JTextField(pseudoActuel, 15);
|
||||
|
||||
JButton boutonJouer = new JButton("Jouer");
|
||||
JButton bouton1Joueur = new JButton("1 Joueur");
|
||||
JButton bouton2Joueurs = new JButton("2 Joueurs");
|
||||
JButton boutonClassement = new JButton("Classement");
|
||||
JButton boutonHistorique = new JButton("Historique");
|
||||
JButton boutonQuitter = new JButton("Quitter");
|
||||
JButton boutonCheat = new JButton("Cheat Mode : OFF");
|
||||
|
||||
boutonJouer.addActionListener(new ActionListener() {
|
||||
bouton1Joueur.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
jeu.lancerPartie(champPseudo.getText());
|
||||
jeu.lancerPartie(champPseudo.getText(), false);
|
||||
}
|
||||
});
|
||||
|
||||
bouton2Joueurs.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
jeu.lancerPartie(champPseudo.getText(), true);
|
||||
}
|
||||
});
|
||||
|
||||
boutonClassement.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
// 1. On récupère les scores depuis la BDD via l'objet 'jeu'
|
||||
String scores = jeu.getGestionnaireBDD().getTopScores();
|
||||
|
||||
// 2. On affiche le résultat dans la petite fenêtre popup
|
||||
JOptionPane.showMessageDialog(fenetre, scores, "Meilleurs Scores", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
});
|
||||
|
||||
boutonHistorique.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// pour le modele de tableau
|
||||
DefaultTableModel modele = jeu.getGestionnaireHistorique().getModeleTableau();
|
||||
|
||||
JTable tableau = new JTable(modele);
|
||||
|
||||
// pour ne pas pouvoir modifier le tableau
|
||||
tableau.setDefaultEditor(Object.class, null);
|
||||
// pour ne pas faire bouger les collones
|
||||
tableau.getTableHeader().setReorderingAllowed(false);
|
||||
|
||||
// pour le scroll
|
||||
JScrollPane scrollPane = new JScrollPane(tableau);
|
||||
scrollPane.setPreferredSize(new Dimension(400, 300));
|
||||
|
||||
// afficher la fenetre pop up
|
||||
JOptionPane.showMessageDialog(fenetre, scrollPane, "Historique des parties", JOptionPane.PLAIN_MESSAGE);
|
||||
}
|
||||
});
|
||||
|
||||
boutonQuitter.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -63,14 +93,24 @@ public class MenuPrincipal {
|
||||
}
|
||||
});
|
||||
|
||||
boutonCheat.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
jeu.cheatMode = !jeu.cheatMode;
|
||||
boutonCheat.setText(jeu.cheatMode ? "Cheat Mode : ON" : "Cheat Mode : OFF");
|
||||
}
|
||||
});
|
||||
|
||||
panneau.add(titre);
|
||||
panneau.add(champPseudo);
|
||||
panneau.add(boutonJouer);
|
||||
panneau.add(bouton1Joueur);
|
||||
panneau.add(bouton2Joueurs);
|
||||
panneau.add(boutonClassement);
|
||||
panneau.add(boutonHistorique);
|
||||
panneau.add(boutonCheat);
|
||||
panneau.add(boutonQuitter);
|
||||
|
||||
// panneau centré dans la fenêtre
|
||||
JPanel conteneur = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 150));
|
||||
JPanel conteneur = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 110));
|
||||
conteneur.add(panneau);
|
||||
|
||||
fenetre.setContentPane(conteneur);
|
||||
|
||||
@@ -7,7 +7,7 @@ public class Niveau {
|
||||
public final int numero;
|
||||
public final Color couleurFond;
|
||||
public final double vitesseScroll;
|
||||
public final double noiseFrequence; // vitesse d'avancement dans le noise
|
||||
public final double noiseFrequence;
|
||||
public final double rayonCercle;
|
||||
public final double limiteHaut;
|
||||
public final double limiteBas;
|
||||
|
||||
@@ -109,11 +109,28 @@ public class NoiseGenerator {
|
||||
return value / initialSize;
|
||||
}
|
||||
|
||||
// Seule fonction publique utilisée, génère une valeur de -1 à 1 à un point x.
|
||||
public double noise(double x, int octaves) {
|
||||
double value = 0.0;
|
||||
double size = default_size;
|
||||
double weightSum = 0;
|
||||
int count = 0;
|
||||
|
||||
while (size >= 1 && count < octaves) {
|
||||
value += smoothNoise((x / size), 0.7, 0.3) * size;
|
||||
weightSum += size;
|
||||
size /= 2.0;
|
||||
count++;
|
||||
}
|
||||
|
||||
return value / weightSum;
|
||||
}
|
||||
|
||||
public double smoothNoise(double x, double y, double z) {
|
||||
// Offset each coordinate by the seed value
|
||||
x += this.seed;
|
||||
y += this.seed;
|
||||
x += this.seed;
|
||||
z += this.seed;
|
||||
|
||||
int X = (int) Math.floor(x) & 255; // FIND UNIT CUBE THAT
|
||||
int Y = (int) Math.floor(y) & 255; // CONTAINS POINT.
|
||||
|
||||
81
src/ObjetCollectible.java
Normal file
81
src/ObjetCollectible.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package linea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.util.List;
|
||||
|
||||
// Classe de base pour tous les objets qu'on peut ramasser (bonus, malus...)
|
||||
// Elle gère toute la logique commune : apparition, déplacement, collision
|
||||
|
||||
public abstract class ObjetCollectible extends ObjetGraphique {
|
||||
|
||||
protected double taille;
|
||||
protected boolean actif = false;
|
||||
protected int compteurFrames = 0;
|
||||
protected boolean dejaCapture = false;
|
||||
|
||||
protected Ligne maLigne;
|
||||
protected List<Joueur> joueurs;
|
||||
protected Jeu monJeu;
|
||||
|
||||
public ObjetCollectible(Ligne l, List<Joueur> joueurs, Jeu j) {
|
||||
this.maLigne = l;
|
||||
this.joueurs = joueurs;
|
||||
this.monJeu = j;
|
||||
}
|
||||
// Chaque sous-classe décide quand elle apparaît, où, quel effet elle a et comment elle se dessine
|
||||
|
||||
protected abstract int getSeuilActivation();
|
||||
protected abstract double calculerY(double hauteurLigne);
|
||||
|
||||
protected abstract void appliquerEffet(Joueur joueur);
|
||||
|
||||
protected abstract Color getCouleurCapture();
|
||||
|
||||
protected abstract void dessiner(Graphics g);
|
||||
|
||||
@Override
|
||||
void Afficher(Graphics g) {
|
||||
if (actif) {
|
||||
g.setColor(dejaCapture ? getCouleurCapture() : this.couleur);
|
||||
dessiner(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void Animer() {
|
||||
if (!actif) compteurFrames++;
|
||||
|
||||
if (compteurFrames >= getSeuilActivation() && !actif) {
|
||||
// Quand on a attendu assez longtemps, l'objet spawn à droite de l'écran
|
||||
|
||||
actif = true;
|
||||
dejaCapture = false;
|
||||
x = 800;
|
||||
double hauteurLigne = 300;
|
||||
if (maLigne.dernierSegment != null)
|
||||
hauteurLigne = maLigne.dernierSegment.y;
|
||||
y = calculerY(hauteurLigne);
|
||||
if (y < 20) y = 20;
|
||||
if (y > 550) y = 550;
|
||||
compteurFrames = 0;
|
||||
}
|
||||
|
||||
if (actif) {
|
||||
double vitesseLigne = monJeu.gestionnaireNiveau.getVitesseScroll();
|
||||
x -= vitesseLigne; // l'objet suit la vitesse du niveau
|
||||
|
||||
if (!dejaCapture) {
|
||||
for (Joueur joueur : joueurs) {
|
||||
if (joueur.verifierCollisionCollectible(x, y, taille, vitesseLigne)) {
|
||||
appliquerEffet(joueur); // délégué à la sous-classe
|
||||
dejaCapture = true; // évite d'appliquer l'effet plusieurs fois
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x + taille < 0) actif = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user