package linea; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.util.ArrayList; public class Ligne extends ObjetGraphique { protected int nbSegments = 50; protected Segment SegCourant; protected ArrayList listeSegments = new ArrayList(); protected Segment dernierSegment; private double decalageXDernierSegment = 0; private NoiseGenerator noiseGenerator; private GestionnaireNiveau gestionnaireNiveau; private double xActuel; // 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; this.gestionnaireNiveau = gestionnaireNiveau; double dx = GetLargeurSegment(); for (int i = 0; i < nbSegments; i++) { double noiseStep = getNoiseStep(); 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) { dernierSegment = s; xActuel = x + dx; } x += dx; } } protected double GetLargeurSegment(){ 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 noiseStep = getNoiseStep(); double yDebut = CalculerY(noiseCurseur); double yFin = CalculerY(noiseCurseur + noiseStep); noiseCurseur += noiseStep; 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, 1); double normalise = (bruit + 1) / 2; return limiteBas - normalise * hauteur; } @Override public void Afficher(Graphics g) { Graphics2D g2D = (Graphics2D) g; g2D.setStroke(new BasicStroke(3.0f)); for (Segment s : listeSegments) { s.Afficher(g); if (SegCourant == null) { if (Cercle.xCercle <= s.x + s.xLong && Cercle.xCercle >= s.x) { SegCourant = s; } } else { if ((SegCourant.x + SegCourant.xLong) < Cercle.xCercle) { if (s.x <= Cercle.xCercle && (s.x + s.xLong) >= Cercle.xCercle) { SegCourant = s; } } } } } @Override public void Animer() { double vitesse = gestionnaireNiveau.getVitesseScroll(); for (Segment s : listeSegments) { s.Animer(); s.x -= vitesse; } 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"); for (int i = 0; i < listeSegments.size(); i++) { Segment s = listeSegments.get(i); 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); xActuel += GetLargeurSegment(); dernierSegment = nouveauSegment; } } } // Renvoie la hauteur à laquelle doit etre le cercle. Utilisé pour la collision public double GetHauteurPointCercle(){ double t = (400 - SegCourant.x) / SegCourant.xLong; return SegCourant.y + SegCourant.yLong * t; } }