Files
Projet-Dev/linea/ZoneDessin.java

283 lines
10 KiB
Java
Raw Normal View History

2026-02-10 16:39:21 +01:00
package linea;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import javax.swing.JPanel;
public class ZoneDessin extends JPanel {
private static final long serialVersionUID = 1L;
// un booleen qui permet d'arreter l'animation (suspendre)
protected boolean estArrete = false;
// liste des objets graphiques
private ArrayList<ObjetGraphique> listeObjets = new ArrayList<ObjetGraphique>();
2026-02-23 09:41:54 +01:00
// indicateur qu'une défaite (perte de contact) est survenue
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;
// liste des boules bonus
private ArrayList<BouleBonus> boolesBonus = new ArrayList<BouleBonus>();
// compteur pour générer les boules à intervalle régulier
private int compteurBoule = 0;
2026-03-28 14:18:17 +01:00
private int intervalleBouleBase = 165; // moins de boules sur la durée
private int delaiInitialBoule = 97; // apparition initiale avancée de 3%
private int niveauActuel = 1;
private Double dernierJoueurY = null;
// type de bonus récupéré (-1 = rouge, 1 = vert, 0 = aucun)
private int bonusRecupere = 0;
2026-02-10 16:39:21 +01:00
public ZoneDessin(){
setLayout(new BorderLayout());
setPreferredSize(new Dimension(800, 600));
setBackground(new Color(220,170,0));
}
2026-03-28 14:18:17 +01:00
public void setCouleurFond(Color couleurFond) {
setBackground(couleurFond);
}
public void setImmortel(boolean immortel) {
this.immortel = immortel;
}
2026-03-28 14:18:17 +01:00
public void setNiveau(int niveau) {
if (niveau < 1) {
niveauActuel = 1;
} else if (niveau > 100) {
niveauActuel = 100;
} else {
niveauActuel = niveau;
}
}
public int getBonusRecupere() {
return bonusRecupere;
}
public void reinitialiserBonus() {
bonusRecupere = 0;
}
2026-02-10 16:39:21 +01:00
// Ajout d'un objet graphique à la zone de dessin
public void ajouterObjet(ObjetGraphique unObjet) {
listeObjets.add(unObjet);
}
public void arreter(){
estArrete = true;
}
public void demarrer(){
estArrete = false;
}
public void traiterBoucleAnimation(){
if (estArrete==true) {
return;
}
2026-03-28 14:18:17 +01:00
Cercle cercleReference = null;
for (ObjetGraphique obj : listeObjets) {
if (obj instanceof Cercle) {
cercleReference = (Cercle) obj;
break;
}
}
double joueurY = (cercleReference != null) ? cercleReference.getY() : 300;
double vitesseJoueurY = 0.0;
if (dernierJoueurY != null) {
vitesseJoueurY = joueurY - dernierJoueurY;
}
dernierJoueurY = joueurY;
2026-02-10 16:39:21 +01:00
// --- 0. Récupérer la ligne pour synchroniser les boules ---
Ligne ligneObjet = null;
for (ObjetGraphique obj : listeObjets) {
if (obj instanceof Ligne) {
ligneObjet = (Ligne) obj;
break;
}
}
// --- 1. Générer une boule au bord droit sur la ligne ---
2026-03-28 14:18:17 +01:00
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 variationAleatoire = (Math.random() - 0.5) * 0.10; // +/- 5%
double probaVerte = Math.max(0.22, Math.min(0.45, probaVerteBase + variationAleatoire));
compteurBoule++;
if (compteurBoule >= intervalleBoule && ligneObjet != null) {
compteurBoule = 0;
2026-03-28 14:18:17 +01:00
boolean estVerte = Math.random() < probaVerte;
double spawnX = 800;
double spawnY;
if (estVerte) {
// Vertes: proches de la trajectoire du joueur pour être récupérables.
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.
double offset = 220 + progression * 20.0 + Math.random() * 150.0;
spawnY = joueurY + (Math.random() < 0.5 ? -offset : offset);
}
if (spawnY < 20) spawnY = 20;
if (spawnY > 580) spawnY = 580;
if (!estVerte) {
// Marge suffisante pour esquiver, sans rendre les rouges inoffensives.
double distanceMin = 125.0;
if (Math.abs(spawnY - joueurY) < distanceMin) {
if (spawnY >= joueurY) {
spawnY = Math.min(580, joueurY + distanceMin);
} else {
spawnY = Math.max(20, joueurY - distanceMin);
}
}
}
// On crée la boule au bord droit (800)
BouleBonus boule = new BouleBonus(spawnX, spawnY, estVerte);
boolesBonus.add(boule);
}
// --- 2. Animation des objets ---
for (ObjetGraphique obj : listeObjets) obj.Animer();
2026-03-28 14:18:17 +01:00
// Mettre à jour et animer les boules (une seule fois par frame)
if (ligneObjet != null) {
for (BouleBonus boule : boolesBonus) {
2026-03-28 14:18:17 +01:00
boule.animerAvecCible(ligneObjet.getVitesse(), joueurY, vitesseJoueurY);
}
}
2026-03-28 14:18:17 +01:00
// 2. vérifier collision entre la Ligne et le Cercle (une seule passe de segments)
if (ligneObjet != null && cercleReference != null) {
double[] info = ligneObjet.contactInfo(
cercleReference.getX(), cercleReference.getY(), cercleReference.getRayon());
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) {
double delta = ligneY - cercleReference.y;
cercleReference.vitesse += delta * 0.12;
// Marquer le premier contact
if (enContact) {
hadBeenOnLine = true;
}
} else if (hadBeenOnLine && immortel) {
// Phase maintenance : 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
if (cercleReference.y < limite) {
cercleReference.y = limite;
if (cercleReference.vitesse < 0) cercleReference.vitesse *= -0.3;
}
// Clamping : empêcher le cercle de sortir en-dessous
else if (cercleReference.y > limiteBas) {
cercleReference.y = limiteBas;
if (cercleReference.vitesse > 0) cercleReference.vitesse *= -0.3;
}
} else if (info != null && !enContact && !immortel) {
// Mode normal : mort si hors contact
collisionOccur = true;
estArrete = true;
}
// Synchroniser tous les autres Cercle en mode immortel
if (immortel) {
for (ObjetGraphique obj : listeObjets) {
if (obj instanceof Cercle && obj != cercleReference) {
Cercle autre = (Cercle) obj;
autre.y = cercleReference.y;
autre.vitesse = cercleReference.vitesse;
2026-02-23 09:41:54 +01:00
}
}
}
}
// 3. vérifier collisions entre les boules bonus et le cercle
for (int i = boolesBonus.size() - 1; i >= 0; i--)
{
BouleBonus boule = boolesBonus.get(i);
boolean collision = false;
2026-02-23 09:41:54 +01:00
for (ObjetGraphique obj : listeObjets) {
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
bonusRecupere = boule.isVerte() ? 1 : -1;
boolesBonus.remove(i);
collision = true;
break;
}
}
}
//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".
2026-03-28 14:18:17 +01:00
if (!collision && boule.getX() < 320) {
boolesBonus.remove(i);
// On ne change pas bonusRecupere ici (donc rien ne se passe)
}
}
// 5. on demande à redessiner
2026-02-23 09:41:54 +01:00
repaint();
2026-02-10 16:39:21 +01:00
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
// Afficher tous les objets
for (ObjetGraphique obj : listeObjets) {
obj.Afficher(g);
}
// Afficher les boules bonus
for (BouleBonus boule : boolesBonus) {
boule.Afficher(g);
}
2026-02-10 16:39:21 +01:00
}
2026-02-23 09:41:54 +01:00
// Indique si une collision est survenue
public boolean aCollision() {
return collisionOccur;
}
2026-02-23 09:57:06 +01:00
// Réinitialise l'état de la zone de dessin et supprime les objets graphiques
public void reinitialiser() {
listeObjets.clear();
boolesBonus.clear();
2026-02-23 09:57:06 +01:00
estArrete = false;
collisionOccur = false;
hadBeenOnLine = false;
bonusRecupere = 0;
2026-03-28 14:18:17 +01:00
compteurBoule = -delaiInitialBoule;
dernierJoueurY = null;
2026-02-23 09:57:06 +01:00
repaint();
}
2026-02-10 16:39:21 +01:00
}