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{ private int nbSegments = 400; private double xCercle = 400; private Segment SegCourant; // vitesse de déplacement (augmente légèrement chaque frame) private double vitesse = 5.0; // croissance initiale (fractionnelle) appliquée chaque frame private double croissance = 0.001; // ~0.1% initial // facteur qui amplifie la croissance elle-même (pour accélérer la montée) private double facteurCroissance = 1.00003; // croissance augmente légèrement private int niveau = 1; // niveau de difficulté, à augmenter pour rendre le jeu plus difficile // liste des segments private ArrayList segments = new ArrayList(); // écran fixe actuellement 800x600 (voir ZoneDessin) private static final int SCREEN_WIDTH = 800; private static final int SCREEN_HEIGHT = 600; private static final int VERTICAL_MARGIN = 20; // éviter de toucher les bords public Ligne(int _niveaux){ niveau = _niveaux; double x = SCREEN_WIDTH; // commence au bord droit double y = SCREEN_HEIGHT/2.0; // milieu vertical double dx,dy; nbSegments += niveau * 50; // augmenter le nombre de segments avec les niveaux Segment s; for (int i=0; i maxStep) rawDy = maxStep; if (rawDy < -maxStep) rawDy = -maxStep; double tentativeY = y + rawDy; // si on dépasserait les marges, repositionner vers l'intérieur if (tentativeY < VERTICAL_MARGIN) { tentativeY = VERTICAL_MARGIN + Math.random()*10; } else if (tentativeY > SCREEN_HEIGHT - VERTICAL_MARGIN) { tentativeY = SCREEN_HEIGHT - VERTICAL_MARGIN - Math.random()*10; } dy = tentativeY - y; // éviter pente nulle (ligne plate) en forçant un petit mouvement if (Math.abs(dy) < 1.0) { dy = (rawDy < 0 ? -1.0 : 1.0); tentativeY = y + dy; } s = new Segment(x,y,dx,dy); s.setCouleur(new Color(0.2f,0.2f,0.2f)); segments.add(s); x += dx; y = tentativeY; } } @Override public void Afficher(Graphics g){ Graphics2D g2D = (Graphics2D) g; g2D.setStroke(new BasicStroke(3.0f)); for (Segment seg : segments) { seg.Afficher(g); } } @Override public void Animer() { // déplace tous les segments vers la gauche double delta = vitesse; // vitesse de déplacement (exponentielle) for (Segment seg : segments) { seg.x -= delta; } // appliquer la croissance (vitesse *= 1 + croissance) vitesse *= (1.0 + croissance + (niveau * 0.00001)); // augmenter la croissance avec le niveau // augmenter légèrement la croissance pour que l'accélération s'amplifie croissance *= facteurCroissance; } // Indique si l'axe horizontal du cercle (cx) se trouve au niveau // d'un des segments de la ligne -> le cercle est "sur la ligne" public boolean estSurLaLigne(double cx) { for (Segment seg : segments) { double x1 = seg.x; double x2 = seg.x + seg.xLong; if ((cx >= Math.min(x1, x2)) && (cx <= Math.max(x1, x2))) { return true; } } return false; } // Vérifie la collision entre la ligne (segments) et un cercle public boolean collisionAvec(Cercle c) { double cx = c.getX(); double cy = c.getY(); double rayon = c.getRayon(); for (Segment seg : segments) { double x1 = seg.x; double y1 = seg.y; double x2 = seg.x + seg.xLong; double y2 = seg.y + seg.yLong; double dist = pointSegmentDistance(cx, cy, x1, y1, x2, y2); if (dist <= rayon) { return true; } } return false; } // distance minimale entre un point (px,py) et un segment (x1,y1)-(x2,y2) private double pointSegmentDistance(double px, double py, double x1, double y1, double x2, double y2) { double vx = x2 - x1; double vy = y2 - y1; double wx = px - x1; double wy = py - y1; double c = vx*vx + vy*vy; if (c == 0) { return Math.hypot(px - x1, py - y1); } double t = (vx*wx + vy*wy) / c; if (t < 0) t = 0; else if (t > 1) t = 1; double projx = x1 + t * vx; double projy = y1 + t * vy; return Math.hypot(px - projx, py - projy); } }