From 06954ae3c495559615a3d3e0188c625aa8ec7099 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Mar 2026 17:19:34 +0100 Subject: [PATCH] updateCollision --- linea/BouleBonus.class | Bin 3696 -> 4679 bytes linea/BouleBonus.java | 77 ++++++++++++++++++++++++++++++++++++----- linea/Jeu.java | 8 ++--- linea/Ligne.class | Bin 3870 -> 4006 bytes linea/Ligne.java | 11 ++++++ linea/ZoneDessin.class | Bin 5736 -> 5853 bytes linea/ZoneDessin.java | 66 ++++++++++++++++++----------------- 7 files changed, 115 insertions(+), 47 deletions(-) diff --git a/linea/BouleBonus.class b/linea/BouleBonus.class index 6c89d14216cc0916ad492eb1f9cc5596de2cb8fa..acf5e60bd8be04d387105ae98cae2b12be94292a 100644 GIT binary patch literal 4679 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 literal 3696 zcmai1dvH|M8UNkv=5DgN*}OL70tO5Ll3iX7QgMT@n+M@xQp7-ND7D;dHk)NPyK#4u zfL5h;kXq}5>2!EhY#rOlFtv58CSOcS#geh? zI;u4Ky7ka<`sGuMDtKL}HZTh{8p>_mmeg<}(vnIJXXrC+?M>0Q)~1KN(@Jv<+#njR zkytj8$wb7^JOlG_qXwftZ4E|RQ^Uz@Bu&jt!dzgWUb)CAbVt(JSlCKL^x$hp&K1O2o3meUUB6zTt$Gjir*p_ZwIu{F^OhHjb^Nu>a;Vc#`gAhU$+?9XkZgI zGlgME_b@Y6-l6I~rM*TEzI|Sv3wo&PX7%WyrFQ&!@YVPC&zs!(fgY-`SuS)laZ?uT z+J`eM+w|b+$*m$R+1X*>v)IX`WTc~6$lOA<@sxpMc$%j!oZtz_ z2hZ*uJ)@-cQ2#!A5xkTOEL5%t(9f8;MQCbKoDcrF+}=a&`;?G$!Ve6*s5-&w&FI1L ze0=}T+g+76_t1?wol`jN!Yc;O$ni34tZ0p-!;)raG?Kl`jZ-*l;GFP<&?AH&8~BM3 zib%Lqz(kz?%)n~`V1)yFhf-OV!geNDcEP~Ur32ln1J%(G@>v;9({5|3kN(O!2y>qv z9_)>zw^>t#-r?gJDDBEx;drMtlw-JJncN{I_U&LG&Heqc@PJ^`tm~RAe_+^VF8p3Y z#Z>#|Ijl#sYOfp=i?47hk%(moPttN!YV5c^FKfh~Y^2+UN$GhuBaeD#Bs-AmyTcNw zBuo-%-Ce2SbU4x;lXR9%WAJi`19j|<5+I%mMk(Sx^a1#MPN;jsS%+bx?6Zl`bFhJ&4%8AK=b@KZS&Zq-U;!SY^dne^C$R{J z(12gjYB>t7k?C}y%Hd#=>X{vOxt$~0DBubx^uL74nd$VC^=tfQN|bj;PIT>aTwI@d zxuq}Sw>i=;Vr#ZYPfBwIt%`Ch>IfSVcPEtt#8vmQ;% z>pFDuvP`i>A47}E-7?8tugaYZzjI-`0~*I`ypkoKd0GK!E*b#-z=GM`>ZftZmdD@2 z{W0=6QFfDrV5d!>1uSGKHj*-ow{v<6;Zmt9@;CTA6UfZexSjkCr7>b_IPPXN4eX>c zJ3Yl-jE+I~VsF4TMY&H=?hh1CQ65y3F9u4cC|^>P{ejXc$^k`rBrt9HQAK$yP%$O* zgrXb_RCyYBAOqEAu~}`pSY|CyBSJ?}X4ZJ|H6E(3hXXaH5PeZE4ta5865j~SHj4vu zZ9&xuUVQWLQ>f!a;%W*$lk${_V6DlWJ!{s+qm&mT=IpQ+-!bQsDQ8zmaaw^``L zm>0*DzBoAo!>skx@nFPA=0Pezm^xz;Vhp`ji#@*my!b$AHdA9$%2;(38fV#?W znL8Es~yC!_6$a~bJ(N3g}vH4xKH~VzM%aR z_iI=1KtTZ>EGWjl0uS*@5b79am$o=Qgvaqo<40(4I2>28-a+v;N62xF8>&#qM*4LR zG_vsVtOBtx+u^uE3)grGd5npSGapdwL#%Vm;wgIvf6SfEZ}CboXt-<11b(=Q!>a)& z#~%gsMwVf9)O1QUqLcV(pol9LSx!o&sk2p&N5_Z;`M1}j0k>IXx(^?N%gJtZ2%_4z z!5nqXJxmxlz`Nkf#Qv`kp&sRbUtd-EnhWPO+zMSG&?yNV*vw!{9U(#Jck!oOv>$ c6Zpl2k(TmS$7 diff --git a/linea/BouleBonus.java b/linea/BouleBonus.java index c5014ab..52ae04e 100644 --- a/linea/BouleBonus.java +++ b/linea/BouleBonus.java @@ -15,6 +15,7 @@ public class BouleBonus extends ObjetGraphique { private double amplitudeOndulation = 0.2; private double vitesseHorizontaleLisse = 0.0; private double phaseOndulation = Math.random() * Math.PI * 2; // phase unique par boule + private double sensEvitementLigne = 0.0; private static double clamp(double value, double min, double max) { return Math.max(min, Math.min(max, value)); @@ -35,6 +36,7 @@ public class BouleBonus extends ObjetGraphique { this.rayon = 14; this.amplitudeOndulation = 0.14; this.vitesseHorizontaleLisse = 4.3; + this.sensEvitementLigne = Math.random() < 0.5 ? -1.0 : 1.0; } } @@ -45,15 +47,62 @@ public class BouleBonus extends ObjetGraphique { public boolean isVerte() { return estVerte; } + + public void garantirDistanceLigne(double yLigne, double margePx) { + if (estVerte) { + return; + } + + double distanceMiniCentre = rayon + Math.max(0.0, margePx); + double ecart = y - yLigne; + double distance = Math.abs(ecart); + if (distance >= distanceMiniCentre) { + return; + } + + double sens = (ecart == 0.0) ? sensEvitementLigne : Math.signum(ecart); + y = yLigne + sens * distanceMiniCentre; + vitesseVerticale = 0.0; + + if (y < 20) y = 20; + if (y > 580) y = 580; + } + + public void ajusterVitessePourDistanceLigne(double yLigne, double margePx) { + if (estVerte) { + return; + } + + double distanceCibleCentre = rayon + Math.max(0.0, margePx); + double ecart = y - yLigne; + double distance = Math.abs(ecart); + + + double progressionZone = clamp((560.0 - x) / 240.0, 0.0, 1.0); + if (progressionZone <= 0.0) { + return; + } + + double sens = (ecart == 0.0) ? sensEvitementLigne : Math.signum(ecart); + + // vitesse variable + if (distance > distanceCibleCentre) { + double excedent = distance - distanceCibleCentre; + double pas = clamp(excedent * (0.08 + progressionZone * 0.20), 0.0, 10.0 + progressionZone * 8.0); + y -= sens * pas; + } + + if (y < 20) y = 20; + if (y > 580) y = 580; + } @Override void Afficher(Graphics g) { Graphics2D g2D = (Graphics2D) g; - // Effet de pulsation (le rayon augmente/diminue) - double rayonAffiche = rayon + Math.sin(frameCounter * 0.12) * 1.5; + double rayonAffiche = rayon; - // Dessiner le cercle rempli (centré sur x,y) + // Dessiner le cercle rempli g2D.setColor(couleur); g2D.fillOval((int)(x - rayonAffiche), (int)(y - rayonAffiche), (int)(2 * rayonAffiche), (int)(2 * rayonAffiche)); @@ -67,7 +116,7 @@ public class BouleBonus extends ObjetGraphique { @Override void Animer() { - // Déplacement vers la gauche (même vitesse que la ligne) + // Déplacement vers la gauche x -= vitesse; } @@ -82,19 +131,26 @@ public class BouleBonus extends ObjetGraphique { double vitessePoursuite = estVerte ? 0.075 : 0.050; // meilleure réactivité double limiteVerticale = estVerte ? 1.85 : 1.05; // accélération verticale double amortissement = estVerte ? 0.87 : 0.81; // moins de friction - double zoneMorte = estVerte ? 18.0 : 16.0; // zone mort réduite + double zoneMorte = estVerte ? 18.0 : 16.0; // zone morte double vitesseVerticaleMax = estVerte ? 4.2 : 2.6; // vitesses verticales plus hautes + double proximiteJoueur = clamp((540.0 - x) / 280.0, 0.0, 1.0); + + if (!estVerte) { + // Plus rouge proche du joueur, plus on ouvre la fenêtre d'esquive. + vitessePoursuite *= (1.0 - proximiteJoueur * 0.66); + limiteVerticale *= (1.0 - proximiteJoueur * 0.52); + vitesseVerticaleMax *= (1.0 - proximiteJoueur * 0.40); + zoneMorte += proximiteJoueur * 22.0; + } double vitesseLigneSecurisee = Math.max(0.0, vitesseLigne); double vitesseCible = Math.min(vitesseMax, vitesseLigneSecurisee * facteurHorizontal); if (!estVerte) { - // Les rouges gardent une vitesse plus stable d'une boule à l'autre. vitesseCible = vitesseCible * 0.68 + 4.5 * 0.32; } double deltaVitesse = clamp(vitesseCible - vitesseHorizontaleLisse, -0.25, 0.25); double vitesseMaxLocale = vitesseMax; if (!estVerte && x < 380) { - // En fin d'écran, on plafonne un peu la vitesse pour laisser une fenêtre d'esquive stable. double facteurApproche = clamp((380.0 - x) / 180.0, 0.0, 1.0); vitesseMaxLocale = vitesseMax - (0.55 * facteurApproche); } @@ -103,11 +159,14 @@ public class BouleBonus extends ObjetGraphique { x -= vitesse; double vitesseJoueurLimitee = clamp(cibleVitesseY, -6.0, 6.0); - // Verte: anticipation légère + oscillation. Rouge: AUCUNE anticipation → trajectoire lisible, esquivable. double anticipation = estVerte ? vitesseJoueurLimitee * 3.2 : 0.0; double cibleLisse = cibleY + anticipation + (estVerte ? Math.sin(frameCounter * 0.055 + phaseOndulation) * 45.0 : 0.0); double deltaY = cibleLisse - y; + double ratioEcartY = clamp(Math.abs(deltaY) / 120.0, 0.50, 1.60); + vitessePoursuite *= ratioEcartY; + limiteVerticale *= Math.sqrt(ratioEcartY); + if (Math.abs(deltaY) < zoneMorte) { deltaY = 0; } @@ -136,7 +195,7 @@ public class BouleBonus extends ObjetGraphique { double cRayon = c.getRayon(); double dist = Math.hypot(cx - x, cy - y); - double seuil = estVerte ? (rayon + cRayon - 6.0) : (rayon + cRayon - 9.0); + double seuil = estVerte ? (rayon + cRayon - 6.0) : (rayon + cRayon - 10.5); return dist <= seuil; } diff --git a/linea/Jeu.java b/linea/Jeu.java index 779021f..f6b1202 100644 --- a/linea/Jeu.java +++ b/linea/Jeu.java @@ -355,26 +355,22 @@ public class Jeu implements KeyListener, ActionListener { * Évite de répéter ce code dans demarrer() et resetLevel(). */ private void initialiserPartie() { - // 1. Nettoyage de l'écran ecran.reinitialiser(); - // 2. Création des instances + // Création des instances demiCercleAvant = new Cercle(90, -180); demiCercleArriere = new Cercle(90, 180); ligne = new Ligne(_niv); ecran.setNiveau(_niv); - // 3. En mode immortel, positionner les cercles loin (la force les attirera vers la ligne) - // En mode normal, ils restent au centre (y = 200 par défaut du constructeur) + if (immortel) { demiCercleAvant.y = -300; demiCercleArriere.y = 300; } - // 4. Configuration visuelle appliquerThemeNiveau(); - // 5. Ajout à l'écran (l'ordre définit la superposition) ecran.ajouterObjet(demiCercleArriere); ecran.ajouterObjet(ligne); ecran.ajouterObjet(demiCercleAvant); diff --git a/linea/Ligne.class b/linea/Ligne.class index 96ab1b2c3816bf17f815f585a515735c0b73758d..1c5b729f5a975f4177113da713266ae5ee04bfef 100644 GIT binary patch delta 2428 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 diff --git a/linea/Ligne.java b/linea/Ligne.java index 04fb297..f93c263 100644 --- a/linea/Ligne.java +++ b/linea/Ligne.java @@ -44,10 +44,21 @@ public class Ligne extends ObjetGraphique{ double baseAmp = 20; double levelFactor = 10; // coeff pour monter la difficulté double amplitude = baseAmp + niveau * levelFactor; + double centreY = SCREEN_HEIGHT / 2.0; // pente maximale par segment pour rester jouable double maxStep = 40; double rawDy = (Math.random()*2 - 1) * amplitude; + + // Biais de recentrage: plus on s'éloigne du milieu, plus on est ramené vers le centre. + double ecartCentre = centreY - y; + rawDy += ecartCentre * 0.14; + + // Si on est très proche des bords, renforcer le retour vers le milieu. + if (y < VERTICAL_MARGIN + 45 || y > SCREEN_HEIGHT - VERTICAL_MARGIN - 45) { + rawDy += Math.signum(ecartCentre) * 14.0; + } + // limiter la variation brute if (rawDy > maxStep) rawDy = maxStep; if (rawDy < -maxStep) rawDy = -maxStep; diff --git a/linea/ZoneDessin.class b/linea/ZoneDessin.class index dccabbbde47d88396e16458347c2b48bc6e1545f..60affbc55c0017d7ff26e0da59a4ef344b951583 100644 GIT binary patch delta 2355 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 listeObjets = new ArrayList(); - // indicateur qu'une défaite (perte de contact) est survenue + // indicateur d'une defaite private boolean collisionOccur = false; - // indique si le cercle a déjà été sur la ligne (début de la phase de maintien) - private boolean hadBeenOnLine = false; - // mode immortel - ignore les collisions - private boolean immortel = false; + // indique si le cercle a déjà été sur la ligne + private boolean AEteSurLigne = false; + // mode immortel + private boolean immortel = false; // liste des boules bonus private ArrayList boolesBonus = new ArrayList(); // compteur pour générer les boules à intervalle régulier private int compteurBoule = 0; private int intervalleBouleBase = 165; // moins de boules sur la durée - private int delaiInitialBoule = 97; // apparition initiale avancée de 3% + private int delaiInitialBoule = 85; // apparition initiale légèrement plus tôt private int niveauActuel = 1; private Double dernierJoueurY = null; // type de bonus récupéré (-1 = rouge, 1 = vert, 0 = aucun) @@ -100,7 +100,7 @@ public class ZoneDessin extends JPanel { } dernierJoueurY = joueurY; - // --- 0. Récupérer la ligne pour synchroniser les boules --- + // Récupérer la ligne pour synchroniser les boules Ligne ligneObjet = null; for (ObjetGraphique obj : listeObjets) { if (obj instanceof Ligne) { @@ -109,12 +109,12 @@ public class ZoneDessin extends JPanel { } } - // --- 1. Générer une boule au bord droit sur la ligne --- + // Générer une boule double progression = Math.min(1.0, (niveauActuel - 1) / 25.0); int intervalleBoule = (int) Math.round(intervalleBouleBase - progression * 20.0); // ~165 -> 145 - double probaVerteBase = 0.35 - progression * 0.06; // ~35% -> 29% + double probaVerteBase = 0.23 - progression * 0.04; // ~23% -> 19% double variationAleatoire = (Math.random() - 0.5) * 0.10; // +/- 5% - double probaVerte = Math.max(0.24, Math.min(0.47, probaVerteBase + variationAleatoire + 0.02)); + double probaVerte = Math.max(0.10, Math.min(0.31, probaVerteBase + variationAleatoire)); compteurBoule++; if (compteurBoule >= intervalleBoule && ligneObjet != null) { @@ -124,11 +124,11 @@ public class ZoneDessin extends JPanel { double spawnX = 800; double spawnY; if (estVerte) { - // Vertes: proches de la trajectoire du joueur pour être récupérables. + // boules Vertes double margeVerte = 95.0 + progression * 45.0; spawnY = joueurY + (Math.random() * (2.0 * margeVerte)) - margeVerte; } else { - // Rouges: visent davantage le joueur, mais démarrent avec une marge d'esquive. + // boules Rouges double offset = 220 + progression * 20.0 + Math.random() * 150.0; spawnY = joueurY + (Math.random() < 0.5 ? -offset : offset); } @@ -137,7 +137,7 @@ public class ZoneDessin extends JPanel { if (spawnY > 580) spawnY = 580; if (!estVerte) { - // Marge suffisante pour esquiver, sans rendre les rouges inoffensives. + // Marge suffisante pour esquiver double distanceMin = 125.0; if (Math.abs(spawnY - joueurY) < distanceMin) { if (spawnY >= joueurY) { @@ -148,22 +148,25 @@ public class ZoneDessin extends JPanel { } } - // On crée la boule au bord droit (800) + // On crée la boule au bord droit BouleBonus boule = new BouleBonus(spawnX, spawnY, estVerte); boolesBonus.add(boule); } - // --- 2. Animation des objets --- + // Animation des objets for (ObjetGraphique obj : listeObjets) obj.Animer(); - // Mettre à jour et animer les boules (une seule fois par frame) + // Mettre à jour et animer les boules if (ligneObjet != null) { for (BouleBonus boule : boolesBonus) { boule.animerAvecCible(ligneObjet.getVitesse(), joueurY, vitesseJoueurY); + double yLigneLocal = ligneObjet.getYAuX(boule.getX()); + boule.ajusterVitessePourDistanceLigne(yLigneLocal, 15.0); + boule.garantirDistanceLigne(yLigneLocal, 15.0); } } - // 2. vérifier collision entre la Ligne et le Cercle (une seule passe de segments) + // vérifier collision entre la Ligne et le Cercle if (ligneObjet != null && cercleReference != null) { double[] info = ligneObjet.contactInfo( cercleReference.getX(), cercleReference.getY(), cercleReference.getRayon()); @@ -171,27 +174,27 @@ public class ZoneDessin extends JPanel { boolean enContact = (info != null) && (info[1] <= cercleReference.getRayon()); double ligneY = (info != null) ? info[0] : ligneObjet.getYAuX(cercleReference.getX()); - // Phase initiale en mode immortel : force d'attraction depuis le début - if (!hadBeenOnLine && immortel) { + // force d'attraction depuis le début + if (!AEteSurLigne && immortel) { double delta = ligneY - cercleReference.y; cercleReference.vitesse += delta * 0.12; // Marquer le premier contact if (enContact) { - hadBeenOnLine = true; + AEteSurLigne = true; } - } else if (hadBeenOnLine && immortel) { - // Phase maintenance : après le premier contact, maintenir le cercle sur la ligne + } else if (AEteSurLigne && immortel) { + // après le premier contact, maintenir le cercle sur la ligne double rayon = cercleReference.getRayon(); double limite = ligneY - rayon; double limiteBas = ligneY + rayon; - // Clamping : empêcher le cercle de sortir au-dessus + // empêcher le cercle de sortir au-dessus if (cercleReference.y < limite) { cercleReference.y = limite; if (cercleReference.vitesse < 0) cercleReference.vitesse *= -0.3; } - // Clamping : empêcher le cercle de sortir en-dessous + // empêcher le cercle de sortir en-dessous else if (cercleReference.y > limiteBas) { cercleReference.y = limiteBas; if (cercleReference.vitesse > 0) cercleReference.vitesse *= -0.3; @@ -214,7 +217,7 @@ public class ZoneDessin extends JPanel { } } - // 3. vérifier collisions entre les boules bonus et le cercle + // vérifier collisions entre les boules bonus et le cercle for (int i = boolesBonus.size() - 1; i >= 0; i--) { BouleBonus boule = boolesBonus.get(i); @@ -224,7 +227,7 @@ public class ZoneDessin extends JPanel { if (obj instanceof Cercle) { Cercle c = (Cercle) obj; if (boule.collisionAvec(c)) { - // Si touché : on définit le bonus et on détruit la boule + // Si touché définit le bonus et on détruit la boule bonusRecupere = boule.isVerte() ? 1 : -1; boolesBonus.remove(i); collision = true; @@ -233,15 +236,14 @@ public class ZoneDessin extends JPanel { } } - //4. Détruire la boule si elle dépasse le joueur sans être touchée --- - // Le cercle est à X = 400. Si la boule est à X < 350, elle est "passée". + //Détruire la boule si elle dépasse le joueur sans être touchée + if (!collision && boule.getX() < 320) { boolesBonus.remove(i); - // On ne change pas bonusRecupere ici (donc rien ne se passe) + } } - // 5. on demande à redessiner repaint(); } @@ -274,7 +276,7 @@ public class ZoneDessin extends JPanel { boolesBonus.clear(); estArrete = false; collisionOccur = false; - hadBeenOnLine = false; + AEteSurLigne = false; bonusRecupere = 0; compteurBoule = -delaiInitialBoule; dernierJoueurY = null;