Compare commits
11 Commits
e93b1cfb64
...
Thibaut
| Author | SHA1 | Date | |
|---|---|---|---|
| 7dffb0fca8 | |||
|
|
f6c6c5044a | ||
| c50210db3f | |||
| e817b064e1 | |||
| 33b5683a59 | |||
| 8888b6dfb3 | |||
| 94ebb17d19 | |||
| 3232cd136f | |||
|
|
4aab505eed | ||
|
|
ec3e46cbe8 | ||
|
|
abd6ae07c8 |
10
README.md
10
README.md
@@ -1,11 +1,15 @@
|
|||||||
# Tetris
|
# Tetris
|
||||||
## Projet Informatique Encadré
|
## Projet Informatique Encadré
|
||||||
|
|
||||||
### POO - objectif de modularité
|
POO - objectif de modularité
|
||||||
|
|
||||||
|
# Diagramme activité proposé
|
||||||
|

|
||||||
|
|
||||||
|
# Diagramme des classes final
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
Liens:
|
Liens:
|
||||||
- Slides de cours: https://partage.liris.cnrs.fr/index.php/s/7ZwqDcXbFrwsLPB
|
- Slides de cours: https://partage.liris.cnrs.fr/index.php/s/7ZwqDcXbFrwsLPB
|
||||||
- Sujet du Tetris: https://partage.liris.cnrs.fr/index.php/s/wsyyzFDrRrjzCHw
|
- Sujet du Tetris: https://partage.liris.cnrs.fr/index.php/s/wsyyzFDrRrjzCHw
|
||||||
|
|
||||||

|
|
||||||
Binary file not shown.
BIN
app/bin/main/TetrisMusic.wav
Normal file
BIN
app/bin/main/TetrisMusic.wav
Normal file
Binary file not shown.
@@ -23,9 +23,6 @@ dependencies {
|
|||||||
|
|
||||||
// This dependency is used by the application.
|
// This dependency is used by the application.
|
||||||
implementation(libs.guava)
|
implementation(libs.guava)
|
||||||
|
|
||||||
// JLayer pour lire les fichiers MP3
|
|
||||||
implementation("javazoom:jlayer:1.0.1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a specific Java toolchain to ease working on different environments.
|
// Apply a specific Java toolchain to ease working on different environments.
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
/*
|
|
||||||
* This source file was generated by the Gradle 'init' task
|
|
||||||
*/
|
|
||||||
package org;
|
package org;
|
||||||
|
|
||||||
import org.Controllers.IO;
|
import org.Controllers.IO;
|
||||||
@@ -31,15 +28,10 @@ public class App {
|
|||||||
IO io = new IO(jeu);
|
IO io = new IO(jeu);
|
||||||
vueTetris.addKeyListener(io);
|
vueTetris.addKeyListener(io);
|
||||||
|
|
||||||
new TetrisBandeauControleur(vueTetris.getVueBandeauControle(), musique, grille);// Création d'un controleur de
|
new TetrisBandeauControleur(vueTetris.getVueBandeauControle(), musique, grille, jeu);// Création d'un
|
||||||
// bandeau avec la musique
|
// controleur de
|
||||||
|
// bandeau avec la
|
||||||
|
// musique
|
||||||
// instanciée
|
// instanciée
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: RESTE A IMPLEMENTER
|
|
||||||
// - rotation
|
|
||||||
// - score
|
|
||||||
// - lignes
|
|
||||||
// - menu pour fin de partie
|
|
||||||
// ext possible: conserver un historique de score dans un fichier txt ?
|
|
||||||
}
|
}
|
||||||
@@ -5,19 +5,34 @@ import java.awt.event.KeyListener;
|
|||||||
|
|
||||||
import org.Models.Direction;
|
import org.Models.Direction;
|
||||||
import org.Models.Jeu;
|
import org.Models.Jeu;
|
||||||
|
import org.Models.Orientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gère les entrées clavier pour contrôler le jeu.
|
||||||
|
*/
|
||||||
|
|
||||||
public class IO implements KeyListener {
|
public class IO implements KeyListener {
|
||||||
|
|
||||||
private Jeu jeu;
|
private Jeu jeu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un gestionnaire d'entrées clavier pour le jeu donné.
|
||||||
|
*
|
||||||
|
* @param jeu le jeu à contrôler
|
||||||
|
*/
|
||||||
public IO(Jeu jeu) {
|
public IO(Jeu jeu) {
|
||||||
this.jeu = jeu;
|
this.jeu = jeu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gère les actions à effectuer lors de l'appui sur une touche.
|
||||||
|
*
|
||||||
|
* @param e l'événement de touche pressée
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
if (jeu.getGrille().estEnPause()) {
|
if (jeu.getGrille().estEnPause()) {
|
||||||
System.err.println("Grille est en pause");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (e.getKeyCode()) {
|
switch (e.getKeyCode()) {
|
||||||
@@ -35,16 +50,35 @@ public class IO implements KeyListener {
|
|||||||
|
|
||||||
case KeyEvent.VK_SPACE:
|
case KeyEvent.VK_SPACE:
|
||||||
jeu.getGrille().deplacerPiece(Direction.TOUTENBAS);
|
jeu.getGrille().deplacerPiece(Direction.TOUTENBAS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyEvent.VK_R:
|
||||||
|
jeu.getGrille().tournerPiece(Orientation.SENSHORAIRE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyEvent.VK_E:
|
||||||
|
jeu.getGrille().tournerPiece(Orientation.SENSANTIHORAIRE);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode appelée lors de la saisie d'un caractère (non utilisée).
|
||||||
|
*
|
||||||
|
* @param e l'événement de touche tapée
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void keyTyped(KeyEvent e) {
|
public void keyTyped(KeyEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode appelée lors du relâchement d'une touche (non utilisée).
|
||||||
|
*
|
||||||
|
* @param e l'événement de touche relâchée
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,91 @@
|
|||||||
package org.Controllers;
|
package org.Controllers;
|
||||||
|
|
||||||
import org.Models.Grille;
|
import org.Models.Grille;
|
||||||
|
import org.Models.Jeu;
|
||||||
import org.Models.Musique;
|
import org.Models.Musique;
|
||||||
import org.Views.VueBandeauControle;
|
import org.Views.VueBandeauControle;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrôleur pour le bandeau de contrôle du jeu Tetris.
|
||||||
|
* Gère les actions des boutons (pause, quitter, aide, relancer) et l'état de la partie.
|
||||||
|
*/
|
||||||
public class TetrisBandeauControleur {
|
public class TetrisBandeauControleur {
|
||||||
private boolean partieEnPause = false;
|
private boolean partieEnPause = false;
|
||||||
private boolean partieTerminee = false;
|
private boolean partieTerminee = false;
|
||||||
private Musique musique;
|
private Musique musique;
|
||||||
private VueBandeauControle vueControle;
|
private VueBandeauControle vueControle;
|
||||||
private Grille grille;
|
private Grille grille;
|
||||||
|
private Jeu jeu;
|
||||||
|
|
||||||
public TetrisBandeauControleur(VueBandeauControle vueControle, Musique musique, Grille grille) {
|
/**
|
||||||
|
* Crée un contrôleur pour le bandeau de contrôle.
|
||||||
|
*
|
||||||
|
* @param vueControle la vue du bandeau de contrôle
|
||||||
|
* @param musique le gestionnaire de musique
|
||||||
|
* @param grille la grille de jeu
|
||||||
|
* @param jeu l'instance du jeu
|
||||||
|
*/
|
||||||
|
public TetrisBandeauControleur(VueBandeauControle vueControle, Musique musique, Grille grille, Jeu jeu) {
|
||||||
this.vueControle = vueControle;
|
this.vueControle = vueControle;
|
||||||
this.musique = musique;
|
this.musique = musique;
|
||||||
this.grille = grille;
|
this.grille = grille;
|
||||||
|
this.jeu = jeu;
|
||||||
// action play/pause
|
// action play/pause
|
||||||
|
// Listener pour le bouton play/pause
|
||||||
this.vueControle.getPauseButton().addActionListener(e -> switchPlayPause());
|
this.vueControle.getPauseButton().addActionListener(e -> switchPlayPause());
|
||||||
|
// Listener pour le bouton quitter
|
||||||
this.vueControle.getQuitterButton().addActionListener(e -> {
|
this.vueControle.getQuitterButton().addActionListener(e -> {
|
||||||
System.out.println("Fermeture de l'application...");
|
System.out.println("Fermeture de l'application...");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
|
// Listener pour le bouton aide
|
||||||
|
this.vueControle.getAideButton().addActionListener(e -> afficherAide());
|
||||||
|
// Listener pour le bouton recommencer
|
||||||
|
this.vueControle.getRelancerButton().addActionListener(e -> {
|
||||||
|
this.jeu.reinitialiserPartie();
|
||||||
|
vueControle.getPauseButton().setText("PAUSE");
|
||||||
|
partieEnPause = false;
|
||||||
|
partieTerminee = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bascule l'état de la partie entre pause et reprise.
|
||||||
|
* Met à jour la grille, la musique et le texte du bouton pause.
|
||||||
|
*/
|
||||||
public void switchPlayPause() {
|
public void switchPlayPause() {
|
||||||
if (partieTerminee) {
|
if (partieTerminee) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
partieEnPause = !partieEnPause;
|
partieEnPause = !partieEnPause;
|
||||||
grille.setEnPause(partieEnPause);
|
grille.setEnPause(partieEnPause);
|
||||||
|
grille.setEnPause(partieEnPause);
|
||||||
musique.basculePlayPause();
|
musique.basculePlayPause();
|
||||||
vueControle.getPauseButton().setText(partieEnPause ? "PLAY" : "PAUSE");
|
vueControle.getPauseButton().setText(partieEnPause ? "PLAY" : "PAUSE");
|
||||||
System.out.println(partieEnPause ? "Partie en pause" : "Partie en cours");
|
System.out.println(partieEnPause ? "Partie en pause" : "Partie en cours");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPartieTerminee() {
|
/**
|
||||||
partieTerminee = true;
|
* Affiche une page d'aide avec les commandes du jeu.
|
||||||
musique.arreterMusique();
|
* Met la partie en pause pendant l'affichage de l'aide.
|
||||||
vueControle.getPauseButton().setEnabled(false);
|
*/
|
||||||
System.out.println("Partie terminée");
|
public void afficherAide() {
|
||||||
|
String messageAide = "Utilisez les flèches du clavier pour déplacer la pièce courante :\n" +
|
||||||
|
"Flèche gauche : Déplacer à gauche\n" +
|
||||||
|
"Flèche droite : Déplacer à droite\n" +
|
||||||
|
"Flèche bas : Accélérer la chute\n" +
|
||||||
|
"R : Faire pivoter la pièce sens horaire\n" +
|
||||||
|
"E : Faire pivoter la pièce sens anti horaire\n" +
|
||||||
|
"Espace : Hard drop\n";
|
||||||
|
if (!grille.estEnPause()) {
|
||||||
|
grille.setEnPause(true);
|
||||||
|
musique.basculePlayPause();
|
||||||
|
JOptionPane.showMessageDialog(vueControle, messageAide, "Aide", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
grille.setEnPause(false);
|
||||||
|
musique.basculePlayPause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
/**
|
||||||
|
* Enumère les directions possibles pour le déplacement d'une pièce dans le jeu Tetris.
|
||||||
|
*/
|
||||||
public enum Direction {
|
public enum Direction {
|
||||||
BAS,
|
BAS,
|
||||||
GAUCHE,
|
GAUCHE,
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uniquement afin de se servir d'une paire de coordonées.
|
||||||
|
*/
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la grille de jeu du Tetris, gère l'état des cases, la pièce courante,
|
||||||
|
* le score, la suppression des lignes et les déplacements/rotations des pièces.
|
||||||
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class Grille extends Observable { // TODO: ?? implements Runnable {
|
public class Grille extends Observable {
|
||||||
private boolean[][] grille;
|
private boolean[][] grille;
|
||||||
public int nbLignes;
|
public int nbLignes;
|
||||||
public int nbColonnes;
|
public int nbColonnes;
|
||||||
@@ -16,6 +24,15 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
private int pieceCouranteY;
|
private int pieceCouranteY;
|
||||||
private boolean enPause = false;
|
private boolean enPause = false;
|
||||||
|
|
||||||
|
private int score = 0;
|
||||||
|
private int nbLignesSupprimees = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle grille de jeu avec le nombre de lignes et de colonnes spécifié.
|
||||||
|
*
|
||||||
|
* @param nbLignes nombre de lignes de la grille
|
||||||
|
* @param nbColonnes nombre de colonnes de la grille
|
||||||
|
*/
|
||||||
public Grille(int nbLignes, int nbColonnes) {
|
public Grille(int nbLignes, int nbColonnes) {
|
||||||
this.nbLignes = nbLignes;
|
this.nbLignes = nbLignes;
|
||||||
this.nbColonnes = nbColonnes;
|
this.nbColonnes = nbColonnes;
|
||||||
@@ -23,6 +40,9 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
initGrille();
|
initGrille();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise toutes les cases de la grille à vide (false).
|
||||||
|
*/
|
||||||
public void initGrille() {
|
public void initGrille() {
|
||||||
for (int i = 0; i < nbLignes; i++) {
|
for (int i = 0; i < nbLignes; i++) {
|
||||||
for (int j = 0; j < nbColonnes; j++) {
|
for (int j = 0; j < nbColonnes; j++) {
|
||||||
@@ -31,6 +51,13 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifie l'état d'une case de la grille.
|
||||||
|
*
|
||||||
|
* @param i indice de ligne
|
||||||
|
* @param j indice de colonne
|
||||||
|
* @param value true si la case est occupée, false sinon
|
||||||
|
*/
|
||||||
public void setCase(int i, int j, boolean value) {
|
public void setCase(int i, int j, boolean value) {
|
||||||
if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
|
if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
|
||||||
this.grille[i][j] = value;
|
this.grille[i][j] = value;
|
||||||
@@ -39,6 +66,13 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne l'état d'une case de la grille.
|
||||||
|
*
|
||||||
|
* @param i indice de ligne
|
||||||
|
* @param j indice de colonne
|
||||||
|
* @return true si la case est occupée, false sinon
|
||||||
|
*/
|
||||||
public boolean getCase(int i, int j) {
|
public boolean getCase(int i, int j) {
|
||||||
if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
|
if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
|
||||||
return this.grille[i][j];
|
return this.grille[i][j];
|
||||||
@@ -46,10 +80,20 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la pièce courante.
|
||||||
|
*
|
||||||
|
* @return la pièce courante
|
||||||
|
*/
|
||||||
public PieceCourante getPieceCourante() {
|
public PieceCourante getPieceCourante() {
|
||||||
return pieceCourante;
|
return pieceCourante;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit la pièce courante et la place en haut de la grille.
|
||||||
|
*
|
||||||
|
* @param pieceCourante la nouvelle pièce courante
|
||||||
|
*/
|
||||||
public void setPieceCourante(PieceCourante pieceCourante) {
|
public void setPieceCourante(PieceCourante pieceCourante) {
|
||||||
this.pieceCourante = pieceCourante;
|
this.pieceCourante = pieceCourante;
|
||||||
this.pieceCouranteX = 3;
|
this.pieceCouranteX = 3;
|
||||||
@@ -58,14 +102,29 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la position X de la pièce courante.
|
||||||
|
*
|
||||||
|
* @return position X
|
||||||
|
*/
|
||||||
public int getPieceCouranteX() {
|
public int getPieceCouranteX() {
|
||||||
return pieceCouranteX;
|
return pieceCouranteX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la position X de la pièce courante.
|
||||||
|
*
|
||||||
|
* @return position X
|
||||||
|
*/
|
||||||
public int getPieceCouranteY() {
|
public int getPieceCouranteY() {
|
||||||
return pieceCouranteY;
|
return pieceCouranteY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déplace la pièce courante dans la direction spécifiée si possible.
|
||||||
|
*
|
||||||
|
* @param direction direction du déplacement
|
||||||
|
*/
|
||||||
public void deplacerPiece(Direction direction) {
|
public void deplacerPiece(Direction direction) {
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
@@ -93,6 +152,9 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déplace la pièce courante d'une case vers le bas.
|
||||||
|
*/
|
||||||
private void deplacerPieceBas() {
|
private void deplacerPieceBas() {
|
||||||
pieceCouranteY++;
|
pieceCouranteY++;
|
||||||
|
|
||||||
@@ -100,6 +162,9 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déplace la pièce courante d'une case vers la gauche.
|
||||||
|
*/
|
||||||
private void deplacerPieceGauche() {
|
private void deplacerPieceGauche() {
|
||||||
pieceCouranteX--;
|
pieceCouranteX--;
|
||||||
|
|
||||||
@@ -107,6 +172,9 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déplace la pièce courante d'une case vers la droite.
|
||||||
|
*/
|
||||||
private void deplacerPieceDroite() {
|
private void deplacerPieceDroite() {
|
||||||
pieceCouranteX++;
|
pieceCouranteX++;
|
||||||
|
|
||||||
@@ -114,43 +182,38 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fait descendre la pièce courante jusqu'à ce qu'elle ne puisse plus descendre.
|
||||||
|
*/
|
||||||
private void deplacerPieceToutEnBas() {
|
private void deplacerPieceToutEnBas() {
|
||||||
while (peuxBouger(Direction.BAS, this.motifPieceCouranteColoriee())) {
|
while (peuxBouger(Direction.BAS, this.motifPieceCouranteColoriee())) {
|
||||||
deplacerPieceBas();
|
deplacerPieceBas();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : ENLEVER ?
|
/**
|
||||||
// public int getMaxYPieceCouranteColoree(List<Point> motifPieceColoree) {
|
* Retourne le nombre de lignes de la grille.
|
||||||
// int maxY = 0;
|
*
|
||||||
// for (Point caseColoree : motifPieceColoree) {
|
* @return nombre de lignes
|
||||||
// if (caseColoree.y > maxY) {
|
*/
|
||||||
// maxY = caseColoree.y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return maxY;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public int getMaxXPieceCouranteColoree(List<Point> motifPieceColoree) {
|
|
||||||
// int maxX = 0;
|
|
||||||
// for (Point caseColoree : motifPieceColoree) {
|
|
||||||
// if (caseColoree.x > maxX) {
|
|
||||||
// maxX = caseColoree.x;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return maxX;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public int getNbLignes() {
|
public int getNbLignes() {
|
||||||
return nbLignes;
|
return nbLignes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le nombre de colonnes de la grille.
|
||||||
|
*
|
||||||
|
* @return nombre de colonnes
|
||||||
|
*/
|
||||||
public int getNbColonnes() {
|
public int getNbColonnes() {
|
||||||
return nbColonnes;
|
return nbColonnes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la liste des points occupés par la pièce courante dans la grille.
|
||||||
|
*
|
||||||
|
* @return liste des points colorés
|
||||||
|
*/
|
||||||
public List<Point> motifPieceCouranteColoriee() {
|
public List<Point> motifPieceCouranteColoriee() {
|
||||||
List<Point> casesColores = new ArrayList<>();
|
List<Point> casesColores = new ArrayList<>();
|
||||||
|
|
||||||
@@ -166,6 +229,13 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
return casesColores;
|
return casesColores;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la pièce peut bouger dans la direction donnée.
|
||||||
|
*
|
||||||
|
* @param direction direction du déplacement
|
||||||
|
* @param motif motif de la pièce
|
||||||
|
* @return true si le déplacement est possible, false sinon
|
||||||
|
*/
|
||||||
public boolean peuxBouger(Direction direction, List<Point> motif) {
|
public boolean peuxBouger(Direction direction, List<Point> motif) {
|
||||||
int deltaX = 0;
|
int deltaX = 0;
|
||||||
int deltaY = 0;
|
int deltaY = 0;
|
||||||
@@ -186,35 +256,37 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Point caseColoree : motif) {
|
List<Point> nouvellePosition = calculerNouvellePosition(motif, deltaX, deltaY);
|
||||||
int newX = caseColoree.x + deltaX;
|
return positionValide(nouvellePosition);
|
||||||
int newY = caseColoree.y + deltaY;
|
|
||||||
|
|
||||||
if (newX < 0 || newX >= nbColonnes || newY < 0 || newY >= nbLignes) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grille[newY][newX]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la matrice représentant la grille.
|
||||||
|
*
|
||||||
|
* @return matrice de booleans
|
||||||
|
*/
|
||||||
public boolean[][] getGrille() {
|
public boolean[][] getGrille() {
|
||||||
return grille;
|
return grille;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixe la pièce courante sur la grille et vérifie la suppression de lignes.
|
||||||
|
*/
|
||||||
public void fixerPiece() {
|
public void fixerPiece() {
|
||||||
for (Point caseColoree : motifPieceCouranteColoriee()) {
|
for (Point caseColoree : motifPieceCouranteColoriee()) {
|
||||||
setCase(caseColoree.y, caseColoree.x, true);
|
setCase(caseColoree.y, caseColoree.x, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.println("post fixage de piece");
|
|
||||||
verifierEtSupprimerLignesSiBesoin();
|
verifierEtSupprimerLignesSiBesoin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la pièce courante doit être fixée (ne peut plus descendre).
|
||||||
|
*
|
||||||
|
* @return true si la pièce doit être fixée, false sinon
|
||||||
|
*/
|
||||||
public boolean doitFixerPiece() {
|
public boolean doitFixerPiece() {
|
||||||
if (!peuxBouger(Direction.BAS, this.motifPieceCouranteColoriee())) {
|
if (!peuxBouger(Direction.BAS, this.motifPieceCouranteColoriee())) {
|
||||||
return true;
|
return true;
|
||||||
@@ -223,32 +295,30 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met la grille en pause ou la reprend.
|
||||||
|
*
|
||||||
|
* @param enPause true pour mettre en pause, false pour reprendre
|
||||||
|
*/
|
||||||
public void setEnPause(boolean enPause) {
|
public void setEnPause(boolean enPause) {
|
||||||
this.enPause = enPause;
|
this.enPause = enPause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indique si la grille est en pause.
|
||||||
|
*
|
||||||
|
* @return true si en pause, false sinon
|
||||||
|
*/
|
||||||
public boolean estEnPause() {
|
public boolean estEnPause() {
|
||||||
return enPause;
|
return enPause;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void verifierEtSupprimerLignesSiBesoin() {
|
/**
|
||||||
|
* Vérifie et supprime les lignes complètes si besoin, met à jour le score.
|
||||||
// for (int i = nbLignes - 1; i > 0; i--) {
|
*/
|
||||||
// boolean ligneSupprimable = true;
|
|
||||||
|
|
||||||
// for (int j = 0; j < nbColonnes; j++) {
|
|
||||||
// if (!this.grille[i][j]) {
|
|
||||||
// ligneSupprimable = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (ligneSupprimable) {
|
|
||||||
// supprimerLigne(i);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void verifierEtSupprimerLignesSiBesoin() {
|
public void verifierEtSupprimerLignesSiBesoin() {
|
||||||
|
int tmpNbLignesSupprimees = 0;
|
||||||
|
System.out.println("Debut uppression d'une ligne......");
|
||||||
for (int i = nbLignes - 1; i >= 0; i--) {
|
for (int i = nbLignes - 1; i >= 0; i--) {
|
||||||
boolean ligneSupprimable = true;
|
boolean ligneSupprimable = true;
|
||||||
|
|
||||||
@@ -261,30 +331,71 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
|
|
||||||
if (ligneSupprimable) {
|
if (ligneSupprimable) {
|
||||||
supprimerLigne(i);
|
supprimerLigne(i);
|
||||||
|
nbLignesSupprimees += 1;
|
||||||
i++;
|
i++;
|
||||||
|
tmpNbLignesSupprimees++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println(tmpNbLignesSupprimees + " Lignes supprimées");
|
||||||
|
switch (tmpNbLignesSupprimees) {
|
||||||
|
case 1:
|
||||||
|
score += 100;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
score += 300;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
score += 500;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
score += 800;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // TODO : EUHHHHHHHHHH JE CROIS PAS que ça marche comme ça c'est pas en mode
|
/**
|
||||||
// gravité récursive, c'est juste tout descend de n lignes cassées
|
* Retourne le score actuel.
|
||||||
// // dès qu'on a fixe la pièce courante on verifie le nombre de lignes a
|
*
|
||||||
// supprimes
|
* @return score
|
||||||
// // dans la grille
|
*/
|
||||||
|
public int getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
// // ->
|
/**
|
||||||
// // faire tomber JUSQU'EN bas la ligne X au dessus des n lines supprimes
|
* Définit le score.
|
||||||
// // PAR CONTRE faire tomber de n lignes toutes les lignes au dessus de X.
|
*
|
||||||
// while (peuxBouger(Direction.BAS, getLignePoints(i))) {
|
* @param score nouveau score
|
||||||
// System.err.println("testtttttttttt descnete");
|
*/
|
||||||
// descendreLigne(i - 1);
|
public void setScore(int score) {
|
||||||
// }
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
// // for (int j = i - 2; j > 0; j--) {
|
/**
|
||||||
// // descendreLigne(j);
|
* Retourne le nombre total de lignes supprimées.
|
||||||
// // }
|
*
|
||||||
// }
|
* @return nombre de lignes supprimées
|
||||||
|
*/
|
||||||
|
public int getNbLignesSupprimees() {
|
||||||
|
return nbLignesSupprimees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le nombre de lignes supprimées.
|
||||||
|
*
|
||||||
|
* @param nbLignesSupprimees nouveau nombre de lignes supprimées
|
||||||
|
*/
|
||||||
|
public void setNbLignesSupprimees(int nbLignesSupprimees) {
|
||||||
|
this.nbLignesSupprimees = nbLignesSupprimees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supprime la ligne d'indice i et fait descendre les lignes au-dessus.
|
||||||
|
*
|
||||||
|
* @param i indice de la ligne à supprimer
|
||||||
|
*/
|
||||||
public void supprimerLigne(int i) {
|
public void supprimerLigne(int i) {
|
||||||
for (int ligne = i; ligne > 0; ligne--) {
|
for (int ligne = i; ligne > 0; ligne--) {
|
||||||
for (int j = 0; j < nbColonnes; j++) {
|
for (int j = 0; j < nbColonnes; j++) {
|
||||||
@@ -300,6 +411,12 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la liste des points d'une ligne donnée.
|
||||||
|
*
|
||||||
|
* @param i indice de la ligne
|
||||||
|
* @return liste des points de la ligne
|
||||||
|
*/
|
||||||
public List<Point> getLignePoints(int i) {
|
public List<Point> getLignePoints(int i) {
|
||||||
List<Point> coordonnesCase = new ArrayList<>();
|
List<Point> coordonnesCase = new ArrayList<>();
|
||||||
|
|
||||||
@@ -310,6 +427,11 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
return coordonnesCase;
|
return coordonnesCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fait descendre une ligne d'une position.
|
||||||
|
*
|
||||||
|
* @param i indice de la ligne à descendre
|
||||||
|
*/
|
||||||
public void descendreLigne(int i) {
|
public void descendreLigne(int i) {
|
||||||
for (int j = 0; j < nbColonnes; j++) {
|
for (int j = 0; j < nbColonnes; j++) {
|
||||||
List<Point> coordonnesCase = new ArrayList<>();
|
List<Point> coordonnesCase = new ArrayList<>();
|
||||||
@@ -322,4 +444,126 @@ public class Grille extends Observable { // TODO: ?? implements Runnable {
|
|||||||
this.setCase(i, j, false);
|
this.setCase(i, j, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tente de tourner la pièce courante dans l'orientation donnée.
|
||||||
|
*
|
||||||
|
* @param orientation sens de rotation
|
||||||
|
*/
|
||||||
|
public void tournerPiece(Orientation orientation) {
|
||||||
|
if (peuxTournerPiece(orientation)) {
|
||||||
|
boolean[][] motif = pieceCourante.getMotif();
|
||||||
|
boolean[][] nouveauMotif;
|
||||||
|
|
||||||
|
if (orientation == Orientation.SENSHORAIRE) {
|
||||||
|
nouveauMotif = PieceCourante.rotationHoraire(motif);
|
||||||
|
} else {
|
||||||
|
nouveauMotif = PieceCourante.rotationAntiHoraire(motif);
|
||||||
|
}
|
||||||
|
|
||||||
|
pieceCourante.setMotif(nouveauMotif);
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la pièce courante peut tourner dans l'orientation donnée.
|
||||||
|
*
|
||||||
|
* @param orientation sens de rotation
|
||||||
|
* @return true si la rotation est possible, false sinon
|
||||||
|
*/
|
||||||
|
public boolean peuxTournerPiece(Orientation orientation) {
|
||||||
|
List<Point> positionApresRotation = calculerPositionApresRotation(orientation);
|
||||||
|
return positionValide(positionApresRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule la position de la pièce après rotation.
|
||||||
|
*
|
||||||
|
* @param orientation sens de rotation
|
||||||
|
* @return liste des points après rotation
|
||||||
|
*/
|
||||||
|
private List<Point> calculerPositionApresRotation(Orientation orientation) {
|
||||||
|
List<Point> nouvellePosition = new ArrayList<>();
|
||||||
|
boolean[][] motifActuel = pieceCourante.getMotif();
|
||||||
|
boolean[][] motifTourne;
|
||||||
|
|
||||||
|
boolean[][] motifCopie = new boolean[motifActuel.length][motifActuel[0].length];
|
||||||
|
for (int i = 0; i < motifActuel.length; i++) {
|
||||||
|
for (int j = 0; j < motifActuel[i].length; j++) {
|
||||||
|
motifCopie[i][j] = motifActuel[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orientation == Orientation.SENSHORAIRE) {
|
||||||
|
motifTourne = PieceCourante.rotationHoraire(motifCopie);
|
||||||
|
} else {
|
||||||
|
motifTourne = PieceCourante.rotationAntiHoraire(motifCopie);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < motifTourne.length; i++) {
|
||||||
|
for (int j = 0; j < motifTourne[i].length; j++) {
|
||||||
|
if (motifTourne[i][j]) {
|
||||||
|
nouvellePosition.add(new Point(pieceCouranteX + j, pieceCouranteY + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nouvellePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la position donnée est valide (dans la grille et non occupée).
|
||||||
|
*
|
||||||
|
* @param points liste des points à vérifier
|
||||||
|
* @return true si la position est valide, false sinon
|
||||||
|
*/
|
||||||
|
public boolean positionValide(List<Point> points) {
|
||||||
|
for (Point point : points) {
|
||||||
|
if (point.x < 0 || point.x >= nbColonnes || point.y < 0 || point.y >= nbLignes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grille[point.y][point.x]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule la nouvelle position d'une liste de points après déplacement.
|
||||||
|
*
|
||||||
|
* @param points liste de points d'origine
|
||||||
|
* @param deltaX déplacement en X
|
||||||
|
* @param deltaY déplacement en Y
|
||||||
|
* @return nouvelle liste de points déplacés
|
||||||
|
*/
|
||||||
|
private List<Point> calculerNouvellePosition(List<Point> points, int deltaX, int deltaY) {
|
||||||
|
List<Point> nouvellePosPoints = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Point point : points) {
|
||||||
|
nouvellePosPoints.add(new Point(point.x + deltaX, point.y + deltaY));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nouvellePosPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Réinitialise la grille, le score, le nombre de lignes supprimées et la pièce courante.
|
||||||
|
*/
|
||||||
|
public void reinitialiserGrille() {
|
||||||
|
initGrille();
|
||||||
|
score = 0;
|
||||||
|
nbLignesSupprimees = 0;
|
||||||
|
pieceCourante = null;
|
||||||
|
pieceCouranteX = 3;
|
||||||
|
pieceCouranteY = 0;
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uniquement afin de se servir d'une paire de coordonées.
|
||||||
|
*/
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@@ -12,6 +16,10 @@ import org.Models.Pieces.PieceS;
|
|||||||
import org.Models.Pieces.PieceT;
|
import org.Models.Pieces.PieceT;
|
||||||
import org.Models.Pieces.PieceZ;
|
import org.Models.Pieces.PieceZ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gère la logique principale du jeu Tetris, y compris la gestion de la grille,
|
||||||
|
* des pièces, de la musique, de l'ordonnancement et de l'état de la partie.
|
||||||
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class Jeu extends Observable implements Runnable {
|
public class Jeu extends Observable implements Runnable {
|
||||||
private Grille grille;
|
private Grille grille;
|
||||||
@@ -21,58 +29,66 @@ public class Jeu extends Observable implements Runnable {
|
|||||||
private PieceCourante pieceSuivante;
|
private PieceCourante pieceSuivante;
|
||||||
private int pieceSuivanteX;
|
private int pieceSuivanteX;
|
||||||
private int pieceSuivanteY;
|
private int pieceSuivanteY;
|
||||||
|
|
||||||
public boolean jeuEnCours = true;
|
public boolean jeuEnCours = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle instance du jeu avec la grille et la musique spécifiées.
|
||||||
|
*
|
||||||
|
* @param grille la grille de jeu
|
||||||
|
* @param musique le gestionnaire de musique
|
||||||
|
*/
|
||||||
public Jeu(Grille grille, Musique musique) {
|
public Jeu(Grille grille, Musique musique) {
|
||||||
System.err.println("init jeu");
|
|
||||||
this.grille = grille;
|
this.grille = grille;
|
||||||
this.musique = musique;
|
this.musique = musique;
|
||||||
|
this.musique = musique;
|
||||||
|
|
||||||
System.err.println("init nouvelle piece courante");
|
|
||||||
this.grille.setPieceCourante(getNouvellePiece());
|
this.grille.setPieceCourante(getNouvellePiece());
|
||||||
System.err.println("init nouvelle piece suivante");
|
|
||||||
this.pieceSuivante = getNouvellePiece();
|
this.pieceSuivante = getNouvellePiece();
|
||||||
|
|
||||||
this.ordonnanceur = new Ordonnanceur(this, 1000);
|
this.ordonnanceur = new Ordonnanceur(this, 1000);
|
||||||
this.ordonnanceur.start();
|
this.ordonnanceur.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Génère et retourne une nouvelle pièce aléatoire.
|
||||||
|
*
|
||||||
|
* @return une nouvelle pièce courante
|
||||||
|
*/
|
||||||
private PieceCourante getNouvellePiece() {
|
private PieceCourante getNouvellePiece() {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int randomiiii = random.nextInt(6);
|
int randomiiii = random.nextInt(7);
|
||||||
System.err.println("randomiiiii : " + randomiiii);
|
|
||||||
|
|
||||||
PieceCourante nouvellePiece;
|
PieceCourante nouvellePiece;
|
||||||
switch (randomiiii) {
|
switch (randomiiii) {
|
||||||
case 0:
|
case 0:
|
||||||
nouvellePiece = new PieceI();
|
nouvellePiece = new PieceI();
|
||||||
System.err.println("piece I");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
nouvellePiece = new PieceL();
|
nouvellePiece = new PieceL();
|
||||||
System.err.println("piece L");
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
nouvellePiece = new PieceJ();
|
nouvellePiece = new PieceJ();
|
||||||
System.err.println("piece J");
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
nouvellePiece = new PieceO();
|
nouvellePiece = new PieceO();
|
||||||
System.err.println("piece O");
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
nouvellePiece = new PieceS();
|
nouvellePiece = new PieceS();
|
||||||
System.err.println("piece S");
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
nouvellePiece = new PieceT();
|
nouvellePiece = new PieceT();
|
||||||
System.err.println("piece T");
|
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
nouvellePiece = new PieceZ();
|
nouvellePiece = new PieceZ();
|
||||||
System.err.println("piece Z");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nouvellePiece = new PieceL();
|
nouvellePiece = new PieceL();
|
||||||
@@ -81,6 +97,11 @@ public class Jeu extends Observable implements Runnable {
|
|||||||
return nouvellePiece;
|
return nouvellePiece;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la pièce suivante.
|
||||||
|
*
|
||||||
|
* @return la pièce suivante
|
||||||
|
*/
|
||||||
public PieceCourante getPieceSuivante() {
|
public PieceCourante getPieceSuivante() {
|
||||||
return pieceSuivante;
|
return pieceSuivante;
|
||||||
}
|
}
|
||||||
@@ -93,13 +114,24 @@ public class Jeu extends Observable implements Runnable {
|
|||||||
return pieceSuivanteY;
|
return pieceSuivanteY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la grille de jeu.
|
||||||
|
*
|
||||||
|
* @return la grille
|
||||||
|
*/
|
||||||
public Grille getGrille() {
|
public Grille getGrille() {
|
||||||
return grille;
|
return grille;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la partie est terminée (collision en haut de la grille).
|
||||||
|
*
|
||||||
|
* @return true si la partie est terminée, false sinon
|
||||||
|
*/
|
||||||
public boolean estFinPartie() {
|
public boolean estFinPartie() {
|
||||||
for (Point caseColoree : this.grille.motifPieceCouranteColoriee()) {
|
for (Point caseColoree : this.grille.motifPieceCouranteColoriee()) {
|
||||||
if (this.grille.getCase(caseColoree.y, caseColoree.x)) {
|
if (this.grille.getCase(caseColoree.y, caseColoree.x)) {
|
||||||
|
finPartie();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,6 +139,9 @@ public class Jeu extends Observable implements Runnable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Termine la partie, arrête l'ordonnanceur et la musique.
|
||||||
|
*/
|
||||||
public void finPartie() {
|
public void finPartie() {
|
||||||
this.jeuEnCours = false;
|
this.jeuEnCours = false;
|
||||||
ordonnanceur.interrupt();
|
ordonnanceur.interrupt();
|
||||||
@@ -118,9 +153,50 @@ public class Jeu extends Observable implements Runnable {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Réinitialise tous les paramètres de la partie pour relancer le jeu.
|
||||||
|
*/
|
||||||
|
public void reinitialiserPartie() {
|
||||||
|
if (ordonnanceur != null) {
|
||||||
|
ordonnanceur.stopOrdonnanceur();
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.grille.initGrille();
|
||||||
|
this.grille.setPieceCourante(getNouvellePiece());
|
||||||
|
this.grille.setScore(0);
|
||||||
|
this.grille.setNbLignesSupprimees(0);
|
||||||
|
this.pieceSuivante = getNouvellePiece();
|
||||||
|
this.jeuEnCours = true;
|
||||||
|
|
||||||
|
this.ordonnanceur = new Ordonnanceur(this, 1000);
|
||||||
|
this.ordonnanceur.start();
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pauseJeu() {
|
||||||
|
grille.setEnPause(true);
|
||||||
|
if (musique != null) {
|
||||||
|
musique.basculePlayPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reprendreJeu() {
|
||||||
|
grille.setEnPause(false);
|
||||||
|
if (musique != null) {
|
||||||
|
musique.basculePlayPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode exécutée périodiquement par l'ordonnanceur pour faire avancer le jeu.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// TODO: game logic here
|
|
||||||
if (!jeuEnCours || grille.estEnPause()) {
|
if (!jeuEnCours || grille.estEnPause()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,106 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
|
||||||
import javazoom.jl.player.Player;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class Musique extends Thread {
|
import javax.sound.sampled.AudioInputStream;
|
||||||
private Player player;
|
import javax.sound.sampled.AudioSystem;
|
||||||
private volatile boolean stop = false;
|
import javax.sound.sampled.Clip;
|
||||||
private volatile boolean enPause = false;
|
import javax.sound.sampled.LineEvent;
|
||||||
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
|
||||||
public void run() {
|
/**
|
||||||
|
* Classe Musique n'étant pas purement données métier, donc n'aurait normalement
|
||||||
|
* sa place dans le package Models. Il faudrait l'externaliser. Par manque de
|
||||||
|
* temps, suite à notre discussion, nous avons décidé de laisser la musique ici.
|
||||||
|
*/
|
||||||
|
public class Musique {
|
||||||
|
private Clip clip;
|
||||||
|
private long clipPositionPause = 0;
|
||||||
|
private boolean estEnPause = false;
|
||||||
|
private boolean estArrete = false;
|
||||||
|
private boolean estInitialise = false;
|
||||||
|
|
||||||
|
public Musique() {
|
||||||
|
initialiserClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise le clip audio à partir du fichier TetrisMusic.wav.
|
||||||
|
*/
|
||||||
|
private void initialiserClip() {
|
||||||
try {
|
try {
|
||||||
while (!stop) {
|
InputStream audioSrc = getClass().getResourceAsStream("/TetrisMusic.wav");
|
||||||
if (!enPause) {
|
if (audioSrc == null) {
|
||||||
try (InputStream musique = getClass().getResourceAsStream("/TetrisMusic.mp3")) {
|
|
||||||
if (musique == null) {
|
|
||||||
System.err.println("Erreur : le fichier musique.mp3 est introuvable.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BufferedInputStream buffer = new BufferedInputStream(musique);
|
|
||||||
this.player = new Player(buffer);
|
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioSrc);
|
||||||
System.out.println("Lecture de la musique...");
|
clip = AudioSystem.getClip();
|
||||||
player.play();
|
clip.open(audioStream);
|
||||||
} catch (Exception e) {
|
estInitialise = true;
|
||||||
System.err.println("Erreur lors de la lecture de la musique : " + e.getMessage());
|
|
||||||
|
clip.addLineListener(event -> {
|
||||||
|
if (event.getType() == LineEvent.Type.STOP && !estEnPause && !estArrete) {
|
||||||
|
clip.setFramePosition(0);
|
||||||
|
clip.start();
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
Thread.sleep(1000); // Attendre 1 seconde avant de vérifier à nouveau
|
|
||||||
}
|
System.out.println("Clip audio initialisé avec succès.");
|
||||||
}
|
} catch (UnsupportedAudioFileException e) {
|
||||||
} catch (InterruptedException e) {
|
|
||||||
System.err.println("Musique interrompue : " + e.getMessage());
|
} catch (LineUnavailableException e) {
|
||||||
}
|
|
||||||
System.out.println("Fin du thread de musique.");
|
} catch (IOException e) {
|
||||||
}
|
|
||||||
public void basculePlayPause() {
|
|
||||||
enPause = !enPause;
|
|
||||||
if (enPause && player != null) {
|
|
||||||
System.out.println("Musique en pause.");
|
|
||||||
player.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joue la musique à partir du début.
|
||||||
|
*/
|
||||||
|
public void start() {
|
||||||
|
if (estInitialise && !estArrete) {
|
||||||
|
clip.setFramePosition(0);
|
||||||
|
clip.start();
|
||||||
|
estEnPause = false;
|
||||||
|
System.out.println("Lecture de la musique...");
|
||||||
|
}
|
||||||
|
System.out.println("Fin de musique.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* met en pause la musique. rejoue la musique à partir de la position actuelle.
|
||||||
|
*/
|
||||||
|
public void basculePlayPause() {
|
||||||
|
if (!estInitialise || estArrete)
|
||||||
|
return;
|
||||||
|
|
||||||
|
estEnPause = !estEnPause;
|
||||||
|
|
||||||
|
if (estEnPause) {
|
||||||
|
clipPositionPause = clip.getMicrosecondPosition();
|
||||||
|
clip.stop();
|
||||||
|
System.out.println("Musique en pause à la position " + clipPositionPause + " µs");
|
||||||
|
} else {
|
||||||
|
clip.setMicrosecondPosition(clipPositionPause);
|
||||||
|
clip.start();
|
||||||
|
System.out.println("Musique reprise à la position " + clipPositionPause + " µs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arrête la musique et libère les ressources.
|
||||||
|
*/
|
||||||
public void arreterMusique() {
|
public void arreterMusique() {
|
||||||
|
if (estInitialise) {
|
||||||
|
estArrete = true;
|
||||||
|
clip.stop();
|
||||||
|
clip.close();
|
||||||
System.out.println("Arrêt de la musique.");
|
System.out.println("Arrêt de la musique.");
|
||||||
stop = true;
|
|
||||||
if (player != null) {
|
|
||||||
player.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,33 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
/**
|
||||||
|
* Ordonnanceur exécute périodiquement une tâche {@link Runnable} dans un thread séparé.
|
||||||
|
*/
|
||||||
public class Ordonnanceur extends Thread {
|
public class Ordonnanceur extends Thread {
|
||||||
|
|
||||||
Runnable runnable;
|
Runnable runnable;
|
||||||
long pause;
|
long pause;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un nouvel ordonnanceur.
|
||||||
|
*
|
||||||
|
* @param runnable la tâche à exécuter périodiquement
|
||||||
|
* @param pause la durée de pause entre chaque exécution (en millisecondes)
|
||||||
|
*/
|
||||||
public Ordonnanceur(Runnable runnable, long pause) {
|
public Ordonnanceur(Runnable runnable, long pause) {
|
||||||
this.runnable = runnable;
|
this.runnable = runnable;
|
||||||
this.pause = pause;
|
this.pause = pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arrête l'ordonnanceur en interrompant le thread.
|
||||||
|
*/
|
||||||
public void stopOrdonnanceur() {
|
public void stopOrdonnanceur() {
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exécute la tâche périodiquement tant que le thread n'est pas interrompu.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
|||||||
8
app/src/main/java/org/Models/Orientation.java
Normal file
8
app/src/main/java/org/Models/Orientation.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package org.Models;
|
||||||
|
/**
|
||||||
|
* Enumère les orientations possibles pour la rotation d'une pièce dans le jeu Tetris.
|
||||||
|
*/
|
||||||
|
public enum Orientation {
|
||||||
|
SENSHORAIRE,
|
||||||
|
SENSANTIHORAIRE,
|
||||||
|
}
|
||||||
@@ -1,5 +1,37 @@
|
|||||||
package org.Models;
|
package org.Models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface représentant une pièce courante du jeu Tetris.
|
||||||
|
* Définit les méthodes pour obtenir et définir le motif de la pièce.
|
||||||
|
*/
|
||||||
public interface PieceCourante {
|
public interface PieceCourante {
|
||||||
abstract public boolean[][] getMotif();
|
abstract public boolean[][] getMotif();
|
||||||
|
|
||||||
|
abstract public void setMotif(boolean[][] motif);
|
||||||
|
|
||||||
|
static boolean[][] rotationHoraire(boolean[][] motif) {
|
||||||
|
int taille = motif.length;
|
||||||
|
boolean[][] resultat = new boolean[taille][taille];
|
||||||
|
|
||||||
|
for (int i = 0; i < taille; i++) {
|
||||||
|
for (int j = 0; j < taille; j++) {
|
||||||
|
resultat[j][taille - 1 - i] = motif[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultat;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean[][] rotationAntiHoraire(boolean[][] motif) {
|
||||||
|
int taille = motif.length;
|
||||||
|
boolean[][] resultat = new boolean[taille][taille];
|
||||||
|
|
||||||
|
for (int i = 0; i < taille; i++) {
|
||||||
|
for (int j = 0; j < taille; j++) {
|
||||||
|
resultat[taille - 1 - j][i] = motif[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,17 @@ package org.Models.Pieces;
|
|||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la pièce I du Tetris.
|
||||||
|
* La pièce I est une ligne de 4 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceI implements PieceCourante {
|
public class PieceI implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[4][4];
|
private boolean[][] motif = new boolean[4][4];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce I avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceI() {
|
public PieceI() {
|
||||||
motif[0][1] = true;
|
motif[0][1] = true;
|
||||||
motif[1][1] = true;
|
motif[1][1] = true;
|
||||||
@@ -13,8 +20,23 @@ private boolean[][] motif = new boolean[4][4];
|
|||||||
motif[3][1] = true;
|
motif[3][1] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce I.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce I.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,41 @@ package org.Models.Pieces;
|
|||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la pièce J du Tetris.
|
||||||
|
* La pièce J est une ligne de 3 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceJ implements PieceCourante {
|
public class PieceJ implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[3][3];
|
private boolean[][] motif = new boolean[3][3];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce J avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceJ() {
|
public PieceJ() {
|
||||||
motif[0][2] = true;
|
motif[0][1] = true;
|
||||||
motif[1][2] = true;
|
motif[1][1] = true;
|
||||||
motif[2][2] = true;
|
|
||||||
motif[2][1] = true;
|
motif[2][1] = true;
|
||||||
|
motif[2][0] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce J.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce J.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,41 @@ package org.Models.Pieces;
|
|||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la pièce L du Tetris.
|
||||||
|
* La pièce L est une ligne de 3 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceL implements PieceCourante {
|
public class PieceL implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[3][3];
|
private boolean[][] motif = new boolean[3][3];
|
||||||
|
|
||||||
public PieceL(){
|
/**
|
||||||
motif[0][0] = true;
|
* Crée une nouvelle pièce L avec son motif initial.
|
||||||
motif[1][0] = true;
|
*/
|
||||||
motif[2][0] = true;
|
public PieceL() {
|
||||||
|
motif[0][1] = true;
|
||||||
|
motif[1][1] = true;
|
||||||
motif[2][1] = true;
|
motif[2][1] = true;
|
||||||
|
motif[2][2] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce L.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce L.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,17 @@ package org.Models.Pieces;
|
|||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la pièce O du Tetris.
|
||||||
|
* La pièce O est une ligne de 4 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceO implements PieceCourante {
|
public class PieceO implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[4][4];
|
private boolean[][] motif = new boolean[4][4];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce O avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceO() {
|
public PieceO() {
|
||||||
motif[1][1] = true;
|
motif[1][1] = true;
|
||||||
motif[1][2] = true;
|
motif[1][2] = true;
|
||||||
@@ -12,8 +20,23 @@ private boolean[][] motif = new boolean[4][4];
|
|||||||
motif[2][2] = true;
|
motif[2][2] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce O.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce O.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
package org.Models.Pieces;
|
package org.Models.Pieces;
|
||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
/**
|
||||||
|
* Représente la pièce S du Tetris.
|
||||||
|
* La pièce S est une ligne de 3 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceS implements PieceCourante {
|
public class PieceS implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[3][3];
|
private boolean[][] motif = new boolean[3][3];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce S avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceS() {
|
public PieceS() {
|
||||||
motif[0][1] = true;
|
motif[0][1] = true;
|
||||||
motif[1][1] = true;
|
motif[1][1] = true;
|
||||||
@@ -13,8 +19,23 @@ private boolean[][] motif = new boolean[3][3];
|
|||||||
motif[2][2] = true;
|
motif[2][2] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce S.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce S.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,17 @@ package org.Models.Pieces;
|
|||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente la pièce T du Tetris.
|
||||||
|
* La pièce S est une ligne de 3 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceT implements PieceCourante {
|
public class PieceT implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[3][3];
|
private boolean[][] motif = new boolean[3][3];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce T avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceT() {
|
public PieceT() {
|
||||||
motif[0][1] = true;
|
motif[0][1] = true;
|
||||||
motif[1][1] = true;
|
motif[1][1] = true;
|
||||||
@@ -13,8 +20,23 @@ private boolean[][] motif = new boolean[3][3];
|
|||||||
motif[1][2] = true;
|
motif[1][2] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce T.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce T.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package org.Models.Pieces;
|
package org.Models.Pieces;
|
||||||
|
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
/**
|
||||||
|
* Représente la pièce Z du Tetris.
|
||||||
|
* La pièce S est une ligne de 3 blocs disposés verticalement par défaut.
|
||||||
|
*/
|
||||||
public class PieceZ implements PieceCourante {
|
public class PieceZ implements PieceCourante {
|
||||||
|
|
||||||
private boolean[][] motif = new boolean[3][3];
|
private boolean[][] motif = new boolean[3][3];
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle pièce Z avec son motif initial.
|
||||||
|
*/
|
||||||
public PieceZ() {
|
public PieceZ() {
|
||||||
motif[0][2] = true;
|
motif[0][2] = true;
|
||||||
motif[1][2] = true;
|
motif[1][2] = true;
|
||||||
@@ -13,8 +18,23 @@ private boolean[][] motif = new boolean[3][3];
|
|||||||
motif[2][1] = true;
|
motif[2][1] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le motif actuel de la pièce Z.
|
||||||
|
*
|
||||||
|
* @return le motif sous forme de matrice de booleans
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean[][] getMotif() {
|
public boolean[][] getMotif() {
|
||||||
return motif;
|
return motif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le motif de la pièce Z.
|
||||||
|
*
|
||||||
|
* @param motif la nouvelle matrice de booleans représentant le motif
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMotif(boolean[][] motif) {
|
||||||
|
this.motif = motif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
package org.Models;
|
package org.Views;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
|
/**
|
||||||
|
* LayoutManager personnalisé pour disposer les composants dans une grille carrée,
|
||||||
|
* centrée dans le conteneur parent, avec des cases de taille égale.
|
||||||
|
*/
|
||||||
public class GridLayoutCarre implements LayoutManager {
|
public class GridLayoutCarre implements LayoutManager {
|
||||||
private int lignes;
|
private int lignes;
|
||||||
private int colonnes;
|
private int colonnes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un nouveau GridLayoutCarre avec le nombre de lignes et de colonnes spécifié.
|
||||||
|
*
|
||||||
|
* @param lignes nombre de lignes
|
||||||
|
* @param colonnes nombre de colonnes
|
||||||
|
*/
|
||||||
public GridLayoutCarre(int lignes, int colonnes) {
|
public GridLayoutCarre(int lignes, int colonnes) {
|
||||||
this.lignes = lignes;
|
this.lignes = lignes;
|
||||||
this.colonnes = colonnes;
|
this.colonnes = colonnes;
|
||||||
@@ -29,11 +42,17 @@ public class GridLayoutCarre implements LayoutManager {
|
|||||||
return parent.getMinimumSize();
|
return parent.getMinimumSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispose les composants enfants dans une grille carrée centrée,
|
||||||
|
* chaque case ayant la même taille.
|
||||||
|
*
|
||||||
|
* @param parent le conteneur parent
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void layoutContainer(Container parent) {
|
public void layoutContainer(Container parent) {
|
||||||
int largeur = parent.getWidth();
|
int largeur = parent.getWidth();
|
||||||
int hauteur = parent.getHeight();
|
int hauteur = parent.getHeight();
|
||||||
int tailleCase= Math.min(largeur / colonnes, hauteur / lignes);
|
int tailleCase = Math.min(largeur / colonnes, hauteur / lignes);
|
||||||
int offSetX = (largeur - tailleCase * colonnes) / 2;
|
int offSetX = (largeur - tailleCase * colonnes) / 2;
|
||||||
int offSetY = (hauteur - tailleCase * lignes) / 2;
|
int offSetY = (hauteur - tailleCase * lignes) / 2;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@@ -1,24 +1,40 @@
|
|||||||
package org.Views;
|
package org.Views;
|
||||||
|
|
||||||
import org.Models.GridLayoutCarre;
|
|
||||||
import org.Models.Jeu;
|
import org.Models.Jeu;
|
||||||
import org.Models.PieceCourante;
|
import org.Models.PieceCourante;
|
||||||
|
|
||||||
import javax.swing.*;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.*;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Insets;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class VueBandeauControle extends JPanel implements Observer {
|
public class VueBandeauControle extends JPanel implements Observer {
|
||||||
private JLabel scoreLabel;
|
private JLabel scoreLabel;
|
||||||
private JPanel nextPiecePanel;
|
private JPanel nextPiecePanel;
|
||||||
private JButton pauseButton;
|
private JButton pauseButton;
|
||||||
|
private JButton aideButton;
|
||||||
private JPanel[][] caseNextPiece = new JPanel[4][4];
|
private JPanel[][] caseNextPiece = new JPanel[4][4];
|
||||||
private JLabel nbLigneLabel;
|
private JLabel nbLigneLabel;
|
||||||
private JButton quitterButton;
|
private JButton quitterButton;
|
||||||
private Jeu jeu;
|
private Jeu jeu;
|
||||||
|
private JButton relancerButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle instance de VueBandeauControle.
|
||||||
|
* @param jeu
|
||||||
|
*/
|
||||||
public VueBandeauControle(Jeu jeu) {
|
public VueBandeauControle(Jeu jeu) {
|
||||||
this.jeu = jeu;
|
this.jeu = jeu;
|
||||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
@@ -26,13 +42,13 @@ public class VueBandeauControle extends JPanel implements Observer {
|
|||||||
// setPreferredSize();
|
// setPreferredSize();
|
||||||
|
|
||||||
// SCORE
|
// SCORE
|
||||||
scoreLabel = new JLabel("SCORE : 0");
|
scoreLabel = new JLabel("SCORE : " + jeu.getGrille().getScore());
|
||||||
scoreLabel.setForeground(Color.white);
|
scoreLabel.setForeground(Color.white);
|
||||||
scoreLabel.setFont(new Font("Arial", Font.PLAIN, 16));
|
scoreLabel.setFont(new Font("Arial", Font.PLAIN, 16));
|
||||||
scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
// NB LIGNE
|
// NB LIGNE
|
||||||
nbLigneLabel = new JLabel("LIGNES : 0");
|
nbLigneLabel = new JLabel("LIGNES : " + jeu.getGrille().getNbLignesSupprimees());
|
||||||
nbLigneLabel.setForeground(Color.white);
|
nbLigneLabel.setForeground(Color.white);
|
||||||
nbLigneLabel.setFont(new Font("Arial", Font.PLAIN, 16));
|
nbLigneLabel.setFont(new Font("Arial", Font.PLAIN, 16));
|
||||||
nbLigneLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
nbLigneLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
@@ -52,14 +68,33 @@ public class VueBandeauControle extends JPanel implements Observer {
|
|||||||
pauseButton.setMargin(margeBoutton);
|
pauseButton.setMargin(margeBoutton);
|
||||||
quitterButton.setPreferredSize(buttonSize);
|
quitterButton.setPreferredSize(buttonSize);
|
||||||
quitterButton.setMargin(margeBoutton);
|
quitterButton.setMargin(margeBoutton);
|
||||||
JPanel boutonsPanel = new JPanel();
|
JPanel hautBoutonsPanel = new JPanel();
|
||||||
boutonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 0));
|
// boutonsPanel.setLayout(new BoxLayout(boutonsPanel, BoxLayout.X_AXIS));
|
||||||
boutonsPanel.setOpaque(false);
|
hautBoutonsPanel.setOpaque(false);
|
||||||
boutonsPanel.add(pauseButton);
|
hautBoutonsPanel.add(pauseButton);
|
||||||
boutonsPanel.add(quitterButton);
|
hautBoutonsPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||||
|
hautBoutonsPanel.add(quitterButton);
|
||||||
pauseButton.setFocusable(false);
|
pauseButton.setFocusable(false);
|
||||||
quitterButton.setFocusable(false);
|
quitterButton.setFocusable(false);
|
||||||
|
|
||||||
|
// Relancer button
|
||||||
|
relancerButton = new JButton("RESTART");
|
||||||
|
relancerButton.setPreferredSize(buttonSize);
|
||||||
|
relancerButton.setMargin(margeBoutton);
|
||||||
|
relancerButton.setFocusable(false);
|
||||||
|
|
||||||
|
// AIDE BUTTON
|
||||||
|
aideButton = new JButton("?");
|
||||||
|
aideButton.setToolTipText("AFFICHER L'AIDE");
|
||||||
|
aideButton.setPreferredSize(new Dimension(45, 20));
|
||||||
|
aideButton.setFocusable(false);
|
||||||
|
|
||||||
|
JPanel footerPanel = new JPanel(new BorderLayout());
|
||||||
|
footerPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
|
||||||
|
footerPanel.setOpaque(false);
|
||||||
|
footerPanel.add(relancerButton, BorderLayout.WEST);
|
||||||
|
footerPanel.add(aideButton, BorderLayout.EAST);
|
||||||
|
|
||||||
add(Box.createVerticalStrut(20));
|
add(Box.createVerticalStrut(20));
|
||||||
add(scoreLabel);
|
add(scoreLabel);
|
||||||
add(Box.createVerticalStrut(20));
|
add(Box.createVerticalStrut(20));
|
||||||
@@ -67,28 +102,50 @@ public class VueBandeauControle extends JPanel implements Observer {
|
|||||||
add(Box.createVerticalStrut(20));
|
add(Box.createVerticalStrut(20));
|
||||||
add(nextPiecePanel);
|
add(nextPiecePanel);
|
||||||
add(Box.createVerticalStrut(20));
|
add(Box.createVerticalStrut(20));
|
||||||
add(boutonsPanel);
|
add(hautBoutonsPanel);
|
||||||
|
add(Box.createVerticalGlue()); // force le JPanel à prendre toute la hauteur
|
||||||
|
add(footerPanel);
|
||||||
|
|
||||||
// setVisible(true);
|
// setVisible(true);
|
||||||
jeu.addObserver(this);
|
jeu.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met à jour le score affiché dans le bandeau de contrôle.
|
||||||
|
* @param score
|
||||||
|
*/
|
||||||
public void setScore(int score) {
|
public void setScore(int score) {
|
||||||
scoreLabel.setText("Score: " + score);
|
scoreLabel.setText("Score: " + score);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le bouton de pause.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public JButton getPauseButton() {
|
public JButton getPauseButton() {
|
||||||
return pauseButton;
|
return pauseButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le bouton de quitter.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public JButton getQuitterButton() {
|
public JButton getQuitterButton() {
|
||||||
return quitterButton;
|
return quitterButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le panneau de la prochaine pièce.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public JPanel getNextPiecePanel() {
|
public JPanel getNextPiecePanel() {
|
||||||
return nextPiecePanel;
|
return nextPiecePanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le bouton de relancer.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private void initierNextPiecePanel() {
|
private void initierNextPiecePanel() {
|
||||||
nextPiecePanel.removeAll();
|
nextPiecePanel.removeAll();
|
||||||
nextPiecePanel.setLayout(new GridLayoutCarre(4, 4));
|
nextPiecePanel.setLayout(new GridLayoutCarre(4, 4));
|
||||||
@@ -109,6 +166,10 @@ public class VueBandeauControle extends JPanel implements Observer {
|
|||||||
nextPiecePanel.repaint();
|
nextPiecePanel.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affiche la prochaine pièce dans le panneau de la prochaine pièce.
|
||||||
|
* @param piece
|
||||||
|
*/
|
||||||
public void afficherPieceSuivante(PieceCourante piece) {
|
public void afficherPieceSuivante(PieceCourante piece) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
@@ -129,12 +190,33 @@ public class VueBandeauControle extends JPanel implements Observer {
|
|||||||
nextPiecePanel.repaint();
|
nextPiecePanel.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le bouton d'aide.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public JButton getAideButton() {
|
||||||
|
return aideButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le bouton de relancer.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public JButton getRelancerButton() {
|
||||||
|
return relancerButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le label du nombre de lignes.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (o instanceof Jeu) {
|
if (o instanceof Jeu) {
|
||||||
afficherPieceSuivante(jeu.getPieceSuivante());
|
afficherPieceSuivante(jeu.getPieceSuivante());
|
||||||
|
setScore(jeu.getGrille().getScore());
|
||||||
// TODO : setScore ??
|
nbLigneLabel.setText("LIGNES : " + jeu.getGrille().getNbLignesSupprimees());
|
||||||
|
scoreLabel.setText("SCORE : " + jeu.getGrille().getScore());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
55
app/src/main/java/org/Views/VueGameOver.java
Normal file
55
app/src/main/java/org/Views/VueGameOver.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package org.Views;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fenêtre affichée à la fin de la partie, indiquant le score et proposant
|
||||||
|
* de quitter ou de rejouer.
|
||||||
|
*/
|
||||||
|
public class VueGameOver extends JFrame {
|
||||||
|
private JButton quitterButton;
|
||||||
|
private JButton rejouerButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une nouvelle fenêtre de fin de partie.
|
||||||
|
*
|
||||||
|
* @param score le score obtenu par le joueur
|
||||||
|
* @param quitterListener action à effectuer lors du clic sur "Quitter"
|
||||||
|
* @param rejouerListener action à effectuer lors du clic sur "Rejouer"
|
||||||
|
*/
|
||||||
|
public VueGameOver(int score, ActionListener quitterListener, Runnable rejouerListener) {
|
||||||
|
setTitle("FIN DE PARTIE");
|
||||||
|
setSize(400, 400);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
// Fenetre de fin de partie
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new BorderLayout());
|
||||||
|
// Texte de fin de partie
|
||||||
|
JLabel messageFin = new JLabel("GAME OVER !", SwingConstants.CENTER);
|
||||||
|
messageFin.setFont(new Font("Arial", Font.BOLD, 32));
|
||||||
|
panel.add(messageFin, BorderLayout.NORTH);
|
||||||
|
// Texte de score
|
||||||
|
JLabel messageScore = new JLabel("Votre score : " + score, SwingConstants.CENTER);
|
||||||
|
messageScore.setFont(new Font("Arial", Font.PLAIN, 24));
|
||||||
|
panel.add(messageScore, BorderLayout.CENTER);
|
||||||
|
// Boutons
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
quitterButton = new JButton("Quitter");
|
||||||
|
rejouerButton = new JButton("Rejouer");
|
||||||
|
|
||||||
|
// mise en forme boutons
|
||||||
|
quitterButton.addActionListener(quitterListener);
|
||||||
|
rejouerButton.addActionListener(e -> {
|
||||||
|
dispose();
|
||||||
|
rejouerListener.run();
|
||||||
|
});
|
||||||
|
buttonPanel.add(quitterButton);
|
||||||
|
buttonPanel.add(rejouerButton);
|
||||||
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
||||||
|
setContentPane(panel);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,22 @@
|
|||||||
package org.Views;
|
package org.Views;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import org.Models.*;
|
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import org.Models.Grille;
|
||||||
|
import org.Models.Jeu;
|
||||||
|
import org.Models.Ordonnanceur;
|
||||||
|
import org.Models.PieceCourante;
|
||||||
|
/**
|
||||||
|
* Vue graphique de la grille de jeu Tetris.
|
||||||
|
* Affiche l'état de la grille, la pièce courante et gère la mise à jour de l'affichage.
|
||||||
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class VueGrille extends JPanel implements Observer, Runnable {
|
public class VueGrille extends JPanel implements Observer, Runnable {
|
||||||
private JPanel grillePanel;
|
private JPanel grillePanel;
|
||||||
@@ -24,11 +31,19 @@ public class VueGrille extends JPanel implements Observer, Runnable {
|
|||||||
private int nbColonnes;
|
private int nbColonnes;
|
||||||
private JPanel[][] casesGrille;
|
private JPanel[][] casesGrille;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit la vue de la grille à partir du modèle de grille et du jeu.
|
||||||
|
*
|
||||||
|
* @param grille le modèle de la grille
|
||||||
|
* @param jeu le modèle du jeu
|
||||||
|
*/
|
||||||
public VueGrille(Grille grille, Jeu jeu) {
|
public VueGrille(Grille grille, Jeu jeu) {
|
||||||
this.grille = grille;
|
this.grille = grille;
|
||||||
this.jeu = jeu;
|
this.jeu = jeu;
|
||||||
this.nbLignes = grille.getNbLignes();
|
this.nbLignes = grille.getNbLignes();
|
||||||
this.nbColonnes = grille.getNbColonnes();
|
this.nbColonnes = grille.getNbColonnes();
|
||||||
|
this.nbLignes = grille.getNbLignes();
|
||||||
|
this.nbColonnes = grille.getNbColonnes();
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
initialiserVueGrille();
|
initialiserVueGrille();
|
||||||
|
|
||||||
@@ -39,6 +54,10 @@ public class VueGrille extends JPanel implements Observer, Runnable {
|
|||||||
ordonnanceur.start();
|
ordonnanceur.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne les cases de la grille pour qu'elles restent carrées
|
||||||
|
* lors du redimensionnement du panneau.
|
||||||
|
*/
|
||||||
public void resizeCases() {
|
public void resizeCases() {
|
||||||
int largeurPanel = grillePanel.getWidth();
|
int largeurPanel = grillePanel.getWidth();
|
||||||
int hauteurPanel = grillePanel.getHeight();
|
int hauteurPanel = grillePanel.getHeight();
|
||||||
@@ -63,6 +82,9 @@ public class VueGrille extends JPanel implements Observer, Runnable {
|
|||||||
grillePanel.repaint();
|
grillePanel.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise l'affichage de la grille et crée les cases graphiques.
|
||||||
|
*/
|
||||||
private void initialiserVueGrille() {
|
private void initialiserVueGrille() {
|
||||||
grillePanel = new JPanel(new GridLayoutCarre(nbLignes, nbColonnes)); // pour que les cases soient carrés
|
grillePanel = new JPanel(new GridLayoutCarre(nbLignes, nbColonnes)); // pour que les cases soient carrés
|
||||||
add(grillePanel, BorderLayout.CENTER);
|
add(grillePanel, BorderLayout.CENTER);
|
||||||
@@ -83,6 +105,9 @@ public class VueGrille extends JPanel implements Observer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met à jour l'affichage de la grille et de la pièce courante.
|
||||||
|
*/
|
||||||
public synchronized void updateGrille() {
|
public synchronized void updateGrille() {
|
||||||
for (int i = 0; i < nbLignes; i++) {
|
for (int i = 0; i < nbLignes; i++) {
|
||||||
for (int j = 0; j < nbColonnes; j++) {
|
for (int j = 0; j < nbColonnes; j++) {
|
||||||
@@ -122,26 +147,27 @@ public class VueGrille extends JPanel implements Observer, Runnable {
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afficherFinPartie() {
|
|
||||||
System.err.println("FIN PARTIE"); // TODO : gerer affichage ?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * Met à jour la vue de la grille lorsque l'état de la grille change.
|
* * Met à jour la vue de la grille lorsque l'état de la grille change.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (o instanceof Grille) {
|
if (o instanceof Grille) {
|
||||||
updateGrille();
|
updateGrille();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o instanceof Jeu && !afficherFenetreFinPartie) {
|
if (o instanceof Jeu) {
|
||||||
if (!this.jeu.jeuEnCours) {
|
Jeu jeu = (Jeu) o;
|
||||||
|
if (!jeu.jeuEnCours && !afficherFenetreFinPartie) {
|
||||||
afficherFenetreFinPartie = true;
|
afficherFenetreFinPartie = true;
|
||||||
afficherFinPartie();
|
new VueGameOver(
|
||||||
}
|
jeu.getGrille().getScore(),
|
||||||
|
e -> System.exit(0),
|
||||||
|
() -> jeu.reinitialiserPartie()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * Met à jour la vue de la grille périodiquement selon l'ordonnaceur.
|
* * Met à jour la vue de la grille périodiquement selon l'ordonnaceur.
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
package org.Views;
|
package org.Views;
|
||||||
|
|
||||||
import org.Models.*;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
import javax.swing.*;
|
import java.awt.Toolkit;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ComponentAdapter;
|
import java.awt.event.ComponentAdapter;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import org.Models.Grille;
|
||||||
|
import org.Models.Jeu;
|
||||||
|
/**
|
||||||
|
* Fenêtre principale du jeu Tetris.
|
||||||
|
* Affiche la grille de jeu et le bandeau de contrôle.
|
||||||
|
*/
|
||||||
public class VueTetris extends JFrame {
|
public class VueTetris extends JFrame {
|
||||||
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
public static double tailleJFrameX = screenSize.getHeight() / 2;
|
public static double tailleJFrameX = screenSize.getHeight() / 2;
|
||||||
@@ -14,9 +21,19 @@ public class VueTetris extends JFrame {
|
|||||||
private VueGrille vueGrille;
|
private VueGrille vueGrille;
|
||||||
private VueBandeauControle vueControle;
|
private VueBandeauControle vueControle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit la fenêtre principale du jeu Tetris.
|
||||||
|
*
|
||||||
|
* @param grille le modèle de la grille
|
||||||
|
* @param jeu le modèle du jeu
|
||||||
|
*/
|
||||||
public VueTetris(Grille grille, Jeu jeu) {
|
public VueTetris(Grille grille, Jeu jeu) {
|
||||||
super("Tetris");
|
super("Tetris");
|
||||||
|
|
||||||
|
this.vueGrille = new VueGrille(grille, jeu);
|
||||||
|
this.vueControle = new VueBandeauControle(jeu);
|
||||||
|
// TetrisBandeauControleur controleur = new
|
||||||
|
// TetrisBandeauControleur(vueControle);
|
||||||
this.vueGrille = new VueGrille(grille, jeu);
|
this.vueGrille = new VueGrille(grille, jeu);
|
||||||
this.vueControle = new VueBandeauControle(jeu);
|
this.vueControle = new VueBandeauControle(jeu);
|
||||||
// TetrisBandeauControleur controleur = new
|
// TetrisBandeauControleur controleur = new
|
||||||
@@ -39,12 +56,26 @@ public class VueTetris extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// listener permettanbt de redimensionner les cases de la grille
|
||||||
|
addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
vueGrille.resizeCases();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
vueGrille.resizeCases();
|
vueGrille.resizeCases();
|
||||||
|
vueGrille.resizeCases();
|
||||||
|
|
||||||
vueControle.afficherPieceSuivante(jeu.getPieceSuivante());
|
vueControle.afficherPieceSuivante(jeu.getPieceSuivante());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la vue du bandeau de contrôle.
|
||||||
|
*
|
||||||
|
* @return la vue du bandeau de contrôle
|
||||||
|
*/
|
||||||
public VueBandeauControle getVueBandeauControle() {
|
public VueBandeauControle getVueBandeauControle() {
|
||||||
return this.vueControle;
|
return this.vueControle;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
BIN
app/src/main/resources/TetrisMusic.wav
Normal file
BIN
app/src/main/resources/TetrisMusic.wav
Normal file
Binary file not shown.
1
readme_files/classDiagram.svg
Normal file
1
readme_files/classDiagram.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 214 KiB |
Reference in New Issue
Block a user