-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgdd_fr.t2t
706 lines (368 loc) · 74.3 KB
/
gdd_fr.t2t
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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
Project Warrior GDD
Pablo Donato, Luc Chabassier
%%date(%d-%m-%Y)
%!style(tex): geometry
%!postproc(tex): "\\usepackage{geometry}" "\\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}"
%!style(tex): tabularx
%!postproc(tex): "\\begin{tabular}" "\\begin{tabularx}{\linewidth}"
%!postproc(tex): "l\|" "X|"
%!postproc(tex): "\\end{tabular}" "\\end{tabularx}"
%!postproc(tex): "\\clearpage" ""
%!postproc(tex): "\\begin{document}" "\\DeclareTextSymbol{\degre}{OT1}{23}\\begin{document}"
%!postproc(tex): "°" "\degre"
= Présentation =
Project Warrior est le nom de code pour désigner un projet de jeu de combat multijoueurs développé par le collectif DWARVES, constituant par ailleurs son premier projet d'envergure. Project Warrior peut être qualifié de Super Smash Bros. like dans la dynamique et le système de combat. Néanmoins il possède ses caractéristiques propres telles qu'un gameplay où les sorts (attaques spéciales dans SSB) prennent une place plus importante, notamment via leur coût en mana qui demande une gestion plus intelligente de leur utilisation. Un soin tout particulier sera aussi apporté au background et donc à l'ambiance générale du jeu afin d'en dégager une personnalité propre d'inspirations diverses. On cherchera aussi un style de préférence un peu décalé et humoristique, pour conserver l'ambiance //joyeux bordel// propre aux SSB, avec des personnages et des stages totalement nouveaux à la patte graphique et à l'ambiance sonore marquées.
= Background =
Le //background// correspond à tous les éléments de l'univers dans lequel prend place le jeu, incluant les lieux représentés dans les stages, les personnages et leurs histoires, le contexte dans lequel les combats se déroulent, un scénario dans un possible mode aventure... Cette partie va donc regrouper et décrire ces différents éléments, ainsi que leurs aspects graphiques et sonores. Tout ce qui se rapporte au gameplay, à l'interface ou à la programmation est situé dans la partie "Gameplay, interface et programmation".
== Scénario ==
//Ce scénario n'est en aucun cas figé et définitif : il peut évoluer, aussi bien avec des changements mineurs qu'avec d'importantes modifications à sa structure et à son contenu.//
=== Contexte ===
L'histoire du jeu se construit autour de la renconte entre le monde du rêve et celui de la réalité.
==== Dans le vrai monde réel de la vérité véritable ====
Le monde réel est plongé dans une guerre permanente que nul ne peut arrêter : toute l'économie du monde est basée sur la vente d'armes, le mercenariat et le pillage. La technologie de guerre et de destruction a pris une place pré-dominante sur l'ensemble des autres sciences, les nations étant plongées dans un effort de guerre permanent.
==== Dans le monde des rêves ====
Les habitants du monde des rêves – immortels – plongés dans la mélancolie et l'ennui de leurs vies sans fin tombent tous peu a peu dans la Torpeur, une léthargie d'où personne ne revient. Les émotions ont déserté leur monde et tout instinct de progès ou d'amélioration de leur condition les ont quittés. Dans leur antique jeunesse, ils avaient pourtant la puissance des dieux et pouvaient manipuler à partir du "fluide" tout leur univers ; certains habitants ont encore une part de ce fluide mais dans une forme bien dégradée du pouvoir originel.
=== Élément déclencheur ===
Un personnage mystérieux, le Prophète, parvient a créer un portail entre les deux mondes ; le monde réel aperçoit dans son alter ego la conquête d'une vie infinie et la création de soldats immortels, tandis que le monde des rêves redécouvre les émotions qui les ont abandonnés. Néanmoins de cette union des deux mondes un personnage naît qui pourra changer la face de ce nouveau monde : il a entre ses mains le pouvoir ultime et pourra au sacrifice de sa vie accorder un voeu...
= Gameplay, interface et programmation =
Dans cette partie sont présentés les différents objectifs fixés initialement pour le développement du jeu en terme de gameplay, d'interface et de programmation. Lorsqu'ils seront tous atteints, Project Warrior atteindra un nouveau stade de développement, qualifié selon le contentement de l'équipe vis-à-vis de la quantité et de la qualité du contenu et des fonctionnalités alors implémentées, mais aussi en fonction des critiques et avis extérieurs de la communauté libre ou de toute personne intéressée par le projet.
== Règles et interface ==
L'interface est contrôlable aussi bien à la manette qu'au clavier.
=== Menu principal ===
Quand le jeu est lancé, il affiche un menu principal permettant d'accéder aux différents sous-menu présentés ci-dessous.
==== Play ====
Permet d'accéder aux différents modes de jeu disponibles afin de lancer une partie. Dans la version alpha de Project Warrior, on pourra accéder uniquement au mode //Custom Melee//, car c'est le mode de jeu le plus convivial et le plus complet, par conséquent il constitue un choix judicieux en tant qu'objectif premier de développement.
==== Events ====
Permet d'accéder à la liste des events. À côté des items de la liste, on peut voir l'image et la description associées à l'event sélectionné.
==== Settings ====
Permet de configurer les paramètres audio, vidéo, ainsi que les paramètres de contrôleurs.
==== Quit ====
Quitte le jeu (ferme le programme).
=== Déroulement d'une partie ===
Project Warrior consiste comme vu dans la présentation en un jeu de combat dynamique reprenant de nombreuses mécaniques de SSB. Étudions le déroulement d'une partie //Custom Melee// au travers d'un des joueurs pour mieux comprendre :
- Le joueur choisit parmi une liste de //héros// charismatiques celui qu'il souhaite incarner ;
- Il modifie les règles à son goût (cf. section "Custom Melee") ;
- Il choisit ensuite dans quel stage (appelé aussi terrain) il souhaite combattre ;
- Le combat commence : l'objectif est d'éliminer les autres joueurs en les envoyant hors du terrain. Pour cela il est d'abord nécessaire d'affaiblir les ennemis en leur infligeant des pourcentages de dégâts plus ou moins importants selon les attaques utilisées, puis d'asséner une attaque appliquant une force de projection afin de faire totalement sortir l'ennemi de l'écran. Bien-entendu, plus les dégâts ayant été pris par la cible auparavant sont importants, et plus celle-ci sera projetée loin et donc susceptible de mourir.
==== Modes de combat ====
Reste à savoir comment déterminer qui est le gagnant... cela va en fait dépendre du mode de combat :
- Timelaps : le combat dure pendant un temps défini par le joueur, et celui qui à la fin possède le meilleur score gagne la partie. Le joueur gagne 1 point en tuant un adversaire, c'est-à-dire lorsque celui-ci meurt moins de 10 secondes après avoir pris des dommages venant de son agresseur. La mort entraîne la perte d'un point. Si jamais deux ou plus de joueurs possèdent des scores égaux, un combat de //mort subite// sera alors engagé uniquement entre ces joueurs, une attaque suffisamment puissante sur un ennemi le projetant directement hors du terrain.
- Survie : Tous les joueurs possèdent le même nombre de vies préalablement choisi, et le gagnant est le dernier à survivre (donc le seul qui n'a pas perdu toutes ses vies).
==== Classement final ====
Selon le mode de combat choisi et le nombre de joueurs, il sera établi à la fin de la partie un classement résumant les nombres de kills, de morts et même de suicides effectués par chaque joueur, ainsi que la position de chaque joueur dans le-dit classement (position qui dépendra du score en Timelaps ou de l'ordre de mort des joueurs en Survie).
=== Custom Melee ===
//Custom Melee// est un mode de jeu convivial, ouvert et complet. Voici ces différentes caractéristiques :
==== Réseau ====
Le mode //Custom Melee// permet d'effectuer des parties comptabilisant de 2 à 4 joueurs, qu'ils soient connectés directement à l'ordinateur via des contrôleurs supplémentaires, ou qu'ils se connectent depuis d'autres postes via TCP/IP. Cela est possible grâce à l'architecture client/serveur adoptée, où un client représente une instance de jeu comptabilisant un ou plusieurs joueurs et devant se connecter, que ce soit en local ou en réseau, à un serveur gérant la partie ; ce serveur est hébergé sur la même machine qu'un des clients. La progression des events est sauvegardée sur le serveur gérant la partie ; cela inclut donc la progression des différents contenus débloquables.
==== Sélection des personnages ====
L'écran de sélection des personnages est similaire dans l'organisation à celui de SSB, à ceci près qu'avant de choisir son personnage, le joueur doit associer son périphérique en maintenant une touche durant 1 seconde, comme cela se fait dans le jeu indépendant //Jamestown//. Il choisit ensuite son personnage à l'aide d'un curseur qui lui est propre, identifié par la couleur associée au numéro de joueur.
Il est possible de choisir le mode de combat (Timelaps ou Survie).
Si la partie ne contient pas déjà 4 joueurs en local, un joueur externe peut se connecter en réseau durant la phase de sélection des personnages.
Comme dans SSB, il sera possible de switcher via un bouton entre les modes //Real Melee// et //Team Melee//. Le premier mode correspond à un combat //chacun pour soi//, où tous les joueurs peuvent s'infliger des dégâts et chacun joue pour son propre score. Le second mode permet de former des équipes de 1 à 3 joueurs identifiées par leur couleur (bleu, rouge ou vert). Durant le combat, chaque personnage possède un costume reprenant les couleurs de son équipe. Au classement final, en Timelaps, les scores des équipes sont calculées en additionnant les scores de chaque joueur, et l'équipe gagnante étant celle possédant le meilleur score ; en Survie, c'est l'équipe qui survit qui gagne, tout simplement.
Il est aussi possible d'accéder au menu de modification des règles, dont les caractéristiques sont présentées ci-après.
==== Règles modifiables ====
En //Custom Melee//, certaines règles du jeu sont modifiables avant chaque partie, afin de diversifier l'expérience de jeu :
- On peut choisir le mode de combat (Timelaps ou Survie).
- Il est possible de donner des handicaps aux joueurs, afin de compenser des niveaux trop différents. Par exemple, dans le cas d'une partie Timelaps, certains joueurs peuvent avoir des points des le débuts, ou d'autres partir avec un malus, c'est à dire des points dans les négatifs. Dans le cas d'une partie Survie, le nombre de vie peut être différent entre les joueurs. Le malus le plus commun reste cependant d'augmenter les pourcentages de dégâts initiaux des joueurs les plus expérimentés, malus valable quelque soit le mode de combat.
- La gravité peut aussi être modifiée : par défaut elle est de 1, une valeur plus grande rendant les personnages plus difficiles à éjecter mais aussi à déplacer. Une valeur plus faible rend les personages plus légers, donc ils sautent plus haut, se déplacent plus vite mais sont aussi éliminés plus vite. Attention cependant, les stages sont testés avec une gravité de 1 et la modification de cette valeur peut rendre le jeu très désagréable sur certains stages.
- Un coefficient sur les dégâts des attaques peut être attribué. Avec une valeur supérieure à 1, les personnages prendront plus de dégâts et seront donc éliminés plus vite.
Il est aussi possible de choisir dans le même écran le mode de sélection du stage (cf partie "Sélection du stage" ci-après).
L'écran de modification des règles reprendra l'interface de celui de SSB, c'est-à-dire une liste contrôlable par tous les joueurs en même temps.
==== Sélection du stage ====
Comme pour l'écran de sélection des personnages, l'écran de sélection des stages est similaire à celui de SSB, avec les stages sélectionnables sous forme de vignettes organisées en grille à l'aide d'un curseur, contrôlable aussi bien à la manette qu'au clavier. Il est aussi possible de choisir un stage aléatoire à l'aide d'un bouton prévu à cet effet.
Pour déterminer le joueur qui sélectionne le stage, on choisira un des 3 modes suivants dans l'écran de modification des règles :
- **Tour de rôle** : le joueur contrôlant le curseur tourne après chaque partie par ordre décroissant (joueur 1, puis 2, etc)
- **Joueur n°#** : c'est toujours le joueur n°# (le chiffre '#' étant choisi par les joueurs) qui choisit le stage
- **Libre** : tous les joueurs peuvent contrôler le curseur ; le mode le plus enthropique :p
=== Events ===
Les //events// sont comme leur nom l'indique des évènements qui s'active dans le jeu sous certaines conditions. Ils peuvent faire office de simples //achievements// à débloquer, mais leur utilité majeure est de permettre de débloquer du contenu, c'est-à-dire de nouveaux stages et personnages. La progression dans l'obtention des events est aussi synonyme de progression narrative, avec notamment des cinématiques explicatives lors de l'accomplissement d'un event important (par exemple lorsqu'un personnage important dans l'histoire est débloqué). Ce système permet donc de concilier gameplay uniquement multijoueurs et progression narrative, innovation notable par rapport à SSB.
==== Représentation en mémoire ====
Les events sont tous placés dans le même dossier. Chaque event est un dossier constitué de différents fichiers :
- ``name`` : c'est un fichier dont la première ligne est la nom complet de l'event, celui affiché dans les menus. La seconde ligne du fichier contient le nom interne de l'event. C'est un nom qui doit être unique et qui est utilisé par les personnages et stages pour se référer à cet event. Ce nom ne doit contenir ni espaces, ni caractères spéciaux, ni caractères non ascii. Enfin, la troisième ligne contient une description de l'event pour le joueur.
- ``preview.png`` : c'est l'image utilisée pour représenter l'event.
- ``event.lua`` : c'est un script exécuté à la fin de chaque partie. Il peut accéder à différentes informations comme le stage, les personnages et différentes statistiques du combat (durée, suicides ...) via l'API du programme. Il peut aussi enregistrer des variables numériques qui seront sauvegardées d'une exécution du script à une autre. Ces variables ne seront modifiées que par le script. Enfin, il peut se valider, indiquant au programme que les conditions ont été remplies. Le script peut posséder une fonction ``displayWin``. S'il n'en possède pas, un message sobre avec la description de l'event apparait lors de la validation de l'event. Sinon, la fonction de callback peut utiliser le moteur graphique pour afficher une cinématique/des informations particulières ... signalant la réussite de l'event.
=== GUI ===
L'ensemble de la GUI du programme peut être personnalisé avec un thème, chargé au lancement du programme. Nous allons détailler ici les différents éléments de la GUI et les paramètres qui peuvent leur être appliqués.
L'ensemble de la GUI est faite pour être parcourue avec la manette, donc les éléments possèdent aux moins deux états : sélectionné (ils ont le focus) et neutre.
La GUI est gérée par une instance d'une classe, unique, qui référence tous les éléments affichés et se charge de leur faire passer les évènements lorsque c'est nécessaire.
==== Les Layouts ====
Les layouts sont un élément essentiel de la GUI puisqu'ils permettent d'organiser les éléments de la GUI indépendamment de la résolution de l'écran. Un layout est en faite une grille dans laquelle chaque élément possède une position et une taille. Lorsque la grille est adaptée à l'écran, tous les éléments à l'intérieur le sont aussi.
==== Les listes ====
Les listes sont un élément centrale de la GUI puisqu'elles constituent la majorité des menus. Le but étant d'avoir une interface proche de celle de SSB melee, une liste occupe une surface donnée et chaque item possède un offset, un décalage sur l'axe x par rapport au centre de cette zone. Les items de la liste sont placés les uns au dessus des autres. L'item sélectionné subit un léger zoom et décale les autres items. Si il y a trop d'item pour qu'ils rentrent tous dans la zone prévue, seul un certain nombre est affiché et on peut scroller en passant d'un item à un autre.
Les items sont constitués de plusieurs images. Une image pour la partie droite, une pour la partie gauche et une de un pixel de large qui est répétée sur l'axe x pour former l'item en entier. Le texte est affiché entre les parties droites et gauches. Si il est trop long, il est tronqué, et des points de suspension sont rajouté. Le texte peut être décalé manuellement avec les touches droites et gauches lorsque l'item est sélectionné. S'il n'est pas sélectionné, seul le début du texte est toujours affiché. Trois autres images sont utilisées pour créer un item sélectionné. Ces trois images doivent avoir exactement la même taille que celle utilisée par un item non sélectionné.
==== Les cadres ====
Les cadres sont des container qui encadrent un ou plusieurs autres éléments de la GUI. Ils sont créés à partir de huit images. Une pour chaque coins, qui doivent être des images carrés, et une pour chaque bordure. Les images des bordures haut et bas doivent faire un pixel de large et le même nombre de pixel de haut que les coins. Pour les images des bordures droites et gauche, c'est l'inverse.
Une texture peut aussi être appliquée à l'intérieur. Dans le cas contraire l'intérieur est transparent.
==== Les grilles ====
Une grille est élément qui affiche des éléments en tableau à deux dimensions dans une zone particulière. On peut préciser une image de fond la grille. Chaque élément est un rectangle affichant une image. Le nombre d'image par ligne est calculé automatiquement pour avoir un espace minimum mais supérieur à 3 pixels. Chaque élément dérive d'une classe qui possède des méthodes permettant à cet élément de se modifier lors de la sélection.
==== Les zones de texte ====
Les zones de texte sont des zones permettant d'afficher du texte //formaté//. Le texte formaté est juste un texte dont les lettres peuvent posséder un attribut ``EM``, indiquant qu'elles sont importantes et donc doivent être affichées avec une police différente. Le texte passé en argument peut posséder des retour à la ligne et des tabulations (qui n'alignent pas mais sont l'équivalent de quatre espaces). Il doit être formaté de la façon suivante : ``Du texte normal [em]du texte important[em]\nUne nouvelle ligne avec du texte normal``.
==== Les entrées ====
Les entrées sont des zones qui permettent d'entrer du texte. La seule méthode d'entrée disponible est la clavier : il n'est pas prévu de supporter un système d'entrée de texte à la manette. Une entrée peut avoir un nombre maximum de lettres fixé, auquel cas un ``_`` est placé pour toutes les lettres qui n'ont pas été entrées. Dans ce cas, la taille de l'entrée est fixe : on précise un largeur maximale et la hauteur est automatiquement calculée. Dans le cas contraire, on doit aussi préciser la hauteur maximale : si le texte dépasse cette hauteur, un scrolling sera mis en place, mais sans barre de scrolling.
==== Les barres de scrolling ====
Une barre de scrolling est composée de quatre images. Une qui représente le haut de la barre de scrolling, une qui représente la bas, une de un pixel de haut qui sera répétée pour former la barre et une de un pixel de haut qui est répétée pour former la partie de la barre qui est scrollée. La barre possède trois informations : la hauteur totale de ce qui est scrollable, la hauteur de ce qui est affiché et la position haute de ce qui est affiché. Une barre de scrolling peut être non interactive, auquel cas elle sert juste d'information.
==== Les barres de remplissage ====
Une barre de remplissage est une barre qui représente une partie remplit de quelque chose. Elle est formée de deux images : une de la barre complètement vide et une de la barre complètement remplie. Seules une partie de chaque image sont affichées pour formée une barre remplit seulement en parties. Les deux informations contenues sont la valeur maximale et la valeur actuelle. À l'instar des barres de scrolling, les barres de remplissages peuvent être en mode non interactif.
==== Les checkboxes ====
Une checkbox est simplement une boite qui peut avoir deux états : activé et éteint. Elle est créée avec quatre image : une pour la checkbox éteinte, une pour la checkbox allumée, une pour la checkbox allumée et sélectionnée et une pour la checkbox allumée et éteinte.
==== Les boutons radio ====
Les boutons radio sont composés de quatre images comme les checkbox. La seule différence dans leur fonctionnement est qu'il ne peut y avoir qu'un seul radio activé à la fois dans un même groupe de radio. Lors de la création d'un radio, on précise le groupe auquel il appartient, identifié par une chaine de caractère.
== Système de combat ==
=== Contrôles ===
Project Warrior est conçu pour être joué à la manette. Cependant, toutes les touches sont //rebindables// : vous pouvez par exemple assigner à toutes les actions du jeu des touches du clavier (utile pour les joueurs ne possédant pas de manette), ou assigner des boutons différents de la manette.
=== Mouvements ===
Comme dans SSB, le personnage peut se déplacer dans 2 directions (droite et gauche) en marchant ou en courant selon l'inclinaison du stick, ainsi que sauter en appuyant sur un bouton et redescendre plus rapidement en inclinant fortement le stick vers le bas. Il y a aussi possibilité de double-saut, tout simplement en réappuyant sur le bouton de saut. Les animations des personnages s'adaptent bien évidemment à ces combinaisons de mouvements.
Certains sorts permettent aux personnages qui les maîtrisent de posséder encore plus de mobilité : on appellera alors de manière générique //dash// un sort avec lequel le personnage augmente énormément sa vitesse de déplacement dans une certaine direction pendant un court instant.
=== Attaques ===
Les attaques étant spécifiques à chaque personnage, on ne présentera dans cette partie que les caractéristiques inhérentes à tous les personnages. Les descriptions détaillées sont situées dans la partie //Personnages//.
La Zone d'Attaque (ZA) est la zone qui lorsqu'elle entre en contact avec le corps d'autres personnages leur inflige les dégâts ou un CC. Cette zone n'est pas forcément solidaire de l'attaquant, elle peut être créée et se déplacer indépendamment de celui-ci.
On peut appliquer un masque de collision aux zones d'attaques : elles ne peuvent prendre en compte que les collisions avec le terrain, étant alors qualifiées de zones //fantômes//, au contraire des zones //physiques//, qui elles prennent en compte toutes les animations. Exemple d'utilisation : un projectile qui touche tous les ennemis sur sa trajectoire ; ce sera une ZA fantôme avec des pourcentages, qui infligera ses dégâts aux personnages qu'elle traverse sans pour autant être stoppée car sa physique fait qu'elle ignore les collisions avec eux. On peut aussi leur appliquer un masque pour qu'elles ignorent les collisions avec le terrain seulement, étant alors qualifiées de ZA //spectre//, au contraire des ZA //réelles//. On peut bien évidemment combiner ces deux masques pour créer des ZA à la fois //spectre// et //fantôme//, comme un laser qui traverse les ennemis et les murs.
Une ZA peut ou non recevoir les dégâts et les CC, tout dépend de la ZA. De plus, la façon dont les ZA reçoivent les CC dépend aussi. Seules les ZA fantômes ne peuvent recevoir ni les dégâts ni les CC.
Les zones indépendantes des personnages peuvent ou non ignorer la gravité.
Ces zones se déplacent avec les animations et sont mises à jour à chaque FPS.
==== Physiques ====
Ces attaques n'ont aucun coût en mana, et existent sous de nombreuses formes à la puissance variable suivant les boutons pressés. Comme dans SSB, ces attaques seront associées à une touche spécifique (que nous appellerons par convention ``P``), qui combinée à une inclinaison du stick plus ou moins forte dans une certaine direction, permettra les différentes attaques, variant selon que le personnage soit sur terre ou dans les airs. De par leur caractère //spammable//, les attaques physiques infligent des dégâts uniquement au corps à corps et ne permettent qu'une seule forme de CC : la projection.
Techniquement, une attaque physique consiste en une ou plusieurs ZA solidaires du corps de l'attaquant associées à un certain nombre de pourcentages de dégâts et un CC de projection, qui seront infligés à n'importe quel autre personnage qui entre en contact avec la/les ZA.
==== Magiques ====
Les attaques magiques (ou sorts) se lancent en appuyant sur la touche qui leur est associée (que nous appellerons par convention ``M``) tout en inclinant (ou pas) le stick dans une certaine direction pour choisir le sort à lancer. On compte ainsi 4 sorts par personnage : ``M``, ``M+Côté``, ``M+Haut`` et ``M+Bas``.
Les attaques magiques diffèrent des attaques physiques de par un élément essentiel : la jauge de mana. Ainsi l'utilisation d'une compétence magique aura-t-elle un coût lié à sa puissance en termes de dégâts et/ou d'utilité, diminuant les ressources en mana du personnage ; si celui-ci ne possède pas assez de mana pour lancer sa compétence, il doit attendre que sa jauge se recharge. La récupération de mana est assez rapide pour permettre un gameplay dynamique et une utilisation fréquente des sorts, tout en demandant une gestion intelligente de cette ressource de par sa faible quantité. Ainsi un sort infligeant de lourds dégâts de zone et étourdissant brièvement les ennemis sera considéré puissant, et pourra par conséquent nécessiter toutes les ressources en mana du personnage, empêchant le joueur d'abuser du sort, d'autant plus qu'il devra utiliser d'autres sorts qui retarderont le moment où sa jauge de mana sera pleine.
Cette limitation liée au mana permet de donner plus de puissance aux sorts : ils peuvent infliger plus de dégâts que les attaques physiques et/ou appliquer tous les types de CC (un seul par sort biensûr).
Techniquement, une attaque magique consiste en une ou plusieurs ZA solidaires ou non du corps de l'attaquant, qui peuvent donc avoir une trajectoire indépendante de celui-ci. Ces attaques sont associées à des pourcentages et n'importe quel(s) CC(s). Une attaque magique peut aussi modifier le personnage attaquant, en modifiant temporairement certaines caractéristiques, comme sa vitesse ou son poids, et définitivement certaines, comme les pourcentages, qui peuvent être réduits ou augmentés.
==== Smashs ====
Le concept de smash est ici le même que dans SSB, à savoir une attaque au fort potentiel de dégâts et de projection. Pour effectuer un smash, il faut appuyer sur ``P`` tout en inclinant complètement et rapidement le stick dans la direction souhaitée ; si le joueur effectue l'inclinaison en plus d'un dixième de seconde, ou si elle n'est pas maximale, alors l'action sera considérée comme une attaque physique. Il existe donc 3 smash : ``P+Côté``, ``P+Bas``, ``P+Haut``. Pour empêcher le joueur d'abuser des smashs, on leur donnera un temps d'exécution plus long que pour les attaques physiques classiques, ainsi qu'un coût en mana minimal. Il est possible de charger son smash en maintenant les boutons appuyés, rendant ce dernier encore plus puissant, mais laissant par la même occasion plus d'opportunités aux ennemis d'annuler le smash avec certains contrôles, le personnage étant immobile durant la charge. De plus, du mana additionnel est consommé durant la charge. Pour empêcher le joueur d'effectuer des smashs trop puissants, la charge a une durée maximale de 2 secondes. Si la barre de mana finit de se vider avant la fin des 2 secondes, le smash est exécuté immédiatement.
Toutes ces caractéristiques font en général du smash une attaque à utiliser avec précaution, occasionnellement en tant qu'outil à dégâts, mais principalement en tant que //finisher// afin d'éjecter l'ennemi hors du terrain.
Techniquement le smash est similaire à une attaque physique simple, c'est à dire une ou plusieurs ZA solidaires de l'attaquant qui possèdent uniquement des dégâts de pourcentage et un CC de projection. Cependant, les pourcentages et le CC de projection augmentent avec la charge.
==== Prises ====
Les prises permettent en appuyant sur une gâchette arrière de la manette d'attraper une cible, au corps à corps ou sur une courte distance selon les personnages, puis de la projeter dans la direction choisie avec le stick. Tant que la direction n'est pas choisie, la cible est totalement incapacitée, situation qui peut durer jusqu'à 4 secondes ; ce temps peut néanmoins être drastiquement réduit si la victime se débat énergiquement avec de multiples mouvements de stick. De plus, l'attaquant est immobilisé et réduit au silence tant qu'il n'a pas lancé sa cible. Cependant, il peut utiliser ses attaques physiques, qui seront toutes dirigées sur la cible, mais peuvent toucher un autre adversaire passant trop près.
Techniquement, une prise est une ZA solidaire du personnage qui ne possède pas de dégâts de pourcentages, mais juste un CC lien entre la cible et la ZA. Une fois le lien infligé, la ZA retourne vers l'attaquant (si nécessaire) puis transforme le lien en immobilisation ; la ZA est supprimée à ce moment là, et donc le CC lien. Si l'attaquant choisit la direction du lancer avec le stick avant la fin de l'immobilisation, ce dernier est annulé et un CC projection est appliqué à la cible.
=== Postures défensives ===
==== Bouclier ====
Le bouclier, tout comme dans SSB, entoure le personnage d'une zone qui encaisse les attaques ennemies. Néanmoins, son utilisation diffère de par son coût en mana : contrairement à SSB, le bouclier ne se réduira pas tant qu'il n'aura pas encaissé de coups, mais le joueur se voit dans l'obligation de l'activer au bon moment pour éviter de perdre inutilement de sa ressource bleue préférée. Le bouclier guérit automatiquement de ses blessures, mais bien plus lentement que dans SSB ; si un ennemi en vient à bout, alors le joueur est étourdi pendant quelques secondes, puis le bouclier est complètement réinitialisé.
Lors du lancement du bouclier, une courte animation est lancée, durant laquelle le bouclier n'est pas encore actif, et ne consomme donc pas de mana ni ne protège des attaques ennemies. Ensuite, il prend son image normale, à laquelle est appliquée un masque de blanchissement des couleurs qui augmente en fonction des PV manquants du bouclier. Lorsqu'il éclate, l'image normale du bouclier disparaît et l'animation correspondante est lancée, en même temps que le personnage devient étourdi.
Le bouclier absorbe tous les CC sauf la projection, qu'il transmet au personnage. Néanmoins cette projection sera moindre car le bouclier rajoute beaucoup de poids au personnage. Si le joueur maintient le bouclier, il pourra le conserver dans les airs.
Pour activer le bouclier, on pressera l'une des gâchettes arrières de la manette. Cette touche étant assignée à l'esquive statique aérienne, il n'est pas possible d'activer les bouclier dans les airs.
==== Esquives ====
Les esquives permettent au personnage d'éviter toute attaque ennemie pendant un court laps de temps. Les esquives, tout comme le bouclier, coûtent du mana, obligeant le joueur à s'en servir à bon escient. Il existe 4 types d'esquives :
- L'esquive latérale, qui consiste en une esquive effectuée en mouvement sur une courte distance ; le personnage ignore alors toutes les collisions avec les autres entités. Elle s'effectue à partir du bouclier en inclinant au maximum le stick vers la gauche ou vers la droite, selon la direction souhaitée.
- L'esquive latérale aérienne, qui correspond à une esquive latérale effectuée dans les airs. Le personnage ne peut effectuer qu'une seule esquive de ce genre avant de retoucher le sol, pour éviter d'en faire un outil de mobilité et de rattrapage sur le terrain. Aussi, cette esquive réinitialise toutes les forces que le personnage subissait (dont la gravité qui se réapplique donc selon sa position à la fin de l'esquive). Le bouclier n'étant pas utilisable dans les airs, on utilisera les mêmes touches que l'esquive latérale, mais en commençant par incliner le stick.
- L'esquive statique, équivalente à l'esquive latérale, sans la notion de mouvement. Le coût en mana est moindre. On l'effectue à partir du bouclier en inclinant complètement le stick vers le bas.
- L'esquive statique aérienne, qui correspond à une esquive statique effectuée dans les airs. Elle conserve les forces déjà appliquées au personnage et s'effectue en appuyant sur le bouton du bouclier.
Chaque type d'esquive possède deux animations distinctes pour chaque direction latérale. Techniquement, l'esquive correspond en fait à cette animation associée à un déplacement ou non selon que l'esquive soit statique ou non.
=== Contrôles de foule (CC) ===
Project Warrior exploite un élément de gameplay très courant dans les MOBA mais peu présent dans SSB : les contrôles de foule, abgrégés en CC (Crowd Controls). Plutôt que de faire une longue explication théorique, listons directement dans un joli tableau les différents CC de base ainsi que leurs effets respectifs :
| **Nom** | **Description** |
| Projection | Le contrôle le plus courant dans Project Warrior, que nous avons déjà évoqué un peu plus tôt. Comme son nom l'indique, il va appliquer une force sur la cible, la projetant dans une certaine direction avec une certaine puissance. C'est un CC un peu particulier de par son omniprésence dans le jeu qui permet le dynamisme des combats ; de plus, il est essentiel au gameplay puisque c'est en éjectant les adversaires hors du terrain que le joueur obtiendra des kills et s'appropriera la victoire. |
| Ralentissement | Diminue la vitesse de déplacement de la cible. |
| Lien | La cible est liée à une entité : elle ne peut pas s'éloigner de plus d'une certaine distance de cette entité. Si cette distance est nulle, la cible et l'entité sont collées. |
| Aveuglement | Empêche la cible d'utiliser ses attaques physiques. |
| Silence | Empêche la cible d'utiliser toute ressource ayant recours au mana (sorts, smashs, bouclier et esquives), mais ne modifie pas le niveau de sa barre de mana, qui continue à se remplir si elle n'était pas pleine. |
| Siphon | Vide tout ou partie de la jauge de mana de la cible ; contrairement au silence, cela ne l'empêche pas d'utiliser ses sorts si il lui reste suffisemment de mana. |
Il existe d'autres CC qui sont réalisés à partir des CC de base. On leur donne un nom particulier car ils sont assez courants dans les capacités des personnages. Voici la liste de ces CC plus complexes :
| **Nom** | **Description** | **Réalisation** |
| Immobilisation | Le nom est assez explicite : la cible est tout simplement immobilisée et ne peut donc plus marcher, courir ou sauter ; néanmoins elle peut toujours attaquer ou se défendre. Un personnage immobilisé en l'air voit toutes les forces qui lui étaient appliquées réinitialisées, dont la gravité qui se réapplique donc par la suite selon sa position. La durée de l'immobilisation peut ou non être réduite par des mouvements de stick. | L'immobilisation est un CC lien distance 0 avec une ZA statique et non solidaire de l'attaquant. |
| Étourdissement | Le contrôle le plus puissant du jeu : la cible est totalement incapacitée, c'est-à-dire à la fois immobilisée, aveuglée et réduite au silence. | Il consiste donc en la combinaison des CC immobilisation, aveuglement et silence. |
La traduction graphique des CC est composée de deux parties. La première est une animation, ou une image affichée par l'attaque qui l'inflige. Cet affichage dépend de l'attaque et n'est pas forcément très lisible. La deuxième partie est une petite icône qui s'affiche à côté du nom du personnage et de ses pourcentages, qui elle est la même quelle que soit la façon dont le CC est infligé : c'est un moyen sûr de savoir les CC appliqués au personnage à un moment donné.
== Personnages ==
=== Caractéristiques communes ===
Chaque personnage possède différentes caractéristiques qui influencent la façon dont il intéragit avec l'environnement et les autres personnages.
==== Attaques ====
La puissance d'une attaque et son utilité sont définies par les CC et dégâts qu'elle inflige, mais aussi par d'autres caractéristiques telles que la portée ou encore la vitesse. Cependant, ces valeurs n'ont aucune répercussion technique directe : aucune vitesse n'est définie pour une attaque, par exemple. Ces valeurs dépendent du script de l'attaque, qui va la faire évoluer et se déplacer sur une plus ou moins grande distance et plus ou moins vite. Ces caractéristiques seront utilisées à titre indicatif dans la liste des personnages. Voici un tableau décrivant chaque caractéristique :
| **Caractéristique** | **Description** |
| Dégâts | Définit les dégâts en pourcentage que va infliger l'attaque. |
| Vitesse | Définit le temps d'animation de l'attaque, temps durant lequel le personnage est vulnérable car dans l'impossibilité d'effectuer une quelconque autre action. |
| Portée | Définit la distance de l'attaque par rapport à l'attaquant, permettant à celui-ci de toucher des cibles situées plus ou moins loin. |
==== Physique ====
Chaque personnage possède un poids : plus le poids est élevé, plus le personnage sera lent, mais il sera aussi plus difficile à projeter, et donc à vaincre.
=== Représentation en mémoire ===
Les personnages sont placés dans le même dossier, dont le contenu est scanné au début du jeu. Chaque personnage est un dossier contenant une image ``preview.png``, un fichier texte ``name`` de deux lignes, la première étant le nom et la deuxième une courte description, un script ``perso.lua`` et ``preview.lua`` et différentes ressources chargées et utilisées par le script. Le nom du dossier n'a pas d'importance mais il ne doit contenir ni caractères spéciaux, ni espaces, ni caractères non-ascii.
Le stage est constitué de différentes fonctions. Ces fonctions sont regroupées en différentes catégories. Toutes les ressources chargées dans le script sont automatiquement libérées par le programme à la fin du script, elle ne doivent pas l'être depuis le script.
==== Sélection du personnage ====
Lors de l'écran de sélection des personnages, le fichier ``perso.lua`` n'est pas chargé. L'image ``preview.png`` est utilisée pour afficher la miniature dans la liste des personnages. Le fichier ``name`` est utilisé pour afficher la nom et la description du personnage quand il est sélectionné.
Enfin, le script ``preview.lua`` contient plusieurs fonctions :
- ``validate`` : cette fonction retourne un booléen indiquant si le personnage a été débloqué ou non. À cette fin, le script utilise l'API du programme permettant de vérifier quels events on étés validés. C'est la première fonction du script. Si elle n'est pas présente, le personnage sera considéré toujours débloqué.
- ``init`` : cette fonction est la deuxième à être appelée dans le script après ``validate``, donc potentiellement la première, pouvant servir à initialiser certaines ressources. Elle est complètement facultative, et une fonction init trop lourde ralentira l'ouverture de l'écran de sélection des personnages.
- ``loadPreview`` : cette fonction prend en paramètre la couleur du personnages (une énumération), et charge sous le nom de ``preview`` l'image correspondante. Cette image est affichée dans la zone des joueurs : c'est une image plus grande et plus détaillée que ``preview.png``.
==== Déplacements ====
Durant le jeu, seul le script ``perso.lua`` est chargé. Il possède une fonction ``init`` qui doit charger toutes les ressources utilisées par le personnage durant le jeu, définissant aussi son poids et qui est appelée lors du début d'une partie. Cette fonction reçoit un argument qui est la couleur du personnage : elle doit adapter les ressources chargées en fonction. Il possède en plus d'autres fonctions utilisées à différents moments et dans différentes occasions :
- ``stand`` : cette fonction correspond au personnage qui reste sur place.
- ``walk`` : cette fonction définit l'image qui est affichée lorsque le personnage marche. Elle doit aussi déplacer à chaque fois les zones de collision si nécessaire. Elle reçoit en argument la direction (LEFT ou RIGHT) du déplacement.
- ``run`` : comme ``walk*``, sauf que le personnage se déplace en courant.
- ``stop`` : cette fonction correspond à l'animation lorsqu'un personnage arrête de courir.
- ``jump``, ``jumpAir`` : ces fonctions marche de la même façon que ``walk*`` et correspondent respectivement à un saut et un double saut.
- ``down``, ``fastDown`` : ces fonctions correspondent respectivement à l'animation de descente après un saut et de descente rapide.
- ``land`` : cette fonction correspond à l'atterrissage du personnage.
- ``turn`` : cette fonction définit l'animation affichée lorsque le personnage change de direction. Elle prend en paramètre la direction (LEFT ou RIGHT) ainsi qu'une des fonctions précédentes correspondant au déplacement actuel, afin de choisir l'animation adaptée. Pour les fonctions ``stand``, ``walk``, ``jump``, ``jumpAir``, ``down``, ``fastDown``, l'animation sera spécifique au déplacement. Pour la fonction ``run``, ``turn`` fera appel à ``stop``. Pour les fonctions ``stop`` et ``land``, ``turn`` ne lance aucune animation.
Toutes ces fonctions ne prennent qu'un seul paramètre : le nombre de FPS depuis le début de l'animation. La valeur de retour est un booléen (un nombre, 0 ou 1), qui indique si l'animation est terminée. La dernière image chargée correspond à l'image qui restera affichée tant qu'aucune autre fonction n'est appelée, donc après la fin d'une fonction de mouvement qui a retournée 1.
==== Attaques ====
Cette partie est dédiée à la description du fonctionnement d'une attaque. Elle est assez complexe puisqu'elle va décrire les fonctions lançant les attaques, mais aussi comment une attaque est créée.
===== Callbacks =====
- ``attack`` : cette fonction affiche l'animation d'une attaque physique. Son premier argument est le nombre de FPS écoulés depuis le début de l'attaque (lors du premier appel de l'attaque elle reçoit 0). Elle doit retourner 1 quand l'attaque est terminée. Son deuxième argument est la direction de l'attaque : ``NONE``, ``RIGHT``, ``LEFT``, ``UP`` ou ``DOWN``. La façon dont l'attaque est créée est décrite dans la partie suivante.
- ``spell`` : cette fonction affiche l'animation du personnage lorsqu'il lance un sort. Elle reçoit les deux mêmes arguments que ``attack`` et doit elle aussi retourner 1 lorsque l'animation est terminée. Elle reçoit en plus un argument indiquant si la touche est toujours appuyée ou pas, permettant entre autre de faire des chargements.
- ``smash`` : cette fonction affiche l'animation du personnage lorsqu'il charge un smash. Les paramètres sont les même que pour la fonction ``spell``.
- ``catch`` : cette fonction affiche l'animation d'une prise. Elle doit créer une attaque avec une ZA qui s'éloigne du personnage et n'inflige qu'un CC lien, puis revient vers le personnage et là lui inflige un étourdissement.
===== Fonctionnement =====
Lors de l'appel d'une des fonctions citées ci-dessus, le script doit se charger de l'animation du personnage mais aussi et surtout créer l'attaque. Une attaque est donc constituée d'une ou plusieurs ZA.
Lors de la création d'une ZA, on y associe quatre fonctions de callback :
+ Une fonction qui est appelée à chaque FPS : elle doit déplacer la ZA et la dessiner à l'écran. Elle reçoit comme argument le nombre de FPS écoulés depuis la création de la ZA et doit retourner -1 quand la ZA est détruite, 0 sinon. Le déplacement d'une ZA peut se faire dans deux repères : local ou global, mais est toujours relatif (il n'y a pas de fonction ``setPosition`` par exemple). Le repère local varie selon que la ZA soit solidaire ou non du personnage. Si oui, c'est le repère du personnage, sinon, c'est le repère de la ZA. Le repère global est celui du terrain, mais il est déconseillé de trop l'utiliser (une attaque va tout droit par rapport à sa direction, non parallèlement au sol).
+ Une fonction qui est appelée quand la ZA entre en contact avec quelque chose. Ça peut être le terrain (donc un mur), un personnage ou une autre ZA. Le premier argument est donc une énumération qui indique le type du second argument, qui lui est l'entité avec laquelle la ZA est entrée en contact. Elle peut donc essayer de lui appliquer des CC et/ou des dégâts, changer sa trajectoire... Cette fonction doit retourner 1 si la ZA est détruite après le contact.
+ Une fonction qui est appelée lorsque la ZA reçoit des dégâts. Cela permet à la ZA de les transmettre normalement au personnage, de les atténuer, de les absorber, de les convertir en soin... Cette fonction doit retourner 1 si la ZA est détruite.
+ Une fonction qui est appelée lorsque la ZA reçoit un CC. Elle sera donc appelée autant de fois que la ZA reçoit de CC. Elle peut décider de les ignorer, de se les appliquer vraiment, de changer légèrement leurs effets, de les transmettre au personnage... Cette fonction doit retourner 1 si la ZA est détruite.
Lors de la création de la ZA, on doit aussi préciser si elle est fantôme et/ou spectre. On doit aussi préciser si la ZA est sensible ou non à la gravité. La fonction de création de ZA retourne un entier, l'identifiant de la ZA, qui est passé en premier argument aux quatre fonctions de la ZA.
L'API dispose de fonctions utilitaires, qui possèdent toutes un nom de la forme ``require*``, qui permettent de vérifier des contraintes dans la fonction d'une attaque :
- ``requireMana`` : cette fonction prend deux paramètres, le premier étant la quantité de mana et le deuxième l'unité. Il existe trois unités, ``ABS``, donc une valeur absolue, ``PERCENT``, en pourcentage du total et ``RELPERCENT``, en pourcentage du mana restant. Si le personnage possède assez de mana, cette quantité est enlevée du quota de mana du personnage et la fonction retourne ``true``, sinon elle retourne ``false``. Dans le cas d'un smash, par exemple, on utilisera plein de petit appels à ``requireMana`` au cour du chargement. Quand la fonction retourne ``false``, le smash se déclenche avec une puissance qui dépend du paramètre FPS.
- ``requireGround`` : cette fonction permet de tester si le personnage est sur le sol ou pas. Elle ne prend pas d'argument et retourne simplement un booléen.
Nous allons maintenant détailler ce qu'il se passe lors du contact entre deux ZA. Lors du contact, la fonction de callback de contact (#2 dans la liste) est appelée pour chacune des ZA avec en argument l'autre ZA . Dans le cas d'une ZA fantôme, seule la callback de cette dernière est appelée, l'autre ZA ignorant la collision. Si les deux ZA sont fantômes, aucune callback n'est appelée. Dans cette fonction, chacune inflige des dégâts et/ou des CC à l'autre : toutes ces attaques ne sont pas appliquées immédiatement, elles sont stockées. À la fin de l'exécution de ces deux fonctions, si une retourne 1, la ZA est détruite et ne reçoit donc ni les dégâts ni les CC. Les (ou la) ZA restantes vont maintenant recevoir les dégâts, à travers l'appel à leur callback #3. Si une de ces fonctions retourne 1, la ZA correspondante est détruite avant de recevoir les CC. Enfin, les CC sont appliqués dans l'ordre dans lequel ils ont été infligé et la callback #4 est donc appelée une ou plusieurs fois. Si un appel retourne 1, la ZA correspondante est détruite avant de recevoir les CC restants.
Comme un personnage peut se déplacer durant l'application d'une attaque (entre l'appui et le relâchement de la touche), certains personnages qui font un chargement veulent pouvoir changer l'animation du déplacement pendant le chargement. Pour cela, il faut définir une variable globale au script, et les fonctions d'animation changent ce qui est affiché en switchant sur la valeur de cette variable.
==== Défenses ====
Cette partie est dédiée aux fonctions de défense, telles l'esquive ou le bouclier :
- ``shield`` : cette fonction doit dessiner le personnage avec le bouclier activé. Le premier et seul argument est bien sûr le nombre de FPS écoulés depuis le premier appel.
- ``staticDodge``, ``flyingStaticDodge`` : correspondent respectivement à l'esquive statique et l'esquive statique aérienne. Ces fonctions ne reçoivent pas le nombre de FPS écoulés mais le pourcentage d'accomplissement de l'action sous la forme d'une nombre entre 0 et 1.
- ``dashDodge``, ``flyingDashDodge`` : correspondent respectivement à l'esquive latérale et l'esquive latérale aérienne. Ces fonctions reçoivent aussi le pourcentage d'accomplissement de l'action.
==== Animations spéciales ====
Cette partie décrit les fonctions correspondant aux animations spéciales des personnages, ces fonctions reçoivent en premier argument le nombre de FPS depuis le début de l'animation :
- ``appear`` : cette fonction correspond à l'animation du personnage lorsqu'il apparait sur le terrain. Elle doit retourner 1 lorsque l'animation est terminée.
- ``won`` : cette fonction correspond à l'animation d'un personnage qui se vante après sa victoire. Cette animation doit pouvoir boucler.
- ``lost`` : cette fonction correspond à l'animation d'un personnage qui se lamente après sa défaite. Cette animation doit pouvoir boucler.
- ``sent`` : cette animation correspond à un personnage qui est projeté. Elle reçoit en second argument un vecteur correspondant à la direction et à la force de la projection.
=== Liste des personnages ===
Dans un premier temps, l'objectif est de développer 4 personnages équilibrés, charismatiques et aux gameplays très différents.
//Les indicateurs// ``LOW, MEDIUM, HIGH`` //ne sont pas applicables à toutes les attaques et représentent une moyenne générale définissant le gameplay global du personnage. De plus, deux indicateurs similaires ne réprésenteront pas les mêmes valeurs selon le type d'attaque auquel ils s'appliquent.//
==== Hybride ====
Il serait l'objectif premier de développement car exploitant la plupart des mécaniques souhaitées (sorts à distance, gapclosers, attaques physiques relativement puissantes...), et possédant des statistiques égales et équilibrées permettant de construire les autres personnages autour de cette moyenne. Au niveau du background, il constituerait probablement le personnage principal.
===== Caractéristiques =====
| **Caractéristique** | **Niveau** |
| Dégâts physiques | ``MEDIUM`` |
| Vitesse des attaques physiques | ``MEDIUM`` |
| Portée des attaques physiques | ``MEDIUM`` |
| Dégâts magiques | ``MEDIUM`` |
| Vitesse des sorts | ``MEDIUM`` |
| Portée des sorts | ``MEDIUM`` |
| Poids | ``MEDIUM`` |
===== Sorts =====
| **Touches** | **Description** |
| ``M`` | Envoie un projectile en ligne droite dans la direction du personnage. En maintenant ``M`` appuyé, on peut charger le projectile jusqu'à un certain seuil, augmentant sa taille, ses dégâts et sa puissance de projection. Le personnage est immobilisé durant la canalisation ; néanmoins, le coût en mana est activé dès le début du chargement, ce qui permet avec la regénération passive de mana de rembourser le coût si on charge suffisemment longtemps. |
| ``M+Bas`` | Le personnage provoque une onde de choc qui se propage simultanément à droite et à gauche, infligeant des dégâts et ralentissant tous les ennemis sur son passage. L'attaque n'est utilisable qu'au sol, et l'onde de choc se termine lorsqu'elle recontre le vide ou un mur.
| ``M+Côté`` | Un dash en ligne droite vers la direction choisie (droite ou gauche). Lors du dash, le personnage ignore les collisions avec les autres entités, il est donc insensible aux dégâts et aux CC. |
| ``M+Haut`` | Fonctionne sous forme de toggle. Lorsque la compétence est activée, la portée des attaques physiques est augmentée ; néanmoins, chaque attaque améliorée coûte du mana, ce qui empêche une utilisation intensive de cette capacité. |
==== Brute ====
Un personnage possédant d'importants dégâts physiques et magiques, avec une cadence lente pour compenser cette puissance. Aussi, il doit être au corps à corps pour infliger ses dégâts, ce qui n'est pas évident de par sa faible vitesse de déplacement. Un sort de contrôle de portée ``MEDIUM`` ou ``HIGH`` permettrait de se rapprocher plus aisément des adversaires ; il est préférable pour raison de cohérence avec sa physique lourde qu'il ne possède pas de gapcloser.
===== Caractéristiques =====
| **Caractéristique** | **Niveau** |
| Dégâts physiques | ``HIGH`` |
| Vitesse des attaques physiques | ``LOW`` |
| Portée des attaques physiques | ``MEDIUM`` |
| Dégâts magiques | ``HIGH`` |
| Vitesse des sorts | ``LOW`` |
| Portée des sorts | ``LOW`` |
| Poids | ``HIGH`` |
==== Assassin ====
Un personnage opposé à la brute de par son gameplay nerveux et très rapide. Il base quasiment tous ses dégâts sur les attaques physiques, qui possèdent des dégâts assez faibles mais une vitesse d'enchaînement élevée. Sa courte portée l'oblige à être collé à ses ennemis, ce qu'il parvient à faire assez aisément grâce à 2 sorts de mobilité et une grande vitesse de déplacement.
===== Caractéristiques =====
| **Caractéristique** | **Niveau** |
| Dégâts physiques | ``LOW+`` |
| Vitesse des attaques physiques | ``HIGH`` |
| Portée des attaques physiques | ``LOW`` |
| Dégâts magiques | ``LOW`` |
| Vitesse des sorts | ``HIGH`` |
| Portée des sorts | ``HIGH`` |
| Poids | ``LOW`` |
==== Mage ====
Un personnage assez équilibré, qui à la différence de l'hybride basera beaucoup de ses dégâts sur les sorts et peu sur les attaques physiques. Sa mobilité n'est pas très grande du fait qu'il ne possède aucun sort prévu à cet effet.
===== Caractéristiques =====
| **Caractéristique** | **Niveau** |
| Dégâts physiques | ``LOW`` |
| Vitesse des attaques physiques | ``MEDIUM`` |
| Portée des attaques physiques | ``MEDIUM`` |
| Dégâts magiques | ``HIGH`` |
| Vitesse des sorts | ``MEDIUM`` |
| Portée des sorts | ``MEDIUM`` |
| Poids | ``MEDIUM`` |
== Stages ==
=== Description ===
Les stages sont les terrains dans lesquels les combats ont lieu. Ils doivent dégager une ambiance particulière et leur forme peut fortement influencer la façon de combattre. Les stages ne doivent pas être trop grands car ils peuvent apparaître entièrement à l'écran si les personnages sont très éloignés. De plus, ils ne doivent pas être complètement fermés car sinon les personnages ne peuvent pas mourir. Lorsque la mort subite commence, le stage se modifie pour devenir plus dangereux, plus agressif.
=== Éléments ===
Les stages possèdent différentes éléments, qui possèdent des caractéristiques différentes :
- Chaque élément possède un facteur de rebondissement. Un facteur de 0 correspond à un mur normal, une valeur plus élevée faisant rebondir tout objet mouvant entrant à son contact.
- Les éléments possèdent aussi un facteur de glissement, une valeur de 0 empêchant tout dérapement, même en pente. 1 correspond à une valeur moyenne.
=== Intéraction ===
Les stages peuvent être animés, avec des murs qui bougent, formant des plateformes, des pièges qui se referment... De plus, les stages peuvent changer dynamiquement au cours d'un combat, en fonction du temps, des actions des joueurs... Cependant, des modifications trop rapides sur un stage peuvent entraîner des bugs, c'est donc aux créateurs des terrains de s'assurer qu'il ne sont pas modifiés trop vite.
=== Représentation en mémoire ===
Les stages sont tous placés dans le même dossier, dont le contenu est scanné au lancement du jeu. Chaque stage est un dossier contenant une image ``preview.png`` et un fichier texte ``name`` d'une seule ligne, utilisés lors de l'écran de chargement de stage pour le présenter, deux scripts ``validate.lua`` et ``stage.lua`` et différentes ressources qui seront chargées et utilisées par le script lors d'une partie sur le terrain. Le nom du dossier n'a pas d'importance, mais il est conseillé de ne pas y inclure de caractère spéciaux, non-ascii ni d'espaces.
Le script ``validate.lua`` ne doit contenir qu'une seule fonction, ``validate``, qui retourne un booléen indiquant si le stage a été débloqué ou non. À cette fin, le script utilise l'API du programme permettant de vérifier quels events on étés validés. Si la fonction ou le script n'existent pas, le stage est considéré comme toujours débloqué.
Le script ``stage.lua`` est constitué de différentes fonctions qui seront appelées par le programme. La première fonction appelée est la fonction ``init``, sans arguments : elle va initialiser les différentes variables globales du script (si nécessaire), charger les ressources graphiques à travers le moteur graphique, définir les zones de collisions dans le moteur physique, les zones d'apparition des personnages et la taille maximale du terrain à travers l'interface fournie par le programme.
La fonction ``subitDeath`` est appelée lors de l'entrée en mort subite. Elle doit modifier les fonctions de callback et le terrain.
==== Physique ====
Les zones physiques sont les zones de //contact// indiquée au moteur physique. Elles possèdent toutes la caractéristiques décrites dans la section "Éléments".
À chaque zone physique ajoutée au terrain peut aussi être associée deux fonctions du script qui seront respectivement appelées quand un personnage ou une attaque entre en contact avec la zone physique. Ces fonctions reçoivent deux arguments : l'entité en question et le point de contact. Cela permet de faire des terrains dynamiques avec des pièges ou des murs qui prennent des dégâts avant d'être détruits. Il est aussi possible de leur rajouter deux autres callbacks (qui elles sont facultatives) : une qui est appelées quand la zone reçoit des dégâts (pour permettre la création de zones destructibles par exemple) et une quand la zone reçoit un CC. Ces deux callbacks reçoivent en premier argument la ZA qui leur a infligé les dégâts/CC.
Il est aussi possible de créer des zones dites //virtuelles// : ces zones ne sont pas considérées lors des calculs de collision, et ne possèdent donc pas de facteurs de glissement ou de rebondissement. Cependant, on peut leur définir les deux callbacks présentées ci-dessus. Ces zones sont juste des capteurs de présence d'entités. Cependant, leurs fonctions de callback ont trois arguments. Le premier reste le même. Cependant, le second n'est pas un point mais l'intersection de la zone virtuelle et de l'espace de l'entité : c'est leur surface commune. Le troisième est le nombre de fois que la fonction de callback est appelée pour cette collision. En effet, l'entité peut rester à l'intérieur de cette zone et donc la collision peut durer. La fonction sera donc réappellée à chaque FPS jusqu'à la fin de la collision : le troisième argument peut être considéré comme la durée en FPS depuis le début de la collision.
Toutes les zones peuvent être modifiées, ajoutées et/ou supprimées dynamiquement durant la partie. Si la suppression ne pose pas de problème, l'ajout et la modification peuvent. En effet, dans le cas d'un ajout ou d'un déplacement trop rapide, des bugs de collision peuvent apparaître. Il est donc conseillé de tester l'apparition d'un objet avec une zone virtuelle avant de faire apparaître une zone de contact. Dans le cas des déplacements, un déplacement (relativement) lent déplacera les entités en contact avec lui, mais un déplacement trop rapide aura les mêmes risques qu'une apparition.
==== Timers ====
Les timers définissent des fonctions de callback qui sont appelées au bout d'un certain temps. Un timer peut être remis à zéro à n'importe quel moment. Un timer remis à zéro par son callback se réappellera donc à intervalles réguliers.
Un exemple d'utilisation serait l'apparition d'une zone de contact : le script va créer une zone virtuelle à la position de la zone de contact avec pour callback une fonction qui remet à zéro le timer et lance un timer court avec comme callback une fonction qui va supprimer la zone virtuelle et créer la zone de contact. Le timer sera donc remis à zéro tant qu'il y aura une entité dans la zone virtuelle et la zone de contact sera créée quand il n'y aura plus de contact durant le laps de temps du timer.
=== Liste des stages ===
La liste suivante présente les stages //officiels// qui devront être présents dans la version 1 :
| **Nom du stage** | **Description** |
| Space platform | Ce stage est similaire au terrain //destination finale// de SSB : c'est un terrain plat, de taille moyenne, sans reliefs ni pièges ni aucune interactivité. C'est le terrain neutre par excellence. |
| Jungle | Ce stage est une jungle, avec du relief et de nombreux pièges sous la forme de plantes carnivores qui attaquent les personnages qui passent à proximité ou de trous avec des pics. Ce stage permet de tester l'interactivité des terrain et le dynamisme des terrains. |
TODO finir la liste.
= Détails techniques =
== Programmation ==
=== Outils ===
Ce programme sera codé en C/C++ : la majorité du code sera en //C++11// (la dernière norme, de 2011), avec un code majoritairement orienté-objet, mais certaines parties du code pourront être codées en C, si jugé pertinent. Le jeu devra être portable, au moins entre Linux, Windows et MacOS.
La partie graphique du jeu sera géré avec la //SDL 2.0// et //OpenGL 2//, des bibliothèques. Le son sera lui aussi géré par la //SDL//.
Le moteur physique sera programmé à l'aide de la bibliothèque Box2D.
Le jeu pourra utiliser d'autres bibliothèques comme //boost// si jugé utile : l'objectif n'est pas d'avoir le moins de dépendances possible.
=== Scripting ===
Project Warrior devra être scriptable en //lua//. Cette capacité sera utilisée notemment lors du chargement des personnages et des stages. À cette fin, une API //lua// pour permettre à ces scripts de communiquer avec le programme devra être développée. Elle devra permettre d'accéder au moteur graphique mais aussi au moteur physique et à certaines informations comme les positions des différents personnages.
À travers son accès au moteur graphique, un script doit pouvoir charger une image, une animation ou encore une texture et l'afficher à l'écran avec certaines transformations comme des rotations ou des zooms. Le script peut aussi dessiner des primitives avec une texture préalablement chargée. Toutes les ressources chargées par le script seront libérées automatiquement à la fin du script.
=== Syntaxe ===
==== Nommage ====
Les variables commencent par des minuscules. Dans le cas d'une variable composée de plusieurs mots, on met une majuscule au début des chaque mot à l'exception du premier. Par exemple, une variable stockant des vies pourra s'appeler ``nombreDeVies``. Si la variable est un membre privé d'une classe, elle sera préfixée par ``m_``. Si la variable est globale à l'ensemble du programme, elle sera préfixée par ``G_``. Enfin, si elle est globale à un fichier uniquement (c'est à dire déclarée avec ``static``), elle sera préfixée avec ``Gs_``. Dans la mesure du possible, les noms de variable devront être suffisamment explicites pour ne pas nécessiter d'explications. Dans le cas contraire, la description se fera dans un commentaire à la déclaration de la variable.
Les constantes globales, ou les defines, sont écrites intégralement en majuscules, et les mots sont séparés par des ``_``. Le nombre maximum de vies pourrait par exemple être nommé ``NOMBRE_MAX_VIES``.
Les fonctions sont nommées de la même façon que les variables. Les classes sont quand à elles nommées de la même façon que les variable normales, à l'exception qu'elles commencent par une majuscule. Il en va de même pour les structures et les énumérations. Les namespaces sont nommés entièrement en minuscule, si possible en un seul mot, sinon les mots sont séparés par des ``_``.
==== Placement des accolades ====
Lors de la création d'une classe, il y a un retour à la ligne avant les accolades ouvrantes et fermantes. Il en va de même pour la déclaration des fonctions et les blocs simples.
Cependant, pour les blocs conditionnels et de boucle, l'accolade est sur la même ligne que la condition ou la boucle. Dans le cas où le contenu du bloc ne fait qu'une ligne, il est possible de ne pas mettre d'accolades. Cependant, même s'il n'y a qu'une instruction, si elle fait plusieurs ligne ou si il y a des commentaires, les accolades sont obligatoires.
==== Espaces ====
Lors d'une copie de valeur, il faut des espaces simples autourt du ``=``. Dans les conditions, les instructions de comparaison doivent aussi être entourées d'espaces, ainsi que les différents opérateurs. Il ne faut cependant pas d'espaces entre les parenthèses et les conditions intérieures dans les boucles et les conditions.
L'indentation n'est pas faite avec des tabulations mais avec 4 espaces.
== Moteurs ==
=== Graphique ===
Le moteur graphique est celui qui s'occupe du chargement des images et autres ressources graphiques, puis qui les affiche à l'écran. Nous allons détailler ici ses différentes fonctionnalités.
Le moteur doit être capable de gérer n'importe quelle résolution d'écran au dessus d'une valeur minimum. Il doit fournir la notion de résolution virtuelle, résolution utilisée ingame qui est différente de la réelle. Il adaptera en zoomant et en plaçant des bandes noires sur les côtés pour préserver le ratio.
Il permet de charger et d'afficher n'importe quel format d'image géré par //SDL2_image//, et de charger certains formats vidéo (liste à préciser lors du développement). Chaque image chargée l'est sous un nom unique, servant à y accéder par la suite. Il est possible de créer des namespaces de noms, limitant les risques de collision entre des noms déjà pris. De plus, lors de la destruction d'un namespace, toutes les ressources chargées dans ce namespace sont automatiquement libérées. Pour accéder à une image dans un namespace, on utilise la syntaxe ``namespace/imgname``. Par conséquent, le caractère ``/`` est interdit dans les noms d'image, ainsi que tous les caractères non ascii. Il est possible d'inclure des namespaces dans des namespaces pour créer une arborescence. Les ressources chargées à l'extérieur de tout namespace le sont en fait dans le namespace dit //root// : ``/``. Le nom d'une image est donc similaire à un chemin UNIX.
À l'instar d'un système de fichier UNIX, il est aussi possible de créer des liens entre des ressources graphique. Une ressource graphique pourra donc être adressée par plusieurs noms. La ressource n'est libérée que quand il n'y a plus un seul lien qui pointe vers elle.
Il est possible de définir un //hotpoint// pour chaque image chargée. Cette valeur est un point de l'image qui correspondra à sa valeur (0;0), c'est à dire que lorsque l'on affiche l'image à une coordonnée donnée, c'est ce point que aura la coordonnée indiquée, et le reste de l'image sera dessinée autour.
Le moteur graphique permet aussi de charger des fonts bitmap, et de s'en servir pour afficher du texte.
Le moteur graphique doit aussi permettre de dessiner toute forme de primitive graphique, que ce soit des points, traits ou polygones pleins ou vides. Il sera possible de leur attribuer ou une couleur ou une texture indiquée par son nom.
Le moteur graphique peut aussi charger et afficher des vidéos. Cependant, les vidéos ne peuvent pas être utilisées comme texture et doivent être évitée la majorité du temps car elles consomment beaucoup de CPU. Elles peuvent notamment être utilisées pour les accomplissement d'event ou encore pour le fond des stages.
Comme on pouvait le faire avec //OpenGL 2//, le moteur permet d'effectuer des transformations sur le repère. Ces transformations sont la rotation, la translation et le redimensionnement. Ces transformations se font bien évidemment en deux dimension seulement. Le système de pile de la matrice est aussi rendu : l'état de transformation peut être sauvegardé et restauré.
=== Physique ===
Le moteur physique s'occupe de la gestion des différents paramètres physiques de l'environnement et des personnages. Cela comprend la gravité, le poids des personnages, la gestion des collisions, des fonctions utilitaires pour appliquer des forces aux différentes entités, le tout au service d'une dynamique des combats plus ou moins réaliste dans la simulation physique.
Le moteur physique doit permettre de créer des entités physiques composées de différentes formes géométriques possédant des liaisons spécifiques entre elles, ainsi que des caractéristiques particulières telles que masse, densité, taux de friction avec les autres entités, etc.
Comme dit précédemment, il doit aussi permettre d'appliquer des forces sur les entités en question, mais aussi de modifier directement des propriétés des entités telles que la vélocité, selon le niveau de réalisme dans la simulation, des mouvements moins réalistes pouvant être plus adaptés en termes de maniabilité ou de lisibilité dans le gameplay.
Le moteur physique permet d'implémenter des callbacks qui s'exécutent lors de collisions entre certains types d'entités. On doit pouvoir aussi définir des masques de collisions afin d'en autoriser uniquement certaines, toujours selon les types d'entités.
Le moteur physique ne peut être instancié qu'une seule fois, lorsque le serveur gère le combat.
=== Sonore ===
Le moteur sonore est celui qui s'occupe de charger et jouer les sons et musiques du jeu.
Le moteur permet de charger les sons au format ``wav`` et les musiques au format ``ogg`` et ``mp3`` au moins (le support pour d'autres formats pourra être ajouté). À l'instar du moteur graphique, le moteur sonore charge chaque ressource avec un nom, et on y retrouve le même système de namespace et de liens.
Il est possible de définir des callbacks qui s'exécutent à la fin d'un son ou d'une musique. Une musique peut être jouée en boucle, mais seule une partie d'elle peut aussi être jouée en boucle : elle est jouée du début la première fois mais quand elle recommence elle reprend à un moment donné, pas du début. Le moteur sonore peut jouer jusqu'à une musique et huit sons simultanés.
Le moteur offre aussi une gestion du volume différenciée pour la musique et les sons.
=== Sauvegarde ===
Le moteur de sauvegarde est celui utilisé par les events pour enregistrer leurs variables et se valider. Il permet de créer et déclarer des variables numériques avec un nom. Ces variables sont organisée de la même façon que les images dans le moteur graphique, à l'exception que les liens sont interdits.
En plus de permettre la lecture et la modification de ces variables, il peut les sauvegarder et les charger depuis un fichier, garantissant que d'une exécution à l'autre, l'état soit toujours le même.
=== Lua ===
Le moteur lua est utilisé par le jeu pour gérer tous les scripts (personnages, stages, events ...). Il a deux types de possibilités.
Il permet d'instancier une classe qui représente un script et permet de contrôler son exécution : permet d'accéder à des variables du script, de modifier leur valeur, de tester la présence de fonction et de la exécuter en récupérant leur valeur de retour et en leur passant des arguments.
Ce moteur permet aussi de rendre accessible au code des scripts les différents moteurs du jeu. Pour cela, il permet //d'enregistrer// dans l'exécuteur lua des fonctions et des classes, avec ou non un nom différent de celui dans le code c++. Cependant, la notion d'héritage n'est pas gérée lors de l'exposition aux scripts. De plus, l'enregistrement des moteurs doit être fait pour chaque script, il ne peut pas être fait une fois puis utilisé par tous les scripts.
== Licence ==
L'ensemble du code du jeu sera sous licence GPLv3. À terme la licence pourra évoluer vers une GPLv3+. La licence des autres éléments du jeu tels que les images, les sons et autres ressources est laissée à la discrétion des créateurs de ces ressources. Il doivent néanmoins choisir au minimum une licence de libre distribution (par exemple une CC-BY-NC-ND) si leurs créations doivent être intégrés comme ressources officielles du jeu.
= FAQ =
Dans cette section peuvent être trouvées des réponses à des questions concernant principalement les choix de Game Design.
== Pourquoi un jeu strictement multijoueurs ? ==
Project Warrior est pour le moment prévu en tant que jeu strictement multijoueurs, c'est à dire qu'il faut au minimum 2 joueurs pour profiter du jeu ; il y a plusieurs raisons à cela :
- Créer un mode solo pour un jeu de combat nécessite de coder une IA que le joueur doit défier, avec toutes les difficultés techniques que cela implique
- Une IA possède forcément des limites au niveau de la difficulté, contrairement à l'adversaire humain
- Project Warrior se veut avant tout un jeu convivial sur lequel les gens s'amusent à plusieurs et se confrontent directement, ce qui est particulièrement vrai en mode local et ce qui ne se retrouvera pas par exemple dans un mode Classique ou Aventure à la SSB
- Le multijoueurs permet aussi d'amener une notion de compétitivité qui rajoute énormément de durée de vie au soft si on la développe dans un mode online, avec des duels ou des combats en équipes équilibrées
Coder un mode solo serait donc une perte d'énergie et de temps considérable pour un jeu dont les enjeux tournent autour de l'intéraction entre les joueurs. Néanmoins il n'est pas exclu que le joueur puisse s'approprier les personnages et leurs techniques de combat dans un mode de jeu - exceptionnellement - solo, en se défoulant gentiment et sans limites sur une entité inerte similaire au sac de sable de SSB.