Tetris LIF13 Printemps 2014 SAAKYAN Aram, FAURE Adrien
Transcription
Tetris LIF13 Printemps 2014 SAAKYAN Aram, FAURE Adrien
Tetris LIF13 Printemps 2014 SAAKYAN Aram, FAURE Adrien Table des matières 1 Présentation du projet 1.1 Description . . . . . . . 1.2 Objectifs . . . . . . . . . 1.3 Choix de développement 1.4 Difficultés rencontrées . 1.5 Liste des fonctionnalités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 2 3 3 2 Diagrammes UML 2.1 Diagramme de classe du modèle . . . 2.2 Diagramme de séquence d’une partie 2.3 Diagramme de cas d’utilisation . . . 2.4 Diagramme de séquence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 5 6 . . . . . . . . . . . . . . . . . . . . 3 Conclusion . . . . . . . . . . 7 1 Chapitre 1 Présentation du projet 1.1 Description En 1985 Alexey Pazhitnov, s’inspira du casse-tête appelé pentomino pour inventer le célèbre Tetris. Notre projet reprend les fondamentaux de ce jeu, tout en ajoutant quelques features modernes. Le jeu consiste à diriger une pièce (aussi appelée tetromino) en mouvement constant vers le bas dans une grille de jeu. Le tetromino peut être tourné (à 90°) ou déplacé (à gauche ou à droite) par le joueur. Le but du jeu étant de remplir des lignes de la grille en posant les tetrominos, afin d’augmenter son score. Le jeu s’arrête si on ne peut plus insérer de pièce en haut de la grille. 1.2 Objectifs Le projet nous demandait de réaliser un tetris en Langage Java, respectant le modèle Objet et implémentant le design-pattern MVC (Model-View-Controler). 1.3 Choix de développement Afin de respecter au mieux le modèle objet, nos classes sont des héritages de classe directement fournis par java.util, par exemple nos pieces sont des extends de LinkedList, notre vue est un extends de JFrame, ainsi nous manipulons directement nos classes selon le modèle objet. Le but du jeu est de remplir des lignes pour les supprimer et augmenter son score, nous avons donc pensé à un moyen de mettre à jour la grille de jeu facilement. Ainsi celle-ci est implementé par une liste de lignes. Ce choix nous permet de faire, avec peu de calcul une mise à jour, et de plus uniquement quand c’est nécessaire. Plusieurs améliorations ont été apporté au tetris, afin d’améliorer la durée de vie et le plaisir de jeu. Ces améliorations ont été choisi parmi les features les plus célèbres de tetris, notamment le ghost, l’affichage de la pièce suivante, ainsi que la possibilité de verrouiller une pièce pour la réutiliser plus tard. 2 1.4 Difficultés rencontrées La plus grande difficulté de ce projet, a été la structuration MVC de la façon la plus générique possible. En effet, même si java propose beaucoup de solutions, notamment la mise en place facile du pattern Observable/Observer utilisé entre le modèle et la vue. Ainsi que l’interface Listener permettant au contrôleur de s’enregistrer au près de la vue. Malheureusement, malgré ces solutions, la vue et le/les contrôleur(s) ne sont pas totalement indépendants. Même si le modèle, quand à lui, est une entité souveraine. Les rotations avec des pièces ayant une coordonnée en [x=0] présentaient une source d’erreur. Pour palier à ce problème, la largeur de la grille a été agrandi de un et toutes les lignes sont remplies en [x=0] mais ne sont pas affichées. Ainsi les rotations sont possibles de partout sur la grille. Le mode torus, a été implémenté en surchargeant quelques fonctions (notament les fonctions de collisions et de déplacements) malheureusement, ce mode rend les calculs de rotations beaucoup plus difficile. Le projet à donc été avorté, même si il est possible de l’activer en modifiant le code. 1.5 Liste des fonctionnalités – Possibilité de lancer la partie et de mettre le jeu en pause. – Utilisation des touches directionnelles pour deplacer la pièce à droite et à gauche. – Touche directionnelle bas pour accélérer la vitesse de la pièce courante. – Touche directionnelle haut pour faire une rotation de la pièce à 90° dans le sens des aiguilles d’une montre. – Touche espace pour poser la pièce courante. – Affichage d’un fantome qui renseigne l’emplacement de la pièce si on la laisse tomber (peut être enlevé dans le menu). – Affichage d’aucune à trois pièces suivantes (option à définir dans le menu). – Animation de fin quand la partie est finie. – Augmentation de la vitesse de jeu à mesure que le joueur complète des lignes (cf : niveau de jeu). – Possibilité de consulter son score dans la partie, de plus le score augmente plus fortement selon le nombre de lignes complétées d’un seul coup et le niveau actuel. – Possibilité de sauvegarder la pièce courante (case hold en haut à gauche) et de la ressortir à un meilleur moment en utilisant la touche entrée. 3 Chapitre 2 Diagrammes UML 2.1 Diagramme de classe du modèle Voici le diagramme de classe de notre modèle, il représente la partie la plus indépendante de notre projet. La classe principale Jeu, est la classe maîtresse qui met en relation chacunes des instances nécessaires et les manipule afin de gérer les collisions entre la grille et la pièce courante, les calcules de score, et met à jour les lignes pleines si nécessaire. Il est également capable d’envoyer différentes notifications grâce à l’héritage Observable, et possède sa propre fonction run() executable dans un thread grâce au type de l’interface Runnable. Diagramme de classe du model Model <<interface>> Runnable LinkedList<Point> <<abstract>> Thread Observable 1 Piece +Piece(t:Forme,p:Point) +construirePiece(p:Point): void +rotationPiece(): void +getNextPosRotation(): LinkedList<Point> +deplacer(m:Mouvement): void +getPosition(): LinkedList<Point> +getNextPosition(m:Mouvement): LinkedList<Point> +getNextPosPiece(m:Mouvement): Piece <<enumeration>> Forme -id: int -couleur: Color +getRandom(): Forme <<enumeration>> Mouvement Grille Jeu $ COS_: double $ SIN_: double -center: Point -forme: Forme 1,n -refresh: boolean -HAUTEUR: int -LARGEUR: int -score: int -intLevel: int -hold: int -nombresLignesCompletees: int -play: boolean -pause: boolean -accelerer: boolean -swap: boolean -fluidite: boolean 1 +Jeu() +lancerPartie(): void +nouvellePartie(): void +run(): void +pieceCouranteNew(): boolean +tenirPiece(): void +vitesse(): void +vitesse (x:int): void +resume(): void +pause(): void +poserPiece(): void +ViderLignePleine(): int +ajouterPieceCouranteGrille(): void +<<synchronized>> deplacerCourante(m:Mouvement): boolean +<<synchronized>> tournerCourante(): boolean +fonctionScore(x:int): void +getThread(): Thread +getGrilleLargeur(): int +getGrilleHauteur(): int +getGrille(): Grille +getFormeCourante(): Forme +getPosCourante(): LinkedList<Point> +getPieceCourante(): Piece +getPieceHold(): Piece +getPause(): boolean +getScore(): int +<<synchronized>> setPause(b:boolean): void +getListeSuivante(): LinkedList<Piece> +getPlay(): boolean +setPlay(b:boolean): void +setAcceleration(b:boolean): void 4 +Grille(largeur:int,hauteur:int) +clearLigne(): int +ifPositionValide(p:Point): boolean +ifPositionValide(list:LinkedList<Point>): boolean +setCAse(p:Piece): void +getLargeur(): int +getHauteur(): int +getCase(): Case +getLigne(): Ligne +ifRefresh(): boolean 1,n Ligne -tailleMax: int -nbElements: int -pleine: boolean +Ligne(Tm:int) +add(e:Case,x:int): boolean +estPleine(): boolean 1,n Case -neant: boolean -couleur: Color +Case() +Case(b:boolean) +Case(b:boolean,f:Color) +getNeant(): boolean +getColor(): Color ArrayList 2.2 Diagramme de séquence d’une partie Le diagramme d’activités complet du jeu. [au moin une migne est pleine] Animation Fin vider ligne pleine placer piece courante Fin Partie [else] reinitialisation partie [nouvelle position valide] [else] appliquer position basse [else] [temps+] [Position valide] Lancer partie [else] Placer piece position courante recuperer piece suivante calculer positon basse ne rien faire [action clavier] tester validité position [deja fait avec cette piece] [else] [aucune piece sauvegardé] [espace] [entrée] poser piece appliquer bas [droite/gauche] [rotation] [else] [position valide] calculer deplacer droite/gauche demander prochaine position recuper piece sauvegarder sauvergarde piece [ok] [!ok] appliquer mouvement ne rien faire positioner haut grille 2.3 Diagramme de cas d’utilisation Voici la liste de fonctionnalités sous forme d’un diagramme d’utilisation. Fonctionnalités Consulter Score/Niveau Lancer Partie Afficher Aide Tenir pièce regarde bouton menu changer le nombre de pièces suivantes à afficher action clavier menu action clavier Joueur Déplacer pièce action clavier Poser Pièce action clavier bouton menu Tourner pièce Mettre/Enlever pause afficher/enlever fantôme 5 2.4 Diagramme de séquence Voici un diagramme de séquence de l’action poser pièce. Nous avons choisi ce diagramme afin de montrer l’architecture MVC. En effet, on remarque que le joueur grâce à un contrôleur de type KeyControler influe sur le model (ici le Jeu). Le jeu quand à lui, applique les actions commandées par le contrôleur et notifie la vue que des changements ont eu lieu. Celle-ci se met à jour pour informer le joueur. Diagramme de séquence pour l’action poser pièce. :KeyControler PieceCourante:Piece :Jeu :vueSwing :Grille Joueur Touche Espace poserPiece() while(mouvement possible) deplacerCourante(Mouvement.Bas) notification ajouterPieceCouranteGrille() retour visuel() notification retour visuel() pieceCouranteNew() notification retour visuel() 6 PieceCourante : Piece Chapitre 3 Conclusion Nous aurions voulu apporter plusieurs modifications sur ce projet, et nous pensions avoir encore quelques temps après la présentation voilà pourquoi nous tenions à vous informer des modifications qui auraient été apportées. – Fonction de sauvegarde rapide, c’est à dire reprendre l’état d’une grille au moment où le joueur aurait sauvegardé de façon dynamique afin d’augmenter son score au plus haut dans une même partie. – Utilisation de fichier xml pour sauvegarder une configuration ( touche préférée du joueur ). Ainsi qu’un tableau des scores. – Ajout de pièce bonus, par exemple des pièces qui explosent, des pièces aimantés, une pièce space-invader qui peut tirer sur la grille afin de faire la place et d’augmenter le score. – Ajout d’un fond sonore. Si nous avions eu plus de temps, il aurait été intérressant grâce à une utilisation plus poussée du multithreading de faire un mode affrontement où deux joueurs doivent faire des lignes le plus vite possible, de plus si un joueur fait une ligne des cases aléatoires apparraissent chez l’adversaire. 7