Compare commits

..

6 Commits

Author SHA1 Message Date
MOISOIU Stefan-Mihai
5a884429fa bruit de perlin 2026-02-23 11:29:41 +01:00
tit-exe
3276da46d8 changement texte 2026-02-23 11:04:01 +01:00
tit-exe
e0a9de1b1c menu 2026-02-23 11:03:22 +01:00
tit-exe
095692eb0a systeme points/écran game over 2026-02-23 10:29:41 +01:00
MOISOIU Stefan-Mihai
513e414dc9 Merge branch 'main' of https://titi.koxi.nl/blodat/projet-dev 2026-02-23 10:28:11 +01:00
MOISOIU Stefan-Mihai
51decf68d0 changement physique 2026-02-23 10:28:06 +01:00
8 changed files with 496 additions and 199 deletions

View File

@@ -13,7 +13,7 @@ public class Cercle extends ObjetGraphique{ // il s'agit plutôt d'arcs de cercl
//-------------------------------------------------------------------------
// PROPRIETES
//-------------------------------------------------------------------------
protected double rayon = 30;
protected double rayon = 50;
protected double depY = 0; // déplacement
// début et fin de l'arc, en degrés
@@ -31,7 +31,7 @@ public class Cercle extends ObjetGraphique{ // il s'agit plutôt d'arcs de cercl
protected double pas = 0.2;
// Valeur de la force (norme) appliquée lorsque le joueur appuie sur up
protected double impulsion = 25;
protected double impulsion = 35;
//-------------------------------------------------------------------------

View File

@@ -1,16 +1,29 @@
package linea;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.Timer;
public class Jeu implements KeyListener, ActionListener{
public class Jeu implements KeyListener, ActionListener, MouseListener {
// -------------------------------------------------------------------------
// PROPRIETES
// -------------------------------------------------------------------------
@@ -25,18 +38,29 @@ public class Jeu implements KeyListener, ActionListener{
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();
protected Ligne lili = new Ligne(new NoiseGenerator(0));
// Timer : un objet qui émet des événements à un intervalle choisi,
// il sert à donner le pas de l'animation
protected Timer horloge;
// Une variable qui contiendra le score
protected double score=0;
protected double score = 1;
// un label qui servira à afficher le score
protected JLabel labScore;
protected int compteurFrames = 0;
protected boolean enCollision = false;
protected boolean estGameOver = false;
protected JLabel labGameOver;
protected int compteurInvincible = 0;
// menu et fenetre
protected JFrame fenetre;
protected JPanel panneauMenu;
protected JTextField champPseudo;
protected String pseudo = "";
// -------------------------------------------------------------------------
// METHODES
@@ -50,14 +74,23 @@ public class Jeu implements KeyListener, ActionListener{
labScore = new JLabel();
labScore.setForeground(Color.WHITE);
labScore.setText("<html><h3>score : 0</h3></html>");
labScore.setText("<html><h3>" + (int) score + "</h3></html>");
labScore.setBounds(20, 0, 200, 50);
ecran.add(labScore);
labGameOver = new JLabel("GAME OVER", SwingConstants.CENTER);
labGameOver.setForeground(Color.WHITE);
labGameOver.setFont(new Font("Arial", Font.BOLD, 40));
labGameOver.setBounds(0, 200, 800, 100);
labGameOver.setVisible(false);
ecran.add(labGameOver);
// ecoute les clics de souris (pour le game over)
ecran.addMouseListener(this);
ecran.traiterBoucleAnimation();
}
// -------------------------------------------------------------------------
// Méthodes qu'il faut implémenter pour être
// conforme à un KeyListener
@@ -112,7 +145,123 @@ public class Jeu implements KeyListener, ActionListener{
// -------------------------------------------------------------------------
public void demarrer() {
// Création d'une fenêtre
JFrame fenetre = new JFrame();
fenetre = new JFrame("Linea");
// on affiche le menu en premier
afficherMenu();
fenetre.setSize(800, 600);
fenetre.setResizable(false);
fenetre.setLocationRelativeTo(null); // centre la fenetre sur l'ecran
fenetre.setVisible(true);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void afficherMenu() {
panneauMenu = new JPanel();
panneauMenu.setLayout(new BoxLayout(panneauMenu, BoxLayout.Y_AXIS));
panneauMenu.setBackground(new Color(15, 15, 35));
panneauMenu.setPreferredSize(new Dimension(800, 600));
// espace en haut
panneauMenu.add(Box.createVerticalStrut(80));
// titre du jeu
JLabel titre = new JLabel("LINEA");
titre.setAlignmentX(JLabel.CENTER_ALIGNMENT);
titre.setForeground(new Color(0, 180, 255));
titre.setFont(new Font("Arial", Font.BOLD, 80));
panneauMenu.add(titre);
// petit sous-titre
JLabel sousTitre = new JLabel("esquive la ligne");
sousTitre.setAlignmentX(JLabel.CENTER_ALIGNMENT);
sousTitre.setForeground(new Color(120, 120, 160));
sousTitre.setFont(new Font("Arial", Font.PLAIN, 18));
panneauMenu.add(sousTitre);
panneauMenu.add(Box.createVerticalStrut(40));
// label pseudo
JLabel labPseudo = new JLabel("pseudo");
labPseudo.setAlignmentX(JLabel.CENTER_ALIGNMENT);
labPseudo.setForeground(new Color(180, 180, 200));
labPseudo.setFont(new Font("Arial", Font.PLAIN, 14));
panneauMenu.add(labPseudo);
panneauMenu.add(Box.createVerticalStrut(8));
// champ de texte pour le pseudo
champPseudo = new JTextField(15);
champPseudo.setText(pseudo); // garde le pseudo prérempli s'il y en a un
champPseudo.setMaximumSize(new Dimension(250, 40));
champPseudo.setFont(new Font("Arial", Font.PLAIN, 16));
champPseudo.setHorizontalAlignment(JTextField.CENTER);
champPseudo.setBackground(new Color(30, 30, 60));
champPseudo.setForeground(Color.WHITE);
champPseudo.setCaretColor(Color.WHITE);
champPseudo.setBorder(BorderFactory.createLineBorder(new Color(0, 180, 255), 2, true));
champPseudo.setAlignmentX(JTextField.CENTER_ALIGNMENT);
panneauMenu.add(champPseudo);
panneauMenu.add(Box.createVerticalStrut(40));
// bouton jouer
JButton boutonJouer = new JButton("JOUER");
styleBouton(boutonJouer, new Color(0, 130, 255));
boutonJouer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lancerPartie();
}
});
panneauMenu.add(boutonJouer);
panneauMenu.add(Box.createVerticalStrut(15));
// bouton classement
JButton boutonClassement = new JButton("CLASSEMENT");
styleBouton(boutonClassement, new Color(100, 100, 150));
boutonClassement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(fenetre, "TOP SCORES", "Classement", JOptionPane.INFORMATION_MESSAGE);
}
});
panneauMenu.add(boutonClassement);
panneauMenu.add(Box.createVerticalStrut(15));
// bouton quitter
JButton boutonQuitter = new JButton("QUITTER");
styleBouton(boutonQuitter, new Color(200, 50, 50));
boutonQuitter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
panneauMenu.add(boutonQuitter);
fenetre.setContentPane(panneauMenu);
fenetre.revalidate();
fenetre.repaint();
}
private void styleBouton(JButton btn, Color fond) {
btn.setAlignmentX(JButton.CENTER_ALIGNMENT);
btn.setFont(new Font("Arial", Font.BOLD, 18));
btn.setForeground(Color.WHITE);
btn.setBackground(fond);
btn.setFocusPainted(false);
btn.setBorderPainted(false);
btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
btn.setMaximumSize(new Dimension(200, 45));
}
private void lancerPartie() {
// on recupere le pseudo
pseudo = champPseudo.getText();
// A FAIRE :
// placer dans l'instance de l'écran tous les objets graphiques nécessaires
@@ -123,44 +272,124 @@ public class Jeu implements KeyListener, ActionListener{
demiCercleArriere.setCouleur(new Color(0.0f, 0.4f, 0.0f));
demiCercleAvant.setCouleur(new Color(0.0f, 0.5f, 0.0f));
// on indique que c'est le jeu qui traitera les appuis sur une touche
ecran.addKeyListener(this);
ecran.setFocusable(true);
// on remplace le menu par l'ecran de jeu
fenetre.setContentPane(ecran);
fenetre.pack();
fenetre.setLocation(100, 100);
fenetre.setVisible(true);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.revalidate();
fenetre.repaint();
ecran.requestFocusInWindow();
// on reinitialise les valeurs de jeu
score = 1;
compteurFrames = 0;
enCollision = false;
estGameOver = false;
compteurInvincible = 0;
labGameOver.setVisible(false);
ecran.demarrer();
// Démarrage du timer, qui rythmera l'animation
if (horloge == null) {
horloge = new Timer(40, this);
}
horloge.start();
// A FAIRE :
demiCercleArriere.setCouleur(new Color(0.8f, 0.0f, 0.0f));
// donner la couleur des 2 demi-cercles, par exemple : demiCerleArriere.setCouleur(new Color(0.8f,0.0f,0.0f));
// donner la couleur des 2 demi-cercles, par exemple :
// demiCerleArriere.setCouleur(new Color(0.8f,0.0f,0.0f));
}
// -------------------------------------------------------------------------
// Méthode appelée lorsqu'un événement timer se produit
// -------------------------------------------------------------------------
@Override
public void actionPerformed(ActionEvent e) {
// si c'est game over, on arrete juste l'animation et on attend le clic
if (estGameOver == true) {
return;
}
ecran.traiterBoucleAnimation();
score = score + 0.4;
labScore.setText("<html><h3>score : " + (int)score + "</h3></html>");
compteurFrames = compteurFrames + 1;
if (compteurFrames >= 25) {
score = score + 1;
compteurFrames = 0;
}
if (compteurInvincible < 75) {
compteurInvincible = compteurInvincible + 1;
} else {
if (demiCercleArriere.VerifierCollision(lili)) {
if (enCollision == false) {
score = score - 5;
enCollision = true;
}
} else {
enCollision = false;
}
}
if (score <= 0) {
score = 0;
estGameOver = true;
ecran.arreter();
labGameOver.setVisible(true);
}
labScore.setText("<html><h3>" + (int) score + "</h3></html>");
demiCercleArriere.ResterDansLigne(lili);
demiCercleAvant.ResterDansLigne(lili);
if (demiCercleArriere.VerifierCollision(lili))
RecommencerPartie();
}
private void RecommencerPartie(){
System.out.println("Fin de partie !");
private void retourMenu() {
// on arrete le timer du jeu
if (horloge != null) {
horloge.stop();
}
// on recrée une nouvelle ligne propre pour la prochaine partie
lili = new Ligne(new NoiseGenerator(0));
demiCercleAvant.y = 200;
demiCercleAvant.vitesse = -1.0;
demiCercleArriere.y = 200;
demiCercleArriere.vitesse = -1.0;
ecran.viderObjets();
// on retourne au menu principal
afficherMenu();
}
// -------------------------------------------------------------------------
// événements souris (pour revenir au menu apres game over)
// -------------------------------------------------------------------------
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (estGameOver == true) {
retourMenu();
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}

View File

@@ -17,15 +17,16 @@ public class Ligne extends ObjetGraphique {
protected double limiteHaut = 50;
protected double limiteBas = 550;
public Ligne() {
public Ligne(NoiseGenerator noiseGenerator) {
double x = 0;
double y = 200;
double dx, dy;
Segment s;
for (int i = 0; i < nbSegments; i++) {
dx = Math.random() * 20 + 80;
dy = Math.random() * 40 - 20;
dx = 10;
dy = noiseGenerator.noise(x / 15) * 8;
if (y + dy > limiteBas) {
dy = limiteBas - y;

View File

@@ -5,8 +5,8 @@ public class LineaAppli {
// Classe de base de l'application, rien à modifier ici
// -------------------------------------------------------------------------
public static void main(String[] arg) {
new MenuPrincipal();
Jeu jeu = new Jeu();
jeu.demarrer();
}
}

View File

@@ -1,98 +0,0 @@
package linea;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuPrincipal extends JFrame {
public MenuPrincipal() {
// Configuration de la fenêtre du menu
setTitle("LINEA - Menu Principal");
setSize(400, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // Centre la fenêtre au milieu de l'écran
setResizable(false);
// Panneau de fond (Même bleu que le jeu pour le style)
JPanel panel = new JPanel();
panel.setLayout(null); // On place les éléments manuellement
panel.setBackground(new Color(0, 73, 220));
setContentPane(panel);
// --- TITRE ---
JLabel titre = new JLabel("LINEA", SwingConstants.CENTER);
titre.setFont(new Font("Arial", Font.BOLD, 40));
titre.setForeground(Color.WHITE);
titre.setBounds(0, 50, 400, 60);
panel.add(titre);
// --- BOUTON START ---
JButton btnStart = new JButton("COMMENCER");
btnStart.setBounds(100, 160, 200, 50);
styleBouton(btnStart);
btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lancerJeu();
}
});
panel.add(btnStart);
// --- BOUTON CLASSEMENT ---
JButton btnClassement = new JButton("CLASSEMENT");
btnClassement.setBounds(100, 230, 200, 50);
styleBouton(btnClassement);
btnClassement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
afficherClassement();
}
});
panel.add(btnClassement);
// --- BOUTON LOGOUT ---
JButton btnLogout = new JButton("LOGOUT");
btnLogout.setBounds(100, 300, 200, 50);
styleBouton(btnLogout);
btnLogout.setBackground(new Color(200, 50, 50)); // Rouge pour quitter
btnLogout.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0); // Ferme tout
}
});
panel.add(btnLogout);
// Afficher la fenêtre
setVisible(true);
}
// Méthode pour lancer le jeu
private void lancerJeu() {
// On ferme le menu
this.dispose();
// On lance le jeu existant
Jeu jeu = new Jeu();
jeu.demarrer();
}
// Méthode pour afficher les classements
private void afficherClassement() {
// Comme on a retiré la BDD, on affiche une liste simulée
String message = "TOP SCORES";
JOptionPane.showMessageDialog(this, message, "Classement", JOptionPane.INFORMATION_MESSAGE);
}
// Petite méthode pour rendre les boutons jolis
private void styleBouton(JButton btn) {
btn.setFont(new Font("Arial", Font.BOLD, 16));
btn.setBackground(Color.WHITE);
btn.setForeground(Color.BLACK);
btn.setFocusPainted(false);
btn.setBorder(BorderFactory.createRaisedBevelBorder());
}
}

161
src/NoiseGenerator.java Normal file
View File

@@ -0,0 +1,161 @@
package linea;
import java.util.Random;
public class NoiseGenerator {
private double seed;
private long default_size;
private int[] p;
private int[] permutation;
public NoiseGenerator(double seed) {
this.seed = seed;
init();
}
public NoiseGenerator() {
this.seed = new Random().nextGaussian() * 255;
init();
}
private void init() {
// Initialize the permutation array.
this.p = new int[512];
this.permutation = new int[] { 151, 160, 137, 91, 90, 15, 131, 13, 201,
95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99,
37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88,
237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74,
165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111,
229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40,
244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76,
132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159,
86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250,
124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207,
206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170,
213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155,
167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113,
224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242,
193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235,
249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184,
84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236,
205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66,
215, 61, 156, 180 };
this.default_size = 35;
// Populate it
for (int i = 0; i < 256; i++) {
p[256 + i] = p[i] = permutation[i];
}
}
public void setSeed(double seed) {
this.seed = seed;
}
public double getSeed() {
return this.seed;
}
public double noise(double x, double y, double z, int size) {
double value = 0.0;
double initialSize = size;
while (size >= 1) {
value += smoothNoise((x / size), (y / size), (z / size)) * size;
size /= 2.0;
}
return value / initialSize;
}
public double noise(double x, double y, double z) {
double value = 0.0;
double size = default_size;
double initialSize = size;
while (size >= 1) {
value += smoothNoise((x / size), (y / size), (z / size)) * size;
size /= 2.0;
}
return value / initialSize;
}
public double noise(double x, double y) {
double value = 0.0;
double size = default_size;
double initialSize = size;
while (size >= 1) {
value += smoothNoise((x / size), (y / size), (0f / size)) * size;
size /= 2.0;
}
return value / initialSize;
}
public double noise(double x) {
double value = 0.0;
double size = default_size;
double initialSize = size;
while (size >= 1) {
value += smoothNoise((x / size), (0f / size), (0f / size)) * size;
size /= 2.0;
}
return value / initialSize;
}
public double smoothNoise(double x, double y, double z) {
// Offset each coordinate by the seed value
x += this.seed;
y += this.seed;
x += this.seed;
int X = (int) Math.floor(x) & 255; // FIND UNIT CUBE THAT
int Y = (int) Math.floor(y) & 255; // CONTAINS POINT.
int Z = (int) Math.floor(z) & 255;
x -= Math.floor(x); // FIND RELATIVE X,Y,Z
y -= Math.floor(y); // OF POINT IN CUBE.
z -= Math.floor(z);
double u = fade(x); // COMPUTE FADE CURVES
double v = fade(y); // FOR EACH OF X,Y,Z.
double w = fade(z);
int A = p[X] + Y;
int AA = p[A] + Z;
int AB = p[A + 1] + Z; // HASH COORDINATES OF
int B = p[X + 1] + Y;
int BA = p[B] + Z;
int BB = p[B + 1] + Z; // THE 8 CUBE CORNERS,
return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z ), // AND ADD
grad(p[BA], x - 1, y, z )), // BLENDED
lerp(u, grad(p[AB], x, y - 1, z ), // RESULTS
grad(p[BB], x - 1, y - 1, z ))),// FROM 8
lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1 ), // CORNERS
grad(p[BA + 1], x - 1, y, z - 1 )), // OF CUBE
lerp(u, grad(p[AB + 1], x, y - 1, z - 1 ),
grad(p[BB + 1], x - 1, y - 1, z - 1 ))));
}
private double fade(double t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
private double lerp(double t, double a, double b) {
return a + t * (b - a);
}
private double grad(int hash, double x, double y, double z) {
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
double u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
}

View File

@@ -24,8 +24,8 @@ public class Segment extends ObjetGraphique { // Hérite de la classe ObjetGraph
public Segment(){
x = 0;
y = 0;
xLong = 50;
yLong = 50;
xLong = 10;
yLong = 10;
}
public Segment(double xx, double yy, double xxLong, double yyLong){

View File

@@ -31,11 +31,11 @@ public class ZoneDessin extends JPanel {
public void arreter() {
estArrete = true;
}
public void demarrer() {
estArrete = false;
}
public void traiterBoucleAnimation() {
if (estArrete == true) {
return;
@@ -58,4 +58,8 @@ public class ZoneDessin extends JPanel {
obj.Afficher(g);
}
}
public void viderObjets() {
listeObjets.clear();
}
}