-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.txt
More file actions
259 lines (180 loc) · 13.1 KB
/
Copy pathREADME.txt
File metadata and controls
259 lines (180 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
TOWER DEFENSE
______________________________________________________________________________________________________________________________
#################################################### FONCTIONNEMENT DU JEU ####################################################
______________________________________________________________________________________________________________________________
I. OBJECTIFS
Tower Defense consistant à défendre sa base de vagues d'ennemis à l'aide de tours.
1. PLATEAU DE JEU.
Chaque niveau se déroule sur un plateau comportant une base verte que le joueur
doit défendre, ainsi qu'une base rouge sur laquelle les ennemis apparaissent.
2. ENNEMIS.
Les ennemis avancent de la base rouge à celle du joueur en prenant l'unique chemin
existant de l'un à l'autre. Si un ennemi arrive à la base du joueur, il attaque
une fois les points de vie du joueur avant de disparaître.
3. TOURS.
Le joueur possède une certaine somme d'argent qu'il peut dépenser dans la boutique pour
acheter et placer des tours. Celles-ci attaquent les ennemis. Un ennemi tué par les tours
rapporte une certaine somme d'argent au joueur.
4. VICTOIRE.
Le joueur gagne un niveau s'il survit jusqu'à ce qu'il n'y ait plus d'ennemi en vie et que
toutes les vagues d'ennemis sont passées. Il perd si son nombre de points de vie atteint zéro.
II. CONTRÔLES
1. SUR LE MENU.
ENTER : Lance le jeu avec la sauvegarde affichée à l'entrée, ou avec une nouvelle sauvegarde si New game est affiché.
<- et -> : Permet de parcourir les sauvegardes disponibles.
D : supprime la sauvegarde affichée, s'il y en a une.
2. DANS UN NIVEAU.
ECHAP : Retour au menu.
LEFT CLICK : Permet de sélectionner une tour dans la boutique, et de placer la tour sélectionnée sur une case de construction.
A, B, C, D : Si un marchand est à la base du joueur, sélectionne l'offre correspondante à la lettre pressée.
On a également les touches de triche suivantes :
W : Ajoute 1 coin au joueur.
N : Passe au niveau suivant.
______________________________________________________________________________________________________________________________
################################################## FONCTIONNALITÉS RÉALISÉES #################################################
______________________________________________________________________________________________________________________________
I. PLATEAU DE JEU
Dans tout le projet, on utilise la classe Coords qui représente une paire d'entiers.
On distingue cinq types de cases, qui étendent Tile :
- BaseTile : la base du joueur, en vert.
- SpawnTile : là où les ennemis apparaissent, en rouge.
- RouteTile : là où les ennemis se déplacent, en bleu clair.
- ConstructionTile : là où des tours placent être placées, en bleu.
- WallTile : une case de remplissage, en bleu foncé.
Le plateau de jeu est implémenté comme une matrice de cases Tile[][].
Le chemin est implémenté comme une pile de coordonnées Stack.
Chaque coordonnées de la pile correspond au milieu d'une case du plateau.
II. ENTITÉS
Les ennemis et les tours dérivent d'une classe abstraite d'entité, notée
Entity<A extends Entity<A, B>, B extends Entity<B, A>>
On justifie ce choix.
D'une part, on souhaite pouvoir appeler sur Entity une méthode abstraite attack qui
fournit les dégâts que l'entité souhaite infliger à chaque ennemi. Le type des entités
attaquées dépend cependant de celui de l'entité elle-même, on doit donc paramétrer la classe Entity
d'un type B représentant celui des ennemis d'une entité.
D'autre part, comme on le verra plus tard, on souhaite pouvoir appeler des manipuler les status de l'entité
(ajouter, retirer, obtenir). Cependant, les status sont eux-même paramétrer du type de l'entité. En effet, un
statut est soit pour les ennemis, soit pour les tours. Similairement, on paramétrise Entity d'un type
A qui indique le type d'entité ciblé par les status.
En particulier, pour une sous-classe de Entity, la classe A est précisément cette sous-classe.
En corrolaire, on en déduit le nom de nos classes-filles d'Entity :
- Enemy extends Entity<Enemy, Tower>, la classe des ennemis.
- Tower extends Entity<Tower, Enemy>, la classe des tours.
III. ENNEMIS
La classe des ennemis est Enemy, qui étend la classe Entity.
Tous les ennemis ont été implémentés.
1. DÉPLACEMENT.
Les ennemis se déplacent via une méthode move. Ils suivent pour cela
le chemin vers le base qu'on leur fournit via la méthode initPath, représenté par une pile
de coordonnées Stack. Les ennemis vont dans la direction des coordonnées en tête
de la pile, et une fois celles-ci atteintes, la tête de la pile est retirée et on recommence, et ce
jusqu'à ce que la pile soit vide, auquel cas l'ennemi a atteint la base.
2. ATTAQUE.
Chaque ennemi défini sa manière d'attaquer les tours. Pour cela, à partir d'une liste de tours donnée,
il renvoie une liste d'attaques, une par tour donnée en entrée.
3. ÉQUILIBRAGE.
Les valeurs données dans l'énonce mènent à un jeu plutôt déséquilibré et injouable.
Pour pallier à cela, nous avons modifié ces valeurs pour gagner en équilibrage, et donc en fun.
IV. TOURS
La classe des tours est Tower, qui étend la classe Entity. Toutes les tours ont été implémentées.
1. BOUTIQUE.
Une tour s'achète dans la boutique, implémentée par la classe Shop. Un attribut majeur de cette classe est son
tableau Slot[] de slots. Chaque slot représente un produit de la boutique, qui est une tour.
Cliquer sur la slot d'une tour la sélectionne, et on peut lire ses détails dans la
case dédié à la slot sélectionnée.
2. PLACEMENT.
Si une tour est sélectionnée, que le joueur a assez d'argent pour l'acheter et qu'il
clique sur une ConstructionTile qui n'est pas occupée, alors la tour est placée et le joueur est débité du montant
indiqué.
3. ATTAQUE.
Chaque tour définie sa manière d'attaquer les ennemis, de manière symétrique à comment les ennemis attaquent les tours.
Cela va permettre la création de méthodes polymorphiques par la suite.
V. GESTIONNAIRE DE COMBAT
Nous avons décrit les deux bélligérants principaux de notre jeu, nous pouvons donc décrire la manière principale par laquelle
ils interagissent. Les interactions se font dans une classe FightManager.
Celle-ci contient seulement deux attributs :
- La liste des tours actuellement vivantes et affichées ;
- La liste des ennemis actuellements vivants et affichés.
À chaque frame, le gestionnaire de combat :
- Met à jour les ennemis, les tours, ainsi que le marché et l'inventaire du joueur (voir plus loin).
- Fait attaquer les ennemis et les tours ;
Le polymorphisme développé à travers les classes précédentes permet d'utiliser d'uniques fonctions polymorphiques capables
de traiter à la fois l'attaque des ennemis envers les tours, et des tours envers les ennemis.
VI. JEU ET NIVEAU
1. JEU.
Le jeu est défini dans la classe Game.
Il ne peut exécuter qu'un niveau à la fois, ce que représente l'attribut level de cette classe.
Au lancement, le jeu charge le nom de tous les fichiers de niveaux que contiennent le jeu.
Le contenu d'un niveau n'est chargé que lorsque celui-ci commence.
2. JOUEUR.
La classe Joueur contient les informations spécifiques au joueur, c'est-à-dire ses points de vie,
sa quantité d'argents et son inventaire.
3. NIVEAU.
Un niveau est composé d'un joueur de la classe Player, d'une boutique de la classe Shop,
d'un gestionnaire de combat FightManager, d'une liste de vagues d'ennemis Queue.
Un niveau commence en générant une première vague d'ennemis, et passe à la suivante quand tous les ennemis sont
morts (ce que détermine le gestionnaire de combat). Si le joueur meurt, ou si la liste de vagues est vide, alors
le niveau est terminé.
4. ÉCRAN.
L'écran d'un niveau est composé de plusieurs zones, dont la classe Zone permet une représentation.
- La classe/zone Level affiche les informations propres au niveau.
- La classe/zone Player affiche les informations propres au joueur.
- La classe/zone Shop affiche les tours disponibles dans la boutique, ainsi que la tour sélectionnée.
- La classe/zone Gameboard affiche le plateau de jeu et tout ce qui se passe dessus (notamment les entités).
______________________________________________________________________________________________________________________________
########################################### FONCTIONNALITÉS BONUS ET SUPPLÉMENTAIRES #########################################
______________________________________________________________________________________________________________________________
I. MENU ET SAUVEGARDE
1. MENU.
Une fonctionnalité majeure que nous avons ajouté est celle d'un menu permettant d'harmoniser le passage entre les niveaux.
Ainsi, au lancement du jeu, un menu de sélection de sauvegarde est affiché. Il permet de sélectionner une sauvegarde parmi
celles trouvées dans le dossier resources/saved, et de la lancer en appuyant sur la touche Entrée. Il permet également de
créer une nouvelle sauvegarde en sélectionnant New game.
2. SAUVEGARDE.
Chaque nouveau niveau atteint met à jour la sauvegarde. De même, nous enregistrons la vague maximale atteinte pour le dernier
niveau atteint. Cependant, relancer une sauvegarde à une vague en milieu de niveau, sans sauvegarder ni l'argent du joueur,
ni les tours posées, peut mener à un softlock, si la vague qui arrive requiert d'avoir posé des tours aux vagues précédentes.
Pour pallier à ce problème, nous avons décidé que le lancement d'une sauvegarde fasse commencer le joueur au début du niveau,
c'est-à-dire à la première vague.
Il serait facilement possible de le faire commencer à la vague enregistrée en passant en argument du constructeur
Level le numéro de la vague enregistrée, et de directement passer à cette vague.
II. ÉCRAN DE TRANSITION
1. TRANSITION.
La transition entre les niveaux peut paraître abrupte, puisque dès que le joueur gagne, le niveau suivant est lancé.
Pour améliorer l'expérience utilisateur, nous avons créé une classe TransitionScreen qui fait une fondue noir,
attend quelques temps et redevient transparent.
2. DÉBUT ET FIN DE NIVEAU.
De cette classe, deux classes filles existent : LevelScreen, pour le début de niveau,
et ResultsScreen, pour la fin de niveau.
Le premier affiche le nom du niveau, et le second le résultat (victoire ou défaite).
Le rendu est clairement visible à l'expérience.
3. STATUTS
Une entité peut posséder des statuts qui alternent ses valeurs, comme son attaque ou ses points de vie.
Un statut est une instance d'une classe implémantant la classe abstraite Status<E extends Entity>.
Il est donc paramétré soit comme étant pour les tours, soit pour les ennemis. De plus, un statut peut
être positif comme négatif. Par exemple, Regeneration fait regagner des points de vie aux tours,
tandis que Frozen diminue la vitesse et la vitesse d'attaque des ennemis.
Ce système s'avère très utile dans l'implémentation de certaines tours (Ice Caster et Poisoned Caster),
ainsi que le marchand.
III. MESSAGE ET BOOST
1. BOOST.
Un ennemi qui implémente l'interface Helper peut également soigner des ennemis avec sa méthode help.
En particulier, il peut soigner les points de vie des autres ennemis, mais aussi leur donner des statuts (supposément positifs).
2. MESSAGE.
Les entités peuvent afficher un message à l'écran, sous forme de bulle de dialogue,
pour une certaine durée. C'est notamment le cas des ennemis Minion, Termiernator et MerchantKing.
IV. MARCHÉ ET MARCHAND
Le marché est une classe Market faisant le pont entre les MerchantKing et le Player.
Il est ainsi ce que le FightManager est aux ennemis et aux tours.
Lorsqu'un marchand atteint la base, il rejoint le marché et propose des offres au joueur, qu'il explicite par un message.
Le joueur peut alors appuyer sur les touches A, B, C et D pour sélectionner une
offre parmi les quatres proposées par le marchand. Une fois l'offre sélectionnée, le marchand part.
Au lieu de propose les trois même offres systématiquement, nous avons amélioré le marchand pour qu'il propose trois de quatre offres
aléatoirement parmi six offres. La quatrième offre, qui est de gagner 30 pièces, est systématiquement présente, afin qu'un joueur
ruiné puisse tout le même bénéficier de l'aide du marchand.
Cependant, par notre implémentation, les bonus du marchand ne sont pas conservés entre les niveaux.
Cela permet que les niveaux soient indépendants entre eux, et afin d'éviter les comportements hasardeux avec le système de sauvegarde.
V. EXCEPTION
Les exceptions sont toutes implémentées. Nous avons légèrement modifié l'arborescence entre les différentes exceptions,
en définissant l'exception MapException comme mère de toutes les exceptions relatives au chemin du plateau de jeu.
Ainsi, l'exception produite en cas de mauvais format de plateau de jeu s'appelle, en toute logique, MapFormatException.