diff --git a/.gitignore b/.gitignore index 14392bf..09f6b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,7 @@ bin/ # ======================== # 3. ANTIGRAVITY / VSCODE # ======================== -.vscode/ +.claude/ .antigravity/ *.code-workspace diff --git a/linea_scores.db b/linea_scores.db index 01a6679..a2ff075 100644 Binary files a/linea_scores.db and b/linea_scores.db differ diff --git a/src/Bonus.java b/src/Bonus.java new file mode 100644 index 0000000..db08c22 --- /dev/null +++ b/src/Bonus.java @@ -0,0 +1,79 @@ +package linea; + +import java.awt.Color; +import java.awt.Graphics; + +public class Bonus extends ObjetGraphique { + + protected double taille = 10; + protected boolean actif = false; + protected int compteurFrames = 0; + + protected Ligne maLigne; + protected Cercle monCercle; + protected Jeu monJeu; + + public Bonus(Ligne l, Cercle c, Jeu j) { + this.maLigne = l; + this.monCercle = c; + this.monJeu = j; + this.couleur = Color.RED; + } + + @Override + void Afficher(Graphics g) { + if (actif) { + g.setColor(this.couleur); + 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; + } + } + } +} \ No newline at end of file diff --git a/src/Cercle.java b/src/Cercle.java index 9463e6a..0d45a28 100644 --- a/src/Cercle.java +++ b/src/Cercle.java @@ -15,11 +15,12 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc protected double fin = 360; protected boolean montee = false; - protected double vitesse = -1.0; + protected boolean descente = false; + protected double vitesse = 0; // pas = "delta t", permet de régler la jouabilité protected double pas = 0.2; - protected double impulsion = 35; + protected double impulsion = 2; public static int xCercle = 400; @@ -39,8 +40,10 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc return rayon; } - // note que "haut" a été appuyée (évite d'être tributaire de la répétition - // clavier) + public void setRayon(double r) { + rayon = r; + } + public void Monter() { montee = true; } @@ -49,6 +52,14 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc montee = false; } + public void Descendre() { + descente = true; + } + + public void ArreterDescendre() { + descente = false; + } + @Override void Afficher(Graphics g) { Graphics2D g2D = (Graphics2D) g; @@ -59,23 +70,25 @@ public class Cercle extends ObjetGraphique { // il s'agit plutôt d'arcs de cerc @Override void Animer() { - // chute libre - vitesse = vitesse + 9.81 * pas; - - // impulsion vers le haut + // acceleration vers le haut if (montee == true) { - vitesse = vitesse - impulsion * pas; + vitesse -= impulsion * pas; } - depY = 1 / 2 * 9.81 + vitesse * pas; + // acceleration vers le bas + if (descente == true) { + vitesse += impulsion * pas; + } - if (depY < -10) { - depY = -10; + // limiter la vitesse max + if (vitesse < -10) { + vitesse = -10; } - if (depY > 10) { - depY = 10; + if (vitesse > 10) { + vitesse = 10; } - y += depY; + + y += vitesse; } public void ResterDansLigne(Ligne li) { diff --git a/src/GestionnaireNiveau.java b/src/GestionnaireNiveau.java new file mode 100644 index 0000000..7141972 --- /dev/null +++ b/src/GestionnaireNiveau.java @@ -0,0 +1,128 @@ +package linea; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +public class GestionnaireNiveau { + + public static final int FRAMES_PAR_NIVEAU = 25 * 10; // 10 secondes + + private final List niveaux = new ArrayList<>(); + private int indexNiveau = 0; + private int framesDepuisDebut = 0; + private int framesDansNiveau = 0; + + private static final int DUREE_FADE = 25 * 3; // 3 secondes + + public GestionnaireNiveau() { + + // Niveau 1 + niveaux.add(new Niveau(1, + new Color(112, 158, 251), + 8, 1 / 80.0, 80, 100, 500)); + + // Niveau 2 + niveaux.add(new Niveau(2, + new Color(187, 138, 255), + 10, 1 / 60.0, 60, 100, 500)); + + // Niveau 3 + niveaux.add(new Niveau(3, + new Color(255, 106, 132), + 12, 1 / 40.0, 50, 100, 500)); + + // Niveau 4 + niveaux.add(new Niveau(4, + new Color(191, 255, 207), + 14, 1 / 35.0, 40, 100, 500)); + + // Niveau 5 + niveaux.add(new Niveau(5, + new Color(30, 30, 30), + 15, 1 / 30.0, 30, 100, 500)); + } + + public void mettreAJour() { + framesDepuisDebut++; + framesDansNiveau++; + + if (framesDansNiveau >= FRAMES_PAR_NIVEAU && indexNiveau < niveaux.size() - 1) { + indexNiveau++; + framesDansNiveau = 0; + } + } + + public Niveau getNiveauActuel() { + return niveaux.get(indexNiveau); + } + + public int getNumeroNiveau() { + return niveaux.get(indexNiveau).numero; + } + + public Color getCouleurFondInterpolee() { + if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) { + Color de = niveaux.get(indexNiveau - 1).couleurFond; + Color vers = niveaux.get(indexNiveau).couleurFond; + double t = (double) framesDansNiveau / DUREE_FADE; + return interpolerCouleur(de, vers, t); + } + return niveaux.get(indexNiveau).couleurFond; + } + + public double getVitesseScroll() { + if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) { + double de = niveaux.get(indexNiveau - 1).vitesseScroll; + double vers = niveaux.get(indexNiveau).vitesseScroll; + double t = (double) framesDansNiveau / DUREE_FADE; + return de + (vers - de) * t; + } + return niveaux.get(indexNiveau).vitesseScroll; + } + + public double getNoiseFrequence() { + if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) { + double de = niveaux.get(indexNiveau - 1).noiseFrequence; + double vers = niveaux.get(indexNiveau).noiseFrequence; + double t = (double) framesDansNiveau / DUREE_FADE; + return de + (vers - de) * t; + } + return niveaux.get(indexNiveau).noiseFrequence; + } + + public double getRayonCercle() { + if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) { + double de = niveaux.get(indexNiveau - 1).rayonCercle; + double vers = niveaux.get(indexNiveau).rayonCercle; + double t = (double) framesDansNiveau / DUREE_FADE; + return de + (vers - de) * t; + } + return niveaux.get(indexNiveau).rayonCercle; + } + + public double getLimiteHaut() { + return niveaux.get(indexNiveau).limiteHaut; + } + + public double getLimiteBas() { + return niveaux.get(indexNiveau).limiteBas; + } + + public void reinitialiser() { + indexNiveau = 0; + framesDepuisDebut = 0; + framesDansNiveau = 0; + } + + private static Color interpolerCouleur(Color de, Color vers, double t) { + int r = (int) (de.getRed() + (vers.getRed() - de.getRed()) * t); + int g = (int) (de.getGreen() + (vers.getGreen() - de.getGreen()) * t); + int b = (int) (de.getBlue() + (vers.getBlue() - de.getBlue()) * t); + return new Color( + Math.max(0, Math.min(255, r)), + Math.max(0, Math.min(255, g)), + Math.max(0, Math.min(255, b)) + ); + } +} diff --git a/src/Jeu.java b/src/Jeu.java index 9705bb0..b42f07d 100644 --- a/src/Jeu.java +++ b/src/Jeu.java @@ -21,8 +21,8 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { 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 - // A FAIRE : ajouter les objets graphiques manquants, s'il y en a - protected Ligne lili = new Ligne(new NoiseGenerator(0)); + protected GestionnaireNiveau gestionnaireNiveau = new GestionnaireNiveau(); + protected Ligne lili = new Ligne(new NoiseGenerator(0), gestionnaireNiveau); protected Timer horloge; @@ -69,16 +69,24 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { demiCercleAvant.Monter(); demiCercleArriere.Monter(); } + if (keyCode == 40) { // flèche bas + demiCercleAvant.Descendre(); + demiCercleArriere.Descendre(); + } } @Override public void keyReleased(KeyEvent e) { int keyCode = e.getKeyCode(); - if (keyCode == 38) { + if (keyCode == 38) { // flèche haut demiCercleAvant.ArreterMonter(); demiCercleArriere.ArreterMonter(); } + if (keyCode == 40) { // flèche bas + demiCercleAvant.ArreterDescendre(); + demiCercleArriere.ArreterDescendre(); + } } @Override @@ -101,6 +109,9 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { public void lancerPartie(String pseudoSaisi) { pseudo = pseudoSaisi; + // C'est cette ligne qui donne vie au bonus ! + ecran.ajouterObjet(new Bonus(lili, demiCercleAvant, this)); + // A FAIRE : placer dans l'écran tous les objets graphiques nécessaires ecran.ajouterObjet(demiCercleArriere); ecran.ajouterObjet(lili); @@ -122,6 +133,7 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { enCollision = false; estGameOver = false; compteurInvincible = 0; + gestionnaireNiveau.reinitialiser(); labGameOver.setVisible(false); ecran.demarrer(); @@ -141,6 +153,13 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { return; } + gestionnaireNiveau.mettreAJour(); + ecran.setCouleurFond(gestionnaireNiveau.getCouleurFondInterpolee()); + + double rayon = gestionnaireNiveau.getRayonCercle(); + demiCercleAvant.setRayon(rayon); + demiCercleArriere.setRayon(rayon); + ecran.traiterBoucleAnimation(); compteurFrames = compteurFrames + 1; @@ -174,7 +193,7 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { } } - labScore.setText("

Score : " + (int) score + " | Vies : " + vies + "

"); + labScore.setText("

Score : " + (int) score + " | Vies : " + vies + " | Niv. " + gestionnaireNiveau.getNumeroNiveau() + "

"); demiCercleArriere.ResterDansLigne(lili); demiCercleAvant.ResterDansLigne(lili); @@ -185,7 +204,8 @@ public class Jeu implements KeyListener, ActionListener, MouseListener { horloge.stop(); } - lili = new Ligne(new NoiseGenerator(0)); + gestionnaireNiveau.reinitialiser(); + lili = new Ligne(new NoiseGenerator(0), gestionnaireNiveau); demiCercleAvant.y = 200; demiCercleAvant.vitesse = -1.0; diff --git a/src/Ligne.java b/src/Ligne.java index 4a6a89b..77d0e68 100644 --- a/src/Ligne.java +++ b/src/Ligne.java @@ -8,40 +8,48 @@ import java.util.ArrayList; public class Ligne extends ObjetGraphique { - protected int nbSegments = 80; + protected int nbSegments = 50; protected Segment SegCourant; protected ArrayList listeSegments = new ArrayList(); - protected double limiteHaut = 50; - protected double limiteBas = 550; - protected Segment dernierSegment; private double decalageXDernierSegment = 0; - protected double noiseFrequence = 1/50f; - private NoiseGenerator noiseGenerator; + private GestionnaireNiveau gestionnaireNiveau; private double xActuel; - public Ligne(NoiseGenerator noiseGenerator) { + // Curseur dans le noise : avance plus vite quand la frequence du niveau augmente + private double noiseCurseur = 0; + + public Ligne(NoiseGenerator noiseGenerator, GestionnaireNiveau gestionnaireNiveau) { double x = 0; this.noiseGenerator = noiseGenerator; - for (int i = 0; i < nbSegments; i++) { + this.gestionnaireNiveau = gestionnaireNiveau; - Segment s = CreerSegment(x); + double dx = GetLargeurSegment(); + double freq = gestionnaireNiveau.getNoiseFrequence(); + + for (int i = 0; i < nbSegments; i++) { + double noiseStep = dx * freq; + double yDebut = CalculerY(noiseCurseur); + double yFin = CalculerY(noiseCurseur + noiseStep); + + Segment s = new Segment(x, yDebut, dx, yFin - yDebut); + s.setCouleur(new Color(0.2f, 0.2f, 0.2f)); listeSegments.add(s); + noiseCurseur += noiseStep; - if (i == nbSegments - 1) - { + if (i == nbSegments - 1) { dernierSegment = s; - xActuel = x + s.xLong; + xActuel = x + dx; } - x += s.xLong; + x += dx; } } @@ -49,26 +57,31 @@ public class Ligne extends ObjetGraphique { return (double)ZoneDessin.largeur / nbSegments; } - protected Segment CreerSegment(double x){ + protected Segment CreerSegmentSuivant(){ double dx = GetLargeurSegment(); - double y = CalculerY(x); - double dy = CalculerY(x + dx) - y; + double freq = gestionnaireNiveau.getNoiseFrequence(); + double noiseStep = dx * freq; - Segment s = new Segment(x, y, dx, dy); + double yDebut = CalculerY(noiseCurseur); + double yFin = CalculerY(noiseCurseur + noiseStep); + noiseCurseur += noiseStep; + + Segment s = new Segment(0, yDebut, dx, yFin - yDebut); s.setCouleur(new Color(0.2f, 0.2f, 0.2f)); return s; } - protected double CalculerY(double x){ - + protected double CalculerY(double noisePos){ + double limiteHaut = gestionnaireNiveau.getLimiteHaut(); + double limiteBas = gestionnaireNiveau.getLimiteBas(); double hauteur = limiteBas - limiteHaut; - double bruit = noiseGenerator.noise(x * noiseFrequence); - bruit = (bruit + 1) / 2; + double bruit = noiseGenerator.noise(noisePos); + double normalise = (bruit + 1) / 2; - return limiteBas - bruit * hauteur; + return limiteBas - normalise * hauteur; } @Override @@ -94,9 +107,11 @@ public class Ligne extends ObjetGraphique { @Override public void Animer() { + double vitesse = gestionnaireNiveau.getVitesseScroll(); + for (Segment s : listeSegments) { s.Animer(); - s.x -= 10; + s.x -= vitesse; } UpdateSegments(); @@ -110,7 +125,7 @@ public class Ligne extends ObjetGraphique { Segment s = listeSegments.get(i); if (s.x + s.xLong < 0) { - Segment nouveauSegment = CreerSegment(xActuel); + Segment nouveauSegment = CreerSegmentSuivant(); nouveauSegment.x = dernierSegment.x + dernierSegment.xLong; listeSegments.set(i, nouveauSegment); @@ -125,4 +140,4 @@ public class Ligne extends ObjetGraphique { return SegCourant.y + SegCourant.yLong * t; } -} \ No newline at end of file +} diff --git a/src/Niveau.java b/src/Niveau.java new file mode 100644 index 0000000..8f8c516 --- /dev/null +++ b/src/Niveau.java @@ -0,0 +1,25 @@ +package linea; + +import java.awt.Color; + +public class Niveau { + + public final int numero; + public final Color couleurFond; + public final double vitesseScroll; + public final double noiseFrequence; + public final double rayonCercle; + public final double limiteHaut; + public final double limiteBas; + + public Niveau(int numero, Color couleurFond, double vitesseScroll, + double noiseFrequence, double rayonCercle, double limiteHaut, double limiteBas) { + this.numero = numero; + this.couleurFond = couleurFond; + this.vitesseScroll = vitesseScroll; + this.noiseFrequence = noiseFrequence; + this.rayonCercle = rayonCercle; + this.limiteHaut = limiteHaut; + this.limiteBas = limiteBas; + } +} diff --git a/src/ZoneDessin.java b/src/ZoneDessin.java index 681fd6f..7f5f724 100644 --- a/src/ZoneDessin.java +++ b/src/ZoneDessin.java @@ -21,10 +21,17 @@ public class ZoneDessin extends JPanel { public static int largeur = 800; public static int hauteur = 600; + private Color couleurFond = new Color(0, 73, 220); + public ZoneDessin() { setLayout(new BorderLayout()); setPreferredSize(new Dimension(largeur, hauteur)); - setBackground(new Color(0, 73, 220)); + setBackground(couleurFond); + } + + public void setCouleurFond(Color c) { + couleurFond = c; + setBackground(c); } public void ajouterObjet(ObjetGraphique unObjet) {