MUGEN - Création de
Lifebars
_________________________________
Mike
Werewolf.
Sommaire :
Introduction.
1. Quelques termes pour se comprendre
2. Les outils nécessaires
3. Le fichier SFF
a. Les sprites nécessaires
b. Création et/ou modification des
sprites (avec Paint Shop Pro)
c. Création du fichier
4. Généralités sur le fichier DEF
a. Les Modules
b. Petit mot sur le facing
c. Petit mot sur le temps
5. Le début du fichier DEF et la section [File]
6. Les sections [Lifebar], [Simul Lifebar] et [Turns Lifebar]
7. La section [Powerbar]
8. Les sections [Face], [Simul Face] et [Turn Face]
9. Les sections [Name], [Simul Name] et [Turn Name]
10. Les sections [Time] et [Combo]
11. La section [Round]
12. La section [WinIcon]
13. Complément : les effets de transparence
14. L'installation
a. Remplacer les lifebars existantes
b. Ajouter les lifebars sans
supprimer celles déjà existantes
Crédits
A propos de l'éthique de Mugen
Tout d'abord, définissions le terme de Lifebar. Ce qu'on appelle communément "lifebars" est en fait la définition de l'écran de combat, en dehors des personnages et des stages, eux-mêmes définis isolément. Les lifebars ne se résument donc pas à la simple barre de vie, mais s'étendent également à l'affichage des barres de power, des portraits des combattants, de leur noms, des rounds gagnés, du temps, du "Round X", du "Fight", etc.
Bien évidemment, comme les lifebars concernent l'affichage de données, on va parler essentiellement graphismes ici. Rien de très compliqué toutefois. Mais tout ce dont on va parler tournera fatalement autour de la retouche graphique, des calculs de coordonnées, etc.
Les lifebars permettent de personnaliser énormément l'écran de jeu, et peuvent être présentées seules, ou avec un screenpack.
Les lifebars se composent, comme les stages, de deux fichiers : un fichier SFF et un fichier DEF. La règle générale veut que ces fichiers soient dénommés fight.sff et fight.def, mais en réalité, vous pouvez les nommez comme bon vous semble, pourvu que vous pensiez à modifier en conséquence les fichier system.def. Ces fichiers de lifebars sont normalement à placer dans le dossier Data. Les lifebars peuvent également comprendre d'autres fichiers (des polices, des sons, etc.), mais ce tutorial ne s'intéressera qu'à la création des fichiers fight.def et fight.sff.
Pour créer les lifebars, je vous conseille d'utiliser une version "vide" de Mugen, c'est à dire une version avec pour seul personnage KFM, sans screenpack autre que celui de départ, sans musiques additionnelles, sans autre stage que Mountainside Temple et Training Room. Vous chargerez ainsi le jeu beaucoup plus rapidement, et ne répercuterez pas les éventuelles erreurs de programmation sur votre jeu traditionnel. Même sur cette version light de Mugen, je vous conseille de faire une copie des fichiers fight.sff et fight.def, pour pouvoir les récupérer en cas de besoin, et les consulter pour voir leur structure, en particulier le fichier def.
Mais dans tous les cas, notez que les lifebars ne sont que des composants graphiques, et qu'elles n'ont donc aucune incidence sur le fonctionnement des personnages, des stages, ou même du jeu en général.
1. QUELQUES TERMES POUR SE COMPRENDRE
Je vais utiliser tout au long de ce document des termes qui peuvent parfois sembler proches. Pour qu'il n'y ait pas de doute, je respecterait les termes suivants dans le sens indiqué :
Lifebar : C'est le squelette qui contient la jauge de vie, le contour de cette jauge, si vous voulez.
Jauge de vie : C'est la jauge représentant la vie restante du personnages. Ces jauges sont souvent jaunes.
Vie perdue : C'est la jauge qui s'affiche momentanément lors d'un coup, et qui représente la vie enlevée par ce coup ou l'enchaînement. Cette jauge est souvent rouge.
Powerbar : C'est le squelette qui contient la jauge de power.
Power : La jauge de power
Round : texte/sprite/animation qui annonce le début du round
Icône Round : Icône indiquant un round gagné par le joueur
Je tiens également à rappeler les différents modes de jeu de Mugen. Je pense que vous les connaissez, mais comme on va beaucoup s'en servir, il faut bien avoir en tête les implications de chacun.
1 contre 1 : C'est le mode le plus courant, deux adversaires s'affronte. On le trouve en mode Arcade, en VS, en training, en watch (Single) et dans les modes team, si les deux opposants choisissent le mode Single.
Simul : C'est le mode de jeu qui permet de faire intervenir jusqu'à 4 joueurs en même temps à l'écran. Il y a donc 2 portraits et 2 barres de vie par équipe (mais toujours une seule barre de power, puisqu'elle est partagée par les deux joueurs de l'équipe). Dans la programmation, ces 4 joueurs sont identifiés par p1, p2, p3 et p4. Sachez qu'en simul, p1 et p3 sont ensemble, contre p2 et p4.
Turn : C'est le mode par tour, jusqu'à 4 joueurs par équipe, le vainqueur reste tant qu'il n'est pas vaincu. Ce mode présente de nombreuses similitudes avec le 1 contre 1 (du moins pour les lifebars), sauf qu'en plus on a la notion de "teammate" (partenaire) qui va intervenir.
Dans ce tutorial, nous resterons dans le basique, puisque nous éluderons les cas où deux lifebars différentes seraient nécessaires (ex : 1 - Single contre 2 - Simul, qui demande une barre de 1 contre 1 pour le joueur 1, et une barre de Simul pour le joueur 2). Ici, dans ces cas là, il y aura un petit défaut d'affichage, qui ne sera toutefois pas très méchant, et qui n'empêchera pas de jouer loin s'en faut.
Une version vide de Mugen, telle que décrite dans l'introduction, pour faire les tests.
Un éditeur de textes type bloc-notes. Personnellement, je vous conseille EditPad qui présente l'avantage de ne pas être limité sur la taille du fichier, et de pouvoir afficher plusieurs fichiers en même temps dans une seule session.
Un éditeur graphique pour retoucher les images si vous rippez un modèle déjà existant d'après un jeu émulé, ou les créer dans le cas d'une création complète. J'utilise personnellement Paint Shop Pro 5, et les indications contenues pour ce tutorial concernent donc cet éditeur.
MCM, programme inévitable pour la création de graphismes Mugen.
Et ce sera à peu près tout.
Commençons par le plus simple, mais pas forcément le plus court : la création du fichier graphique.
Nous allons avoir besoin de plusieurs sprites indispensables pour créer les lifebars. Il est possible, et même conseillé d'utiliser encore plus de sprites pour créer des animations, ou remplacer des textes par des sprites, mais nous en tiendrons au minimum pour l'instant. Voici donc les sprites qu'il nous faut (avec une image d'exemple pour vous donner une idée) :
Sprite | Noms | Références MCM | Description |
![]() |
lifebar | 1,0 | Lifebar utilisée par les deux joueurs en mode 1 contre 1 (Arcade, Turns, VS, Training...) |
![]() |
simullifebar | 1,1 | Lifebar utilisée par les joueurs en mode Simultané (plus de 2 joueurs en même temps à l'écran) |
![]() |
roundcard | 10,0 | Icône round, icône qui s'affiche quand un joueur remporte un round |
![]() |
vieperdue | 12,0 | Barre de vie perdue (cf. partie 1) en mode 1 contre 1 |
![]() |
simulvieperdue | 12,1 | Barre de vie perdue en mode Simul |
![]() |
vie | 13,0 | Barre de vie en mode 1 contre 1 |
![]() |
simulvie | 13,1 | Barre de vie en mode Simul |
![]() |
partelim | 14,1 | Cadre qui s'affiche autour des portraits des persos éliminés en mode Turns |
![]() |
KO | 15,0 | Image de KO qui s'affiche à la fin d'un round lorsque l'un des joueurs perd autrement que par le temps. |
![]() |
powerbar | 21,0 | Powerbar où se charge le power. Il n'y a qu'une powerbar pour les deux joueurs, du fait que la programmation du fight.def permet de retourner l'image, et donc de l'appliquer au joueur 2. De même, en mode Simul, les joueurs d'une même équipe partagent la powerbar, et il n'y a donc pas de powerbar distincte pour le mode Simul. |
![]() |
power | 23,0 | barre de power |
![]() ![]() ![]() |
F1 F2 F3 |
31,1 31,2 31,3 |
Ces trois images vont nous permettre de réaliser une animation pour le "Fight" du début de combat. Ce n'est pas vital, mais cela nous permettra d'étudier l'animation... |
(Si, si, y a bien une image ! C'est le point rose que vous pourriez prendre pour une saleté sur votre écran ! Lisez la description pour comprendre !) |
perfect | 99,99 | Ce sprite est celui qui s'affiche par dessus l'icône victoire en cas de perfect. Même si vous ne voulez pas avoir de sprite "perfect", vous devez intégrer celui-ci dans le fichier SFF. C'est ici notre cas, et pour circonvenir à la règle, nous utiliserons une image de 1x1 pixel, coloriée en couleur d'index 0, pour qu'elle paraisse transparente dans Mugen. |
Voilà ! Rien qu'avec cela, nous aurons déjà de quoi faire. Quelques remarques : vous pouvez insérer vos sprites sans ordre particulier, du moment que vous leur affectez les bons numéros de groupes et d'images.
La colonne Référence MCM indique ces numéros de groupe et d'image au format : groupe,image. Les noms de fichiers ne sont là qu'à titre indicatif puisqu'ils n'ont aucune incidence sur le fichier SFF.
b. Création et/ou modification des sprites (avec Paint Shop Pro)
Que vous ayez "rippé" vos sprites depuis un jeu émulé, ou que vous les ayez créé de toutes pièces, il y a certaines règles à respecter. Comme pour toutes création de fichier SFF, vos images doivent être au format PCX, en 256 couleurs. La couleur ayant le numéro d'index 0 sera considérée comme transparente. Vous devez bien tenir compte de tout cela.
Imaginons donc que vous ayez rippé quelques sprites depuis l'écran de jeu suivant (capture du jeu Super Street Fighter II - The New Challengers, émulateur ZSNES) :
Ce sprite de départ présente de quoi faire pas mal de choses : on peut récupérer l'icône round, qui est ici une carte rouge avec une étoile dorée, le squelette de la barre de vie, la vie et la vie perdue. Vous pouvez également récupérer les sprites des fonts pour recréer le style d'écriture des noms, du temps, du message annonçant le vainqueur. Ouvrons cette capture d'écran dans Paint Shop Pro.
Si vous avez créé votre propre image, notez que ce qui suit est également valable, même si du fait de la création, on peut définir une couleur d'index 0 pour ne pas avoir à retoucher l'image.
D'emblée, on pourrait se dire que l'image n'étant pas en 256 couleurs, c'est la première choses à faire : ainsi, toutes les images que l'on découpera dessus seront ensuite en 256 couleurs, et on évite ainsi de devoir convertir chaque découpage en 256 couleurs. Toutefois, pour optimiser les palettes, en ne gardant que les couleurs nécessaires, nous allons garder notre image en millions de couleurs, et seuls les découpages seront réduits à 256 couleurs.
Donc pour commencer, nous allons découper les parties qui
nous intéressent grâce à l'outil Recadrage
. Chaque découpage se traite
ainsi : découpage, enregistrement (enregistrez les parties découpées au fur et à
mesure sous d'autres noms pour ne pas perdre l'image d'origine, ou travaillez
sur une copie pour pouvoir la retrouver en cas d'erreur), réduction des
couleurs, édition de la palette, et sauvegarde au format PCX. Commençons par le
plus simple : la barre de vie. Une fois découpée, il n'y a qu'une couleur
visible.
Nous allons donc réduire cette image en 256 couleurs. Pour cela, nous utiliserons le menu Couleurs>Diminuer le nombre de couleurs>256 couleurs (8 bits).
Ensuite, nous devons penser à notre palette. Nous l'affichons avec le raccourci Maj+P ou menu Couleurs>Editer la palette. Et là, voici ce que nous obtenons :
L'image n'utilisant qu'une seule couleur, c'est celle-ci qui est placée en première position dans la palette, à l'index 0. Or l'index 0 est interprété par Mugen comme une couleur transparente, et n'est donc pas affichée. Si nous enregistrons notre image ainsi, elle sera inexploitable. Nous devons donc transférer cette couleur sur un autre index. Voici comment faire : tout d'abord, notez les valeurs RVB de la couleur à transférer (sélectionner la couleur en question, ses valeurs RVB s'affiche en bas), puis double cliquez sur la première couleur non utilisée par la palette (en l'occurrence ici, l'index 1, de manière générale, prenez une case blanche - RVB 255, 255, 255). On ouvre ainsi une fenêtre couleur :
Dans le cadre "Couleur en cours", reportez les valeurs RVB dans les cases Rouge, Vert et Bleu, et validez avec OK. Là, votre case doit donc avoir la même couleur que l'index 0. Double cliquez ensuite sur l'index 0, afin d'ouvrir la fenêtre couleur, et sélectionnez n'importe quelle couleur qui ne soit pas utilisée dans le sprite. Par défaut, on utilise très souvent le rose fluo (en bas à gauche dans la grille "Couleur de base") ou le vert fluo (dans la même colonne). Votre jauge de vie doit être devenue de cette couleur. Ressortez de la palette et cliquez sur la case de la couleur principale, dans la barre d'outils "palette couleurs" sur la droite :
Vous ouvrez ainsi de nouveau la fenêtre palette (attention : vous pouvez uniquement sélectionner un index de palette, pas les modifier !). Sélectionnez votre index contenant la couleur d'origine (ici, l'index 1) :
Cliquez sur OK, puis sélectionnez l'outil "Remplissage"
. Vérifiez bien que vous êtes
bien configuré :
Et appliquez le remplissage sur les parties colorées en index 0 (ici toute la barre). Répétez cette procédure pour toutes les images que vous découperez ou que vous créerez. Ca s'arrête là pour la barre de vie, vous pouvez enregistrez votre image au format PCX. En revanche, pour d'autres sprites, il va falloir encore une étape : rajouter la transparence. Prenons l'exemple de la lifebar, que nous venons de découper :
Vous avez modifié votre palette pour que l'index 0 ne corresponde pas à une couleur utilisée dans le sprite, vous avez réduit le nombre de couleurs à 256, oui, mais l'image n'est toujours pas exploitable. Tout d'abord, vous noterez que sur la gauche, on voit une partie de l'icône round qui se superpose à la life bar (comparez avec le côté droit). Il faut donc retoucher l'image pour faire disparaître la partie en trop. Mais le plus gênant ici est que l'on a du décor en fond, et que l'on n'a pas besoin de jauge de vie (à gauche) ni de vie perdue (à droite). Il faut donc rendre tout cela transparent. Vous l'aurez compris, vous devez sélectionner l'index 0 pour votre couleur principale, et l'appliquer à tout ce qui est superflu. On obtient donc ce résultat, en ayant choisi le rose fluo comme couleur transparente :
Voilà, vous avez désormais la procédure pour obtenir les images avec Paint Shop Pro. Vous noterez quand même que dans Super Street Fighter II - The New Challengers, que j'ai pris pour modèle, il manque des composants de l'écran de combat Mugen, notamment : la barre de power, l'affichage des portraits, la lifebar en mode Simul, etc. Dans ce cas, ce sera à vous de créer graphiquement ces éléments pour les intégrer (à moins de les récupérer sur un autre jeu...).
Nous pouvons donc nous intéresser à la création du fichier SFF proprement dit, maintenant que nous avons toutes nos images. Nous avons besoin de MCM pour cela.
On va commencer par ajouter nos sprites avec le bouton
.
Dans la fenêtre qui s'affiche, vous devez choisir le sprite à ajouter :
Surtout, n'oubliez pas de décocher la case "Use Shared Palette" afin que les images utilisées gardent leur palette propre et donc, qu'elles s'affichent avec les bonnes couleurs. Appliquez ensuite aux sprite le numéro de groupe et d'image, soit depuis la fenêtre "Load Image", soit dans la fenêtre générale de MCM, au-dessus du cadre d'image :
Lorsque toutes vos images sont intégrées et que les numéros de groupe et d'image sont bons, vous pouvez enregistrer le fichier sous le nom "fight.sff" (touche F2 ou Menu SFF>Save).
Nous pouvons ensuite passer à la plus grosse partie : la réalisation du fichier DEF.
4. GENERALITES SUR LE FICHIER DEF
Avant de nous lancer dans la programmation pure et dure du fichier DEF de notre écran de combat, je pense qu'il est très utile de définir et d'expliquer quelques notions.
Plus vous allez taper du code dans ce fichier, plus vous allez comprendre que le système utilisé est très souple, et que la structure est assez facilement compréhensible. En fait, chaque paramètre se compose de plusieurs "modules", séparés par des points. Ces modules désignent chacun un paramètre vague, et c'est l'association de ces modules qui permet de rendre le paramètre précis. Voici un exemple :
On en déduit que ce paramètre indique les coordonnées d'affichage de la vie perdue pour le joueur 1. Mais on en déduit aussi, que pour le joueur 2 par exemple, on aura le paramètre p2.mid.offset.
Tout est basé sur cette structure, ce qui rend le code finalement assez compréhensible, pour peu que l'on sache à quoi se rapporte les modules. En voici donc une liste (la colonne "Entrée de valeurs" indique si le module est suivi de valeurs [il est donc dans ce cas le dernier module du paramètre, et dans "Signification / Description", les types de valeurs à entrer sont décrits] ou non [dans ce cas, il doit y avoir un autre module derrière]) :
Module | Entrée de valeurs | Signification / Description |
p1 | Non | S'applique au joueur 1. De même, p2 s'applique au joueur 2, p3 au joueur 3 et p4 au joueur 4. |
pos | Oui | Désigne la position virtuelle où se situe l'élément concerné (désigné par le nom de la section : Lifebar, Powerbar, etc.). Les valeurs du paramètre seront donc des coordonnées x,y. |
bgX | Non | Désigne le sprite de fond de l'élément (le squelette). Le X est le numéro de l'élément. On commence souvent à 0 : bg0, bg1, etc... |
text | Oui | Précise un affichage de texte. La valeur
entrée sera donc du texte. En première position (section [Combo]), il désigne le texte lui-même en tant qu'élément, et non plus pour indiquer à Mugen d'afficher du texte. |
spr | Oui | Désigne un sprite à afficher. La valeur entrée sera donc le numéro de groupe et d'image du sprite selon la syntaxe groupe,image. |
anim | Oui | Désigne une animation. La valeur entrée sera le numéro de l'animation (ex : ...anim = 100, qui correspondra à l'animation décrite par le [Begin Action 100]). |
layerno | Oui | Désigne le niveau de plan pour l'affichage, qui peut avoir 3 valeurs : arrière-plan (0), plan normal (1) ou premier plan (2). |
offset | Oui | Désigne des coordonnées d'affichage. Les valeurs à entrer sont des coordonnées x,y. Elles correspondent au point haut gauche du sprite (sauf avec un facing = -1), ou au bas de la police. |
range | Non | Désigne l'amplitude sur l'axe définit ensuite ; si on a une barre horizontale (cas le plus fréquent) on aura ...range.x = x1,x2 ; si on a une barre verticale, on aura : ...range.y = y1,y2. le y1/x1 désigne la barre à 0% tandis que le y2/x2 désigne la barre à 100% |
x / y | Oui | Associés à range, ces paramètres désigne l'axe horizontal (x) ou vertical (y). Les valeurs à entrer sont deux coordonnées de cet axe, définissant ainsi le range. Cf. le module range pour plus de détails. |
facing | Oui | Le facing indique si le sprite en question doit être affiché normalement (valeur 1) ou s'il doit être retourné horizontalement (valeur -1). Dans ce cas, il y a donc une symétrie axiale opérée sur l'image, sur l'axe des y. |
front | Non | Désigne la barre qui s'affiche normalement (jauge de vie restante pour les lifebars, jauge de power pour la powerbar). |
mid | Non | Désigne la barre qui s'affiche momentanément lors de la réduction d'une barre de type front. Elle est facultative, et assez peu employée pour le power. Techniquement, les barres de front et mid sont affichées exactement de la même façon, mais la barre front recouvre la barre mid, et lorsque la barre front réduit, la barre mid apparaît, un court instant, avant de se mettre au niveau de la barre front. |
counter | Non | Désigne l'affichage d'un compteur (pour les niveaux de power, le temps, les combos, etc.). |
font | Oui | Le premier chiffre indique le numéro de la police utilisée, tel que définit au début du fichier DEF dans la partie [Files]. Le second chiffre réfère au numéro de banque de couleur de la police (référez-vous aux documents concernant les fonts et leur création, fournis par Elecbyte). Le troisième chiffre indique l'alignement de la police : (1 = gauche, 0 = centré, -1 = droite). On n'utilise le font que si le module text est utilisé sur le même paramètre. A l'inverse, si vous utilisez le module text sans préciser de font, le texte ne s'affichera pas. |
snd | Oui | Indique un son à jouer, selon le format groupe,image. Les sons joués sont ceux contenus dans le fichier par le snd = dans la partie [Files] (fight.snd par défaut). |
face | Non | Désigne les mini-portraits des joueurs ou des partenaires (mode Turns) |
scale | Oui | Indique l'échelle à laquelle doit être affichée le portrait. Les valeurs à entrer sont des coefficients appliqués à l'image de base, en x et en y. 1,1 affichera donc le portrait normalement, alors que .5,.5 affichera le portrait réduit de moitié. Il est conseillé de garder les mêmes coefficients x,y pour que le portrait ne soit pas déformé. |
teammate | Non | Désigne les paramètres relatifs aux partenaires (mode turns) |
spacing | Oui | Indique en pixel sur x et y les distances séparant les éléments. Il est possible de mettre des valeurs négatives. |
ko | Non | Faites attention, ce module est en minuscule ! ;o) Donc, ce module s'applique au teammate pour désigner un partenaire vaincu en mode turns. |
name | Non | Désigne le nom du joueur actif |
start | Non | Utilisé dans la partie [Combo], ce paramètre
définit la position de départ d'un texte sur l'axe spécifié ensuite (start.x), par rapport à la position définit du texte (pos), et qui
permet donc de faire "surgir" le texte d'un bord de l'écran pour l'amener de
la coordonnée définit par le start.x à la coordonnée définit par le pos. Utilisé dans d'autres sections ([Round] notamment), ce module permet d'indiquer le début de l'élément concerné. |
displaytime | Oui | C'est le temps d'affichage de l'élément concerné. |
time | Oui | C'est le temps qui s'écoule avant que l'élément ne soit actif. On a ainsi un fight.time qui indique au bout de combien de temps le "Fight" est affiché, et un fight.displaytime, qui indique combien de temps s'affiche le "Fight". |
round | Non | Désigne ce qui se rapporte au round. |
fight | Non | Désigne ce qui se rapporte au fight (qui donne le départ du combat) |
KO | Non | En majuscules ! ;o) Désigne ce qui se rapporte à la situation de KO (l'un des deux adversaires a perdu toute sa vie avant la fin du temps imparti). |
DKO | Non | Désigne ce qui se rapporte à la situation de Double KO (les deux adversaires ont épuisé leur barres de vie en même temps, avant la fin du temps imparti). |
TO | Non | Désigne ce qui se rapporte à la situation de Time Over (le temps imparti est écoulé sans qu'aucun des deux adversaires ne soit KO - impossible si le temps est infini). |
over | Non | Désigne "l'après round", une fois qu'une situation de KO, DKO ou TO est survenue. |
win | Non | Désigne la situation où l'un des joueurs l'emporte sur l'autre (Mode 1 contre 1 ou Turns). |
win2 | Non | Même chose mais pour le mode Simul |
draw | Non | Désigne une situation d'égalité (DKO et TO quand les adversaires ont la même vie restante). |
Cette liste ne comprend pas les paramètres uniques tel que le "framespercount" de la section [Time], qui est un paramètre sans module et propre à cette section, ni les paramètres spécifiques à la section [WinIcon].
Imaginons un sprite ayant deux nuances de gris, qui fasse 100 pixels de large, et que l'on place en x=220 sans facing. On obtient ceci :
Code imaginaire :
sprite.offset = 220,0 sprite.facing = 1 ;optionnel, juste pour indiquer que le sprite n'est pas retourné. |
Et on obtiendrait ceci (notre sprite va de 220 à 320 en x) à l'écran :
x,y = 220,0 |
axe de symétrie axiale x = 270 (220+(100/2) |
|
SPR |
ITE |
Si le facing opérait un retournement sur l'axe central, les coordonnées du sprite resteraient inchangées, et on mettrait :
Code imaginaire :
sprite.offset = 220,0 sprite.facing = -1 ;on retourne le sprite mais les coordonnées sont les mêmes |
Et on obtiendrait :
x,y = 220,0 |
axe de symétrie axiale au centre du sprite | |
ETI |
RPS |
Mais le fait est que la symétrie axiale opérée par le facing ne se fait pas sur l'axe passant par le milieu du sprite. Non, cette symétrie se fait en fait sur le bord gauche :
x,y = 220,0 |
axe de symétrie du facing. x = 220. | |
SPR |
ITE |
Avec le facing, on obtient donc :
x,y = 120,0 |
x,y = 220,0 |
|
ETI |
RPS |
Et là, notre sprite ne correspond plus à ce que l'on avait au départ : notre sprite ne va plus de 220 à 320 en x, mais de 120 à 220. Pour que tout rentre dans l'ordre, il faut donc modifier notre code :
sprite.offset = 320,0 ;soit 220 + 100 sprite.facing = -1 ;on retourne le sprite mais les coordonnées sont les mêmes |
La symétrie due au facing crée un décalage de la taille du sprite, qu'il faut compenser en recalculant le offset, tel que x en facing -1 = (x en facing =1) + taille du sprite.
En fait, on peut également considérer que, du fait du facing, ce n'est plus le coin haut gauche du sprite qui sert de référence pour le offset, mais le coin haut droit.
Dans Mugen, tous les paramètres de temps sont définis en "game-ticks" ou "ticks". On ne peut pas réellement rapporter le tick à notre mesure du temps. Le tick correspond en fait à l'affichage d'une frame. Pour simplifier, une frame est un sprite à un moment donné d'une animation. Par exemple, si vous reprenez le tableau des sprites, vous constaterez que le "Fight" est composé de 3 images. Ces images sont les 3 frames de l'animation. Là où ça se complique, c'est quand on sait qu'une frame peut être affichée pendant plusieurs ticks ! >:o(
En fait, c'est simple : il ne faut pas comprendre que l'image est affichée pendant X ticks, mais plutôt que l'image est réaffichée X fois (le X fois correspondant au nombre de ticks). Ainsi, pour notre animation, que l'on verra plus loin, F1 sera affichée 5 ticks, F2, 5 ticks, et F3, 100 ticks. Si on considère que l'image ne reste pas pendant 5 ticks, mais est bien réaffichée 5 fois (1 fois par tick), alors on comprend que notre animation comporte 110 frames. Et donc 1 frame équivaut bien à 1 tick, et tous les tick/frame s'affichent à la même vitesse.
Par défaut, 60 ticks sont censées représenter 1 seconde de jeu. C'est à dire donc que 60 frames s'afficheront avant que le compteur de temps change de seconde. Ce paramètre peut cependant être changé avec le framespercount que nous verrons plus loin, et qui définit tout bonnement le nombre de ticks (et donc de frames ;o) par seconde. Si on augmente ce nombre, la seconde durera donc plus longtemps, et si on le diminue, la seconde de jeu durera moins longtemps.
Attention ! Le fait d'augmenter ou de diminuer le framespercount n'a aucune incidence sur la vitesse de jeu elle-même ! C'est juste la vitesse de défilement des secondes au compteur de temps qui est affectée !
5. LE DEBUT DU FICHIER DEF ET LA SECTION [FILES]
Cette fois, entrons dans le vif du sujet. Vous allez voir cependant que si vous avez bien assimilé la partie 4, ce qui suit ne devrait vous poser aucun problème.
Commençons par le commencement ! Comme dans tous les fichiers Mugen lisible par un éditeur de textes (DEF, CNS, CFG, CMD, etc.), tout ce qui suit un point-virgule sur une ligne est interprété comme du commentaire et n'a donc aucune incidence sur le fonctionnement du fichier.
En règle générale, on commence chaque fichier DEF de lifebars (que l'on enregistrera communément sous "fight.def") par une description rapide, et des coordonnées. Exemple type :
;===== CAPCOM' SUPER
STREET FIGHTER II SCREENPACK ===== ;Conçu par Mike Werewolf et GhOw ;Made by Mike Werewolf and GhOw ;http://mike.werewolf.free.fr/ ;http://www.aprog.fr.st/ ;E-mail : mikewerewolf@hotmail.com & ;A propos de l'écran de combat : ;About the battle screen : ; Rip, adaptation graphique, et écran de combat réalisé par Mike Werewolf. ; Rip, graphic adaptation, and battle screen made by Mike Werewolf. ; Commentaires en français par Mike Werewolf. ; French comments by Mike Werewolf. [Info] Name="Super Street Fighter II Mugen Edition" Author="Mike Werewolf & GhOw" |
Dans ce début de ce fichier, toutes les lignes sont mises en commentaires. On décrit le nom de la lifebar (ou en l'occurence, du screenpack dont fait partie la lifebars), le nom des auteurs, les emails, les sites, et toute information jugée utile. On trouve aussi une section [Info], optionnelle, où sont reprit le nom de la lifebar ou du screenpack, et le nom du ou des auteur(s).
Ensuite, on attaque la section [Files]
Files] ; Fichiers utilisés par le screenpack pour l'écran de combat sff = fight.sff snd = fight.snd font1 = font/jg.fnt font2 = font/f-4x6.fnt font3 = font/name1.fnt font4 = font/num1.fnt fightfx.sff = fightfx.sff fightfx.air = fightfx.air common.snd = common.snd |
Cette partie définit tous les fichiers dont vont dépendre la lifebar. On y trouve le fichier SFF (il faut reprendre le nom que vous lui avez donné), le fichier son des bruitages propres à l'écran de jeu (décompte du temps, niveau de power franchit, annonce du round, etc.), les polices, les sprites et animations de combat (s'ils ne sont pas prévus dans la programmation du personnage), et le fichier son liés à ces animations de combat.
Hormis le premier fichier, vous n'êtes pas obligé de créer vos propres fichiers, puisque Mugen en propose par défaut (autant les reprendre). Il peut être cependant intéressant de créer vos propres polices adaptées à l'écran de jeu, d'autant que celles proposées par Mugen ne sont pas exceptionnelles.
Un petit mot encore sur la partie police : chaque ligne commençant par "fontX =" attribut une police à un numéro de font. Et c'est ce numéro X que vous utiliserez pour appeler les fonts avec les modules font. C'est à dire que si vous souhaitez par exemple utiliser la police jg.fnt, pour afficher le temps, on mettra "counter.font = 1,0,0" dans la section [Time]. On aurait mis "counter.font = 3,0,0" si on avait voulu utiliser la police name1.fnt.
Enfin, Elecbyte préconise de ne pas indexer plus de 9 polices, ce qui laisse déjà de quoi faire...
6. Les sections [Lifebar], [Simul Lifebar] et [Turns Lifebar]
Maintenant que nous avons bien définis nos fichiers, nous sommes parés à entamer la programmation pure. Commençons par les lifebars proprement dites :
[Lifebar] p1.pos = 32,10 p1.bg0.spr = 1,0 p1.bg0.layerno = 1 p1.mid.spr = 12,0 p1.mid.offset = 31,03 p1.mid.layerno = 2 p1.front.spr = 13,0 p1.front.offset = 31,03 p1.front.layerno = 2 p1.range.x = 118,31 p2.pos = 32,10 p2.bg0.spr = 1,0 p2.bg0.facing = 1 p2.bg0.layerno = 1 p2.mid.spr = 12,0 p2.mid.facing = -1 p2.mid.offset = 224,3 p2.mid.layerno = 2 p2.front.spr = 13,0 p2.front.facing = -1 p2.front.offset = 224,3 p2.front.layerno = 2 p2.range.x = 137,224 |
Dans cette partie, nous définissons l'affichage des lifebars en mode 1 contre 1. Plusieurs remarques sont à formuler : tout d'abord, le pos. Il définit la position du squelette de la lifebar. Il fixe ensuite la position relative des autres sprites de lifebar pour les modules p1 et p2. Nous allons y revenir. Le p1/2.bg0.spr appelle le sprite de la lifebar. Comme nous avons utilisé le même sprite pour les deux joueurs, c'est le même sprite qui est appelé, et il est placé au même endroit. Dans les modules p1, vous noterez qu'il n'y a pas de facing. Implicitement, celui-ci est définit à 1, et il n'y a pas lieu de le rajouter.
Le module mid ensuite nous permet d'appeler la barre de Vie Perdue. Là, nous utilisons le facing = -1, mais en réalité, notre sprite étant un rectangle de couleur unie, cela ne change rien. En revanche, si vous utilisez des barres avec dégradés, ou des formes plus fantaisiste, n'oubliez pas ce facing pour retourner votre jauge.
Attention ! Les coordonnées que vous mettez en offset et en range sont des coordonnées relatives ! Ce qui signifie tout simplement qu'elles sont calculées par rapport au pos (32,10), qui est alors considéré comme le point d'origine, de valeur 0,0 (et non plus 32,10). Ainsi, nos jauges de vie et de vie perdues ont des offset de 31,03 pour le joueur 1, mais seront en réalité affichées aux coordonnées 63,13 (32+31,10+03). C'est valable également pour le joueur 2, et dans les autres cas de lifebar (simul lifebar et turns lifebar) que nous allons étudier ensuite.
Nos barres de vie étant horizontales, le range se calcule sur l'axe des x.
Passons maintenant aux lifebars en mode Simul :
[Simul Lifebar] ;Lifebars en Team - Simul p1.pos = 32,10 p1.bg0.spr = 1,1 p1.bg0.layerno = 1 p1.mid.spr = 12,1 p1.mid.offset = 31,3 p1.mid.layerno = 2 p1.front.spr = 13,1 p1.front.offset = 31,3 p1.front.layerno = 2 p1.range.x = 118,31 p2.pos = 32,10 p2.bg0.spr = 1,1 p2.bg0.facing = 1 p2.bg0.layerno = 1 p2.mid.spr = 12,1 p2.mid.facing = -1 p2.mid.offset = 224,3 p2.mid.layerno = 2 p2.front.spr = 13,1 p2.front.facing = -1 p2.front.offset = 224,3 p2.front.layerno = 2 p2.range.x = 137,224 p3.pos = 32,10 p3.bg0.spr = 1,1 p3.bg0.layerno = 1 p3.mid.spr = 12,1 p3.mid.offset = 31,8 p3.mid.layerno = 2 p3.front.spr = 13,1 p3.front.offset = 31,8 p3.front.layerno = 2 p3.range.x = 118,31 p4.pos = 32,10 p4.bg0.spr = 1,1 p4.bg0.facing = 1 p4.bg0.layerno = 1 p4.mid.spr = 12,1 p4.mid.facing = -1 p4.mid.offset = 224,8 p4.mid.layerno = 2 p4.front.spr = 13,1 p4.front.facing = -1 p4.front.offset = 224,8 p4.front.layerno = 2 p4.range.x = 137,224 |
La programmation est ici complètement identique au [Lifebar], sauf qu'il y a quatre joueurs à afficher au lieu de deux, et que les sprites de lifebar, de vie et de vie perdue sont différents. Je ne pense pas que cette partie appelle de commentaires particuliers. Je me contenterai donc de rappeler que les joueurs 1 & 3 sont ensembles contre les joueurs 2 & 4. Passons donc au mode Turns :
[Turns Lifebar] ;Lifebars en mode Team - Turns, exactement identique au [Lifebar] p1.pos = 32,10 p1.bg0.spr = 1,0 p1.bg0.layerno = 0 p1.mid.spr = 12,0 p1.mid.offset = 31,03 p1.mid.layerno = 2 p1.front.spr = 13,0 p1.front.offset = 31,03 p1.front.layerno = 2 p1.range.x = 118,31 p2.pos = 32,10 p2.bg0.spr = 1,0 p2.bg0.facing = 1 p2.bg0.layerno = 1 p2.mid.spr = 12,0 p2.mid.facing = -1 p2.mid.offset = 224,3 p2.mid.layerno = 2 p2.front.spr = 13,0 p2.front.facing = -1 p2.front.offset = 224,3 p2.front.layerno = 2 p2.range.x = 137,224 |
Techniquement, l'affichage de la lifebars en mode Turns est rigoureusement identique au mode 1 contre 1, c'est pourquoi nous reprenons exactement le même code, avec un basique copier-coller. Cependant, vous noterez qu'il est possible de créer une lifebar spéciale pour le mode Turns, afin par exemple de pouvoir inclure les portraits des partenaires dans le squelette de la lifebar, en prévoyant des emplacement déjà délimités. Mais si vous en êtes là, vous ne devez plus avoir véritablement besoin de ce tutorial ! ;o)
Nous pouvons maintenant passer aux barres de power.
Cette section est assez courte. En effet, dans Mugen, que vous soyez en solo, en Simul ou en Turns, c'est toujours la même barre de power qui s'affiche. Il n'y a donc qu'une seule définition de la barre de power.
[Powerbar] ;Définition des powerbars p1.pos = 102,22 p1.bg0.spr=21,0 p1.bg0.layerno = 0 p1.front.spr = 23,0 p1.front.offset = 2,0 p1.front.layerno = 2 ;p1.mid.spr = 21,1 ;p1.mid.offset = 02,0 ;p1.mid.layerno = 2 p1.range.x = 49,2 p1.counter.offset = -6,8 p1.counter.font = 3,0,0 p1.counter.layerno = 1 p2.pos = 217,22 p2.bg0.spr = 21,0 p2.bg0.facing = -1 p2.bg0.layerno = 1 p2.front.spr = 23,0 p2.front.facing = -1 p2.front.offset = -2,0 p2.front.layerno = 1 ;p2.mid.spr = 21,1 ;p2.mid.facing = -1 p2.range.x = -49,-2 p2.counter.offset = 6,8 p2.counter.font = 3,0,0 p2.counter.layerno = 1 ;Sons de power / level sounds level1.snd = 0,2 level2.snd = 0,3 level3.snd = 0,4 |
Vous noterez que cette partie ressemble étrangement à la partie [Lifebar]. Comme nous n'avons pas prévu de barre de perte de power, nous n'avons qu'une unique barre de power (front) et les paramètres mid sont mis en commentaires.
On notera également l'apparition des counter, qui affiche le niveau de power. Là encore, la position du counter est relative par rapport au p1/2.pos. Et n'oubliez pas que la valeur y du counter.offset correspond au bas de la lettre. La valeur x est une position de référence qui ici est valable étant donné qu'on n'affiche qu'un seul chiffre. Sinon, tout dépend de l'alignement choisi.
On note également trois paramètres de sons : level1/2/3.snd. Ces paramètres correspondent au son émis lorsque les niveaux de power 1, 2 ou 3 sont atteints.
Nous passons maintenant à l'affichage des portraits.
8. Les sections [Face], [Simul Face] et [Turn Face]
Les "Faces" sont les portraits des joueurs, et comme les lifebars, ils s'affichent différemment selon que vous êtes en solo, en simul ou en turns. Il y a donc trois sections sur le Face.
[Face] |
On voit que la section est relativement courte en solo. La première ligne indique le placement du portrait. Ensuite, le sprite appelé, (9000,0) correspond au mini-portrait dans le fichier SFF des personnages. Normalement, tous les personnages ont leur mini-portrait avec les groupe,image 9000,0. On notera que le offset est à 0,0 car le pos indique déjà la position du portrait, et que le offset contient des coordonnées relatives par rapport au pos, comme pour les lifebars. pour le joueur 2, il n'y a pas de surprise : le facing est à -1 pour orienter le portrait dans le sens inverse, et les coordonnées du pos correspondent au coin haut droit et non au coin haut gauche, à cause du facing = -1.
Nous pouvons passer maintenant au Simul Face :
[Simul Face] |
Là encore, il n'y a pas de réelle nouveauté, hormis qu'il y a 4 joueurs et non plus 2. Nous plaçons deux portraits de chaque côté cette fois, puisque notre cadre pour les portraits a été prévu à cet effet. Comme le cadre est aussi grand que pour le mode 1 contre 1, nous utilisons le scale pour réduire la taille des portrait. Nous utilisons le coefficient 0.48, qui correspond donc à 48%. Sachant qu'un mini-portrait normal fait 25x25 pixels, on obtient la nouvelle taille : 0.48x25 = 12, donc 12x12 pixels.
Nous pouvons maintenant passer au mode Turns, qui va apporter quelques nouveautés.
[Turns Face] |
Si la première partie (p1/2.face...) reste identique (puisqu'il s'agit de l'affichage du portrait du combattant actif, qui est identique au mode 1 contre 1), on trouve une nouvelle partie qui commence par p1/2.teammate.
Comme nous l'avons décrit dans le tableau des modules, le teammate désigne les partenaires, c'est à dire les membres de l'équipe Turns qui ne sont pas actifs à l'écran. En fait, on décrit ici le premier partenaire, qui va servir de modèle pour les suivants. Le pos indique la position du partenaire (le premier donc, et qui sera donc le second personnage à intervenir).
Le spacing indique la distance en x,y séparant un portrait du suivant. Attention : cette distance se calcule par rapport au pos, et non par rapport au bord droit du portrait précédent. Donc si on ne met que 1,0 pour le joueur 2, le premier portrait sera positionné en 181,27, mais le second en 182,27, ce qui fait que les deux portraits seront pratiquement l'un sur l'autre. On voit ici que l'on a conservé le scale à .48,.48 et que notre portrait fera donc 12 pixels de côté. Si nous voulons que les portraits soient collés les uns aux autres, nous mettrions donc 12,0. Les valeurs 13,0 nous permettent d'avoir en plus un pixel vide entre les portraits. On voit également que la valeur de spacing pour le joueur 1 est négative. Le négatif nous permet de décaler le portrait vers la gauche, alors que le positif provoque un décalage des portraits vers la droite.
Les éléments teammate.ko servent à décrire les partenaires éliminés. Nous avons créé un sprite en forme de croix rouge qui va se superposer au portrait du partenaire pour indiquer qu'il est éliminé.
Pour le reste (teammate.face), on retrouve des paramètres déjà vus (spr, scale...), à part qu'ils s'appliquent au portrait des partenaires et non des joueurs actifs.
Voilà pour les portraits. Il ne nous reste plus qu'un élément concernant les joueurs : les noms.
9. Les sections [Name], [Simul Name] et [Turn Name]
Les noms sont assez faciles à définir. Commençons par les noms en mode 1 contre 1 :
[Name] p1.pos = 63,11 p1.name.font = 3,0,1 p1.name.layerno = 1 p2.pos = 256,11 p2.name.font = 3,0,-1 p2.name.layerno = 1 |
En fait, on a déjà rencontré tous les modules présents ici (sauf le name, qui se rapporte au nom). En fait, l'élément principal à déterminer, c'est de savoir où vous voulez afficher les noms. Dans notre exemple, les noms s'affichent au dessus des jauges de vie. Le nom du joueur 1 sera aligné à gauche (le troisième chiffre du paramètre font est 1), et commencera donc à partir du x=63. Pour le joueur 2, en revanche, l'alignement se fait à droite (troisième chiffre du font à -1), ce qui signifie que le nom du joueur s'arrêtera à x=256. Mais vous pouvez également choisir d'afficher le nom au milieu de la barre de vie. Pour cela, vous devez calculer la position du centre de la barre en question, et mettre l'alignement à 0.
Passons maintenant au noms en mode Simul :
[Simul Name] |
Nous voyons qu'il y a ici 4 joueurs, mais que la syntaxe ne change nullement. Les alignements choisis nous permettent d'aligner les noms du joueur 1 et 4 au bord gauche de la barre de vie, tandis que les noms des joueurs 2 et 3 sont alignés au bord droit.
Nous terminons enfin par le mode Turns :
[Name] p1.pos = 63,11 p1.name.font = 3,0,1 p1.name.layerno = 1 p2.pos = 256,11 p2.name.font = 3,0,-1 p2.name.layerno = 1 |
Ceci n'appelle aucun commentaire particulier puisque le tout est rigoureusement identique au mode 1 contre 1.
10. Les sections [Time] et [Combo]
Nous en avons maintenant terminé avec les éléments propres aux joueurs. Nous allons aborder tout ce qui est plus général sur l'écran de jeu. Nous commençons avec les sections [Time] et [Combo].
La section [Time] définit ce qui est lié au compteur de temps. Bien évidemment, tout ceci (hormis l'affichage), n'a d'incidence que si vous déterminez une limite de temps au round dans les Options de Mugen.
Voici comment se présente cette section :
[Time] |
Le pos définit la postion du compteur. L'alignement du compteur se faisant forcément au milieu, nous positions ce compteur à la moitié de l'écran (qui fait 320 de large, je vous le rappelle). C'est d'ailleurs pourquoi le offset du counter (qui désigne le compteur) reste à 0,0. Comme l'alignement se fait forcément au milieu, seuls deux chiffres définissent la police.
Enfin, on trouve le fameux framespercount qui définit le nombre de frames qui peuvent s'afficher en 1 seconde de jeu. Je vous renvoi à la partie 4-c ("petit mot sur le temps") de ce tutorial pour plus d'explications. Par défaut, ce paramètre est défini à 60.
Passons maintenant à la partie Combo :
[Combo] pos = 20,80 start.x = -50 counter.font = 4,0 counter.shake = 1 text.text = HITS COMBO !!! text.font = 3,0 text.offset = 3,0 displaytime = 90 |
Cette partie correspond à l'affichage des Hits Combos (enchaînement de coups tel que si l'adversaire encaisse le premier, il ne sera pas en mesure de bloquer ou d'éviter les suivants). Ce texte est légèrement animé, puisqu'il peut apparaître en défilant depuis le bord du joueur qui réalise le combo. L'affichage du combo peut-être composé de 2 éléments : le counter et le text. Le counter correspond au compteur lui-même (affichage du nombre), et le text, au texte d'accompagnement du compteur. Toutefois, il est possible d'intégrer le compteur dans le text, mais dans ce cas, les attributs counter ne peuvent être appliqués, notamment le shake.
pos indique la position finale du texte de combo, après le défilement de départ.
start.x indique la coordonnée x depuis laquelle part le texte pour atteindre le x du pos. En mettant une valeur négative, vous donnez l'impression que le texte surgit réellement du bord, puisqu'il s'affiche en fait en dehors de l'écran de jeu avant d'apparaître.
Nous avons ensuite ce qui est relatif au compteur lui-même : la police et le "shake". Le shake est un attribut qui permet de faire vibrer légèrement le compteur (et uniquement le compteur) à chaque fois que celui-ci voit sa valeur augmenter. Mettez sa valeur à 1 pour l'activer ou à zéro si vous n'en voulez pas !
Enfin, nous terminons avec ce qui se rapporte au texte d'accompagnement. Tout d'abord, le texte lui-même (text.text). Vous pouvez mettre ce que vous voulez, du moment que la police possède les caractères nécessaires. Notez quand même que votre texte s'affichera à droite du compteur, et que vous ne pouvez pas inclure celui-ci tel quel dans votre texte. Vous pouvez donc mettre comme là : "Hits Combo !!!". Toutefois, si vous souhaitez intégrer le compteur dans votre texte, ceci est faisable. Il faut utiliser la syntaxe "%i" pour inclure le compteur. Mais ce compteur s'affichera dans la même police que le texte, et le shake ne pourra pas être appliqué. De façon générale, ce procédé donne un rendu moins joli. Exemple : text.text = CHAINE DE %i COUPS. Vous noterez également que le texte doit être entré sans guillemets.
L'offset du texte se calcul par rapport au pos (là encore, il s'agit de coordonnées relatives). Enfin le displaytime correspond au temps durant lequel le texte sera affiché, en ticks bien sûr.
Nous allons maintenant nous pencher sur une section un peu longue, consacrée au round. Nous allons la scinder en plusieurs parties, puisqu'elle traite de différentes choses.
Voici la partie round :
[Round] match.wins = 2 start.waittime = 10 ctrl.time = 200 round.time = 0 round.default.offset = 160,110 round.default.font = 3,0,0 round.default.text = ROUND %i round.default.displaytime = 150 round.default.layerno = 2 round1.snd = 0,1 round2.snd = 0,2 round3.snd = 0,3 roundsndtime = 30 |
La première partie concerne des généralités sur le round : le match.wins définit le nombre de rounds à remporter pour gagner le match. Dans la plupart des jeux, ce nombre est de deux, mais vous pouvez le modifier. Notez quand même que peu de lifebars sont prévues pour des matchs excédant les 4 ou 5 rounds. Le start.waittime est le temps à attendre avant de lancer l'intro du round, bref, avant que le round ne commence réellement. Enfin, le ctrl.time définit le temps à attendre avant que les personnages ne puissent être manipulés, une fois que le fight débute. Il correspond donc à la somme des paramètres fight.time et fight.displaytime.
Ensuite, nous passons à une série de paramètres débutant par le module round. En fait, tout ceci concerne l'affichage du numéro de round, qui intervient avant le fight. Le round.time est définit par Elecbyte comme le temps durant lequel "round" doit être affiché. Mais techniquement, ce paramètre n'a pas d'incidence sur le jeu car ce sont les autres qui agissent, c'est pourquoi il est à 0. Pour le reste : tous les paramètres commençant par round.default s'appliquent à tous les rounds.
Le offset définit toujours l'endroit où sera affiché le round, de préférence au milieu de l'écran en x, et pas trop bas. Définissez une font avec alignement central, ainsi votre texte sera bien centré à l'écran, c'est mieux. Pour le texte lui-même, vous pouvez mettre "%i" comme pour les combos pour préciser le numéro du round. Le displaytime indique le temps que sera affiché ce texte.
Les round1/2/3.snd indiquent les sons qui devront être joués lors du début du round (généralement une voix disant "round 1/2/3"). Enfin, le roundsndtime définit le temps pendant lequel le son doit être joué.
Passons maintenant à la partie fight :
fight.time = 90 fight.offset = 160,110 ;fight.text = NOW, FIGHT !!! fight.anim = 31 fight.font = 2,0,0 fight.displaytime = 110 fight.snd = 1,0 fight.sndtime =60 |
Notez que tous ces paramètres font partie de la section [Round]. Le fight.time est le temps qu'il faut attendre avant le fight ne s'affiche (là, faites des tests pour trouver le bon timing par rapport à l'affichage du "round"). L'offset définit la position du fight sur l'écran (généralement au même endroit que le round).
Ici nous avons mis le fight.text en commentaire puisque comme nous l'avons dit, nous allons utiliser une animation pour afficher le fight. C'est pourquoi nous utilisons le paramètre fight.anim = 31. 31 est le numéro de l'action que nous avons attribué à l'animation du fight, et nous aurons donc dans ce fichier une animation qui commencera par [Begin Action 31]. Nous étudierons cette animation à la fin de la section [Round]. Si vous voulez voir tout de suite comment ça se passe, cliquez là.
Nous avons laissé le fight.font, mais étant donné que nous n'utilisons pas de texte, ce paramètre devient superflu. On aurait pu le mettre en commentaire, voire le supprimer.
Le fight.displaytime indique combien de temps le fight doit être affiché. Dans le cas d'une animation, cela correspond à la somme des ticks de l'animation (voir l'animation en question).
Le fight.snd est le son à jouer pour le fight. Je vous renvoie au fichier fight.snd qu'il est possible de lire avec la dernière version de MCM, pour trouver à quoi cela se rapporte. Enfin, le fight.sndtime est le temps pendant lequel le son doit être joué.
Nous arrivons maintenant sur la partie "fin de combat", qui est également comprise dans la section [Round] :
KO.time = 0 KO.offset = 114,91 KO.spr = 15,0 KO.displaytime = 90 KO.snd = 0,5 KO.sndtime = 0 DKO.time = 0 DKO.offset = 160,100 DKO.text = Double KO ! DKO.font = 2,0,0 DKO.displaytime = 90 DKO.snd = 0,6 TO.time = 0 TO.offset = 160,100 TO.text = Time Over ! TO.font = 2,0,0 TO.displaytime = 60 TO.snd = 0,7 |
Tout ceci, vous l'aurez compris, se rapporte à la fin du combat, que ce soit par KO, Double KO (DKO) ou Time Over (TO). Pour rappel, le double KO est un cas très rare ou les deux adversaires se mettent KO en même temps (ou presque) avant la fin du temps imparti. Et le Time Over est le cas plus fréquent ou les deux adversaires n'arrivent pas à se mettre KO avant la fin du temps imparti.
Le schéma est le même, qu'il s'agisse de KO, DKO ou TO : le time indique le temps à attendre avant d'afficher le KO, DKO ou TO, l'offset, l'endroit où cela doit s'afficher, le text, le texte à afficher (pour le KO, on utilise un sprite, ce qui fait que l'on ne met pas KO.text, mais KO.spr), le displaytime est le temps pendant lequel ce texte/sprite/anim s'affiche, et le snd, le son à jouer. On peut rajouter un sndtime pour indiquer la durée du son.
Notons les coordonnées du sprite : 114 en x et 91 en y. En fait, notre sprite de KO fait 92x37 pixels. J'ai souhaité l'afficher de façon à ce qu'il soit centré sur le point 160,110. J'ai donc pris la moitié du sprite en x et en y et l'ai ôtée de ces coordonnées centrales. Pour la hauteur (37), j'ai pris le chiffre pair supérieur (38), ce qui donne : KO.offset = 160-(92/2),110-(38/2), soit donc KO.offset = 114,91.
Passons maintenant à "l'après combat" :
slow.time = 100 over.waittime = 100 over.hittime = 10 over.wintime = 100 over.time = 210 win.time = 110 win.offset = 160,90 win.font = 2,0 win.text = %s wins win.displaytime = 300 win2.offset = 160,90 win2.font = 2,0 win2.text = %s and %s win win2.displaytime = 300 draw.offset = 160,90 draw.font = 2,0 draw.text = Draw. draw.displaytime = 300 |
Tout ce qui est décrit ici concerne ce qui se passe après un KO, DKO ou TO.
Le slow.time est la durée pendant laquelle l'animation est ralentie une fois que le dernier coup, mettant fin au round, a été porté (cela ne concerne pas le TO).
Le module over correspond à la fin de l'action, et coïncide donc avec l'affichage du KO/DKO/TO (voire, se déroule avant !). Le waittime est le temps qui s'écoule avant que le contrôle du personnage cesse. Durant ce temps, vous pouvez donc continuer à bouger et à frapper votre adversaire ;o). Le hittime décrit le temps durant lequel vous pouvez continuer à vous battre (pour tenter d'arracher un double KO, par exemple). Le wintime est le temps qui s'écoule avant que le vainqueur ne prenne sa position de victoire. Enfin, over.time indique le temps qui s'écoule avant que le round soit définitivement terminé.
Le module win se rapporte à une victoire en mode 1 contre 1, que cette victoire résulte d'un KO ou d'un TO. Nous commençons par l'exception :oþ : win.time, qui s'applique en fait à la victoire seule, double ou à l'égalité. C'est le temps qui s'écoule avant que le texte proclamant le vainqueur ou l'égalité ne s'affiche.
Pour la suite du win, rien de très nouveau : le offset indique la position du texte à afficher, font, la police à utiliser (alignement 0 pour centrer le texte), et text, le texte à afficher, avec la syntaxe "%s" pour que le nom du vainqueur s'affiche. Enfin, le displaytime est le temps durant lequel s'affiche ce message.
On retrouve les même paramètres avec les mêmes fonction pour win2 (victoire en simultané, sur KO ou après un TO - on notera que %s est utilisé à chaque fois pour désigner les deux membres de l'équipe) et pour draw (égalité sur DKO ou TO).
Est-ce fini ? Oui, pour la section [Round]. Mais nous devons penser à l'animation :
Créer une animation est extrêmement simple, en fait. On définit une nouvelle section qui s'appelle [Begin Action X], ou X est un numéro d'animation, servant de référence dans les autres sections. Par exemple, pour appeler l'animation fight, on a entré le paramètre fight.anim = 31. On aura donc [Begin Action 31].
Vous pouvez mettre ces animations où vous voulez dans le fichier DEF, sauf à l'intérieur d'une section. Le plus simple est soit de les placer à la fin de la section dans laquelle chacune intervient, soit de toutes les placer à la fin du fichier DEF.
On utilise simplement 5 données par niveau d'animation. Par niveau d'animation, j'entends "changement d'image". Ici, nous avons mis trois images, qui donneront l'impression que le fight grossit. Nous utiliserons pour cela 3 niveaux d'animation. Attention : le nombre d'images différentes dans l'animation ne donne pas le nombre de niveau d'animation ! Si on avait voulu faire que le fight grossisse, puis rétrécisse, en utilisant les images dans l'ordre inverse, on aurait eu 5 niveaux (ordre des images : 1,2,3,2,1), bien qu'on n'ait que 3 images !
Ces 5 données sont : groupe,image,coordonnée x, coordonnée y,durée en ticks.
Voici le code l'animation :
[Begin Action 31] ;Animation du "Fight" 31,1,-9,-4,5 31,2,-16,-12,5 31,3,-18,-14,100 |
Les deux premiers paramètres ne posent aucun problème sur chacune des lignes, puisque ce sont simplement les références groupe,image du sprite appelé. En revanche, pour les coordonnées (du fight ici), il y a deux méthodes :
Soit on laisse le offset auquel l'animation se rapporte à 0,0, et on définit des coordonnées absolues dans l'animation, pour chaque sprite. Toutefois, cette méthode pose problème lorsque vous souhaitez centrer votre animation (c'est le cas du fight), parce que ce sont les coins haut gauche qui sont pris en référence. Vous devez alors calculez la largeur et la hauteur pour chaque sprite ainsi : (x1-[x2/2]),(y1-[y2/2]) avec x1 = coordonnée x centrale où vous souhaitez que votre sprite soit affiché, x2 = longueur en x du sprite, y1 = coordonnée y centrale où vous souhaitez que votre sprite soit affiché et y2 = hauteur du sprite. Pour afficher un sprite avec un centre à 160,110, et que vous ayez un sprite de 20x10, vous obtenez : (160-[20/2]),(110-[10/2]) soit 150,105. Et vous devez répétez les calculs pour tous les sprites. Vous noterez qu'on a déjà vu ces formules pour le cacul des coordonnées du sprite KO.
Soit vous définissez votre point central avec le offset (ex : fight.offset = 160,110 - c'est ce qu'on a fait), et dans ce cas, les coordonnées que vous entrez sont des coordonnées relatives par rapport à ce point central, que vous obtenez en faisant -(x2)/2 et -(y2)/2, ou x2 et y2 sont, comme précédemment, la largeur et la hauteur du sprite. On obtient ainsi des coordonnées de -10 et -5 pour notre sprite de 20x10. Le signe négatif permet de créer un décalage pour centrer l'image (par rapport au point central qui devient l'origine 0,0). L'image va ainsi de -10 à +10 en x et de -5 à +5 en y, et est donc bien centrée par rapport au point central défini par le offset.
Personnellement, je trouve la seconde méthode beaucoup plus simple, mais vous faites comme vous le sentez !
Enfin, la cinquième donnée est la durée d'affichage, en ticks bien sûr, du niveau d'animation. Ici, on aura donc une animation qui dure 5+5+100 = 110 ticks. C'est ce nombre qui doit alors être reportée dans le fight.displaytime.
Nous pouvons enfin aborder la dernière partie : le [WinIcon]
Qu'est-ce donc que cette section ? Eh bien elle décrit tout simplement l'icône de victoire d'un round, notre Icône Round. Pour ce tutorial, nous n'avons pris qu'une seule icône, mais vous allez voir qu'il est possible d'en utiliser plusieurs totalement différentes. Commençons par le code :
[WinIcon] p1.pos = 61,22 p2.pos = 248,22 p1.iconoffset = 11,0 p2.iconoffset = -11,0 ;p1.counter.offset = 0,10 ;p2.counter.offset = 0,10 ;p1.counter.font = 1,0 ;p2.counter.font = 1,0 p1.n.spr = 10,0 p2.n.spr = 10,0 p1.s.spr = 10,0 p2.s.spr = 10,0 p1.h.spr = 10,0 p2.h.spr = 10,0 p1.throw.spr = 10,0 p2.throw.spr = 10,0 p1.c.spr = 10,0 p2.c.spr = 10,0 p1.t.spr = 10,0 p2.t.spr = 10,0 p1.suicide.spr = 10,0 p2.suicide.spr = 10,0 p1.teammate.spr = 10,0 p2.teammate.spr = 10,0 p1.perfect.spr = 99,99 ;sprite vide p2.perfect.spr = 99,99 ;sprite vide useiconupto = 3 |
On commence fort logiquement par le placement de cette icône (en générale près de la barre de vie) avec le pos. Nous trouvons ensuite le paramètre iconoffset, qui est l'équivalent du spacing des teammates, à savoir qu'il décrit à quel endroit sera placé l'icône round suivante, à partir du pos (si c'est la première icône affichée) ou de la dernière carte affichée (dans le cas contraire). Là encore, le positif décale les icône vers la droite, et le négatif, vers la gauche.
Nous arrivons ensuite sur le compteur, mis ici en commentaire (p1/2.counter). Celui-ci est utilisé lorsque le nombre de rounds remportés par un joueur dépasse la valeur du paramètre useiconupto. On trouve juste des modules d'affichage (offset) et de font. Ce compteur reste toutefois très peu utilisé, mais peut être utile pour des longs match (ex : Turns VS Turns en 4 contre 4).
Ensuite, tous les paramètres désigne une icône pour un type de victoire différent. Voici ces différents types :
n : Victoire par coup normal
s : Victoire par coup spécial
h : Victoire par coup hyper (fury)
throw : Victoire par projection
c : Victoire par cheese
t : Victoire par Time Over
suicide : Victoire par suicide de l'adversaire
teammate : Victoire sur l'adversaire battu par son propre partenaire
perfect : Victoire avec Perfect (sans que la barre de vie ne soit entamée);
N'ayant qu'une seule icône de victoire (icône round), nous utiliserons à chaque fois le même sprite (sauf pour le perfect, voir paragraphe suivant), mais notez qu'il est possible d'utiliser une icône différente pour chaque type de victoire. On notera également que comme le iconoffset est général et s'applique à tous les types de victoire, si l'on souhaite utiliser des icônes différentes selon le type de victoire, leur taille devra être identique.
Particularité du Perfect : le Perfect est un type secondaire de victoire, qui n'est pas incompatible avec les autres. Par exemple, on peut vaincre avec un hyper tout en faisant un perfect. C'est pourquoi l'icône perfect vient s'ajouter l'icône de victoire (en l'occurrence, sur la victoire par hyper). Dans la lifebar de base fournie avec Mugen, cette icône est représentée par un "P" vert. Pour ce tutorial, nous avons choisi de ne pas faire d'icône perfect. A la place, nous avons créé un sprite vide, le 99,99, qui est un pixel coloré avec une couleur d'index 1, et est donc interprété comme transparent. En l'occurrence, ce sprite étant transparent, il n'apparaîtra pas à l'écran, et la victoire par perfect n'affectera pas l'affichage.
Enfin, le dernier paramètre du fichier : useiconupto, qui indique combien d'icône on peut afficher. Si on dépasse ce chiffre, les icônes victoires ne s'afficheront plus.
Voilà, vous avez terminé votre fichier. Vous pouvez l'enregistrer (normalement sous fight.def) et les tester !
13. COMPLEMENT : LES EFFETS DE TRANSPARENCE
Pour divers éléments des lifebars, il peut être intéressant de rajouter un effet de transparence, sur le fond des jauges, par exemple. Pour ce faire, il y a deux moyens. Le premier coule de source lorsque l'on connaît un peu Mugen : il s'agit de jouer sur la couleur de transparence, c'est-à-dire l'index 0 de l'image. C'est ce que nous avons fait là :
Le fond des jauges de vie est parsemé de noir. Un zoom nous permettrait de constater qu'un pixel sur deux est en noir, et l'autre, en rose bonbon (interprété par Mugen comme étant transparent). L'effet est somme toute assez moyen, donnant une impression de "crans" sur les bords de la jauge :
Sur cette image, le rendu semble quand même acceptable. Mais les réglages graphiques de Mugen (fichier mugen.cfg) permettaient de "lisser" l'image pour la rendre agréable (résolution 640x480, Vretrace à 1, DoubleRes en Bilinear Filtering). Malheureusement, tous les PC ne supportent pas cette configuration, et si vous jouez avec les réglages de base (résolution 320x240, pas de Vretrace, DoubleRes sur off), l'image est alors très pixellisée, et l'effet de cran ressort beaucoup plus.
Il existe toutefois une autre solution, beaucoup plus esthétique, et plus souple, pour ces effets de transparence. Elle consiste à utiliser les effets d'ajout ou de retrait de luminosité des sprites d'animation. Pas de panique, c'est très simple ! Mais vous allez devoir scinder votre sprite de fond en deux : un pour le contour de l'élément que vous souhaitez rendre transparent (ici, le contour des jauges de vie), et un pour l'élément transparent lui-même (le fond des jauges de vie).
Ensuite, il va falloir modifier le code de base. Je vous donne ici le code pour le joueur 1 en mode solo, mais vous devez maintenant être capable de l'appliquer sans problème aux autres joueurs, et aux autres modes :
[Lifebar] p1.pos = 0,10 p1.bg0.spr = 1,0 p1.bg0.layerno = 2 p1.bg1.anim = 1 p1.bg1.layerno = 2 |
Bon, expliquons un peu la chose. Nous retrouvons notre p1.bg0.spr = 1,0 qui appelle toujours notre sprite de jauge de vie (mais cette fois, ce sprite ne contient que le contour de la jauge !). Mais on trouve maintenant un p1.bg1.anim = 1. Ce bg1, comme dit en début de tutorial, désigne un sprite de fond. Ce bg1 va désigner le fond des jauges de vies. Pourtant, techniquement, ces jauges ne sont pas des animations, mais des sprites uniques. Cependant, pour leur appliquer l'effet de transparence, nous sommes obligés d'en passer par une animation, qui ne contiendra qu'un seul sprite. Et voici donc comment va se présenter le code de l'animation :
[Begin Action 1] 3,1,31,3,1,,A |
Le sprite 3,1 est celui que nous avons utilisé pour ce fond de jauge. Les coordonnées x,y (31,3) sont logiquement les mêmes que pour les barres de vie et barres de vie perdue. Comme l'animation est répétée indéfiniment, en affichant toujours le même sprite, le temps d'affichage importe peu. Par défaut, on met 1. Ensuite, on trouve DEUX virgules. N'oubliez surtout pas la seconde virgule.
En effet, il y a un paramètre entre le temps (1) et le paramètre suivant (A). Ce paramètre permet des retournements horizontaux et verticaux. Comme nous ne nous en servons pas, nous ne mettons rien. Cependant, nous devons signaler à Mugen, par une seconde virgule, que nous laissons ce paramètre vierge, et que le "A" est bien le 7ème paramètre et non le 6ème.
Venons-en au dernier paramètre. Il peut avoir deux valeurs, et les deux provoquent un effet de transparence : A, pour Add, permet de donner un effet de filigrane au sprite. Le sprite devient ainsi très clair. S, pour Sub, met le sprite en négatif. Voici le résultat :
Le fond de la jauge de vie utilise un effet "A", tandis que le fond de la barre de power utilise un effet "S". Voici les sprites de départ :
fond de la barre de vie
fond de la barre de power
Attention cependant : sous peine d'obtenir des résultat assez "particuliers", n'utilisez pas de couleurs noire (0,0,0) ou blanche (255,255,255) dans les sprites.
Voilà ce que l'on pouvait dire sur les effets de transparence, qui peuvent considérablement améliorer le rendu des lifebars.
Nous allons voir comment manipuler les deux fichiers que vous avez créé. Nous avons deux cas : soit vous souhaitez remplacer purement et simplement la lifebar déjà installée, soit vous souhaitez l'ajouter, tout en conservant l'ancienne (recommandée en cas de problème...).
Vous souhaitez supprimer la lifebar en place pour mettre la vôtre ? Rien de plus simple. Les deux fichiers que vous avez créés avec ce tutorial doivent s'appeler fight.sff et fight.def. Il suffit de les copier dans le répertoire Data, en écrasant les fichiers existants. Si toutefois, au lancement de Mugen, vous aviez toujours l'ancienne lifebar, dans ce cas, il est probable que vous ayez un screenpack qui utilisait des fichiers différents. Ouvez le fichier system.def qui se trouve dans Data, et dans la section [Files], au début du fichier, trouvez la ligne commençant par :
fight = |
Et mettez :
fight = fight.def ; fichier de définition de la lifebar |
Enregistrez, et lancez Mugen : cette fois, il ne devrait plus y avoir de problème. Notez que le commentaire est facultatif ;o).
b. Ajouter les lifebars sans supprimer celles déjà existantes
C'est peut-être le cas le plus prudent, si vous souhaitez pouvoir récupérer votre ancienne lifebar (pour la réutiliser ou y trouver des commentaires, ou des exemples). Vous avez deux possibilités : soit vous nommez vos deux fichiers différemment, soit vous créez un répertoire spécifique pour votre lifebar. Mettons que l'on nomme nos fichiers "fight-test.sff" et "fight-test.def". Mettez alors vos fichiers dans le dossier Data, puis ouvrez le fichier fight-test.def, et dans [File], à la ligne "sff =" remplacez "fight.sff" par "fight-test.sff". Ensuite, ouvrez le fichier system.def, toujours dans le dossier data, et à la ligne "fight =", entrez "fight-test.def" à la place du fichier DEF qui était spécifié. Au prochain lancement de Mugen, votre lifebar sera active.
Dernière possibilité, vous créez un dossier "lifetest" (par exemple), dans lequel vous mettez vos fichiers fight.def et fight.sff. Placez ce dossier dans le dossier Data, et modifiez le system.def, sur la ligne "fight =", en mettant "fight = lifetest/fight.def". Le système de dossier peut être utile si vous changez souvent de lifebar.
Je tiens à remercier tout une série de personne sans qui ce tutorial n'aurait jamais pu voir le jour :
Puppet Master, alias GhOw, webmaster du site Aprog, pour le screenpack Super Street Fighter II que nous avons réalisé, et qui m'a donné l'envie de me mettre aux lifebars
Cabbit007 pour son tutorial sur les lifebars, même si seul, il est un peu incomplet et comporte quelques erreurs... ;o)
Orochi KOF 97 pour sa traduction en bon français dudit tutorial (ce qui est assez rare sur le net de nos jours...) et pour sa distribution, ainsi que pour ses tutoriaux sur les screenpacks
Elecbyte pour avoir créé Mugen, mais aussi pour avoir eu l'excellente idée d'inclure des commentaires dans les fichiers :o)))))
Et tout plein de monde auquel je ne pense pas forcément (I apologize...).
HAVE FUN !!!
Auteur du tutorial :
Mike Werewolf
Site : http://mike.werewolf.free.fr/
Date de création :
Ce texte reste ma propriété, et je vous demanderai donc de bien vouloir me contacter avant de distribuer ce tutorial autour de vous. Il en va de même si vous souhaitez modifier ce texte en y apportant des modifications, ou en supprimant des passages. Merci de respectez l'éthique Mugen afin que Mugen puisse continuer à vivre et à progresser.
L'ETHIQUE DE MUGEN, QUELQUES MOTS...
Le problème est que pas mal de personne passe outre cette éthique morale et prenne leurs aises en "hostant" (rendant téléchargeables directement depuis leur site) des personnages, des stages, des screenpacks, bref, toute création liée à Mugen sans demander l'autorisation à l'auteur, en les incluant dans des jeux de la même façon, en les modifiant, ou encore pire, en vendant des jeux mugen, qui est et doit rester dans tous les cas gratuit.
Bafouer cette éthique engendre énormément de problèmes que les "pirates" (appelons-les ainsi...) n'imaginent pas toujours, ou dont ils se foutent des conséquences. Pourtant, elles existent, et se traduisent pour l'instant par le départ de créateurs. Ces auteurs, qui voient leur travail (bénévole, rappelons-le) galvaudé par des profiteurs, préfèrent arrêter de créer pour la communauté Mugen, la privant ainsi de ses créations. C'est assez grave en soi puisqu'ils n'existent pas tant de créateur que cela, puisque la réalisation d'un personnage par exemple demande souvent beaucoup de travail, de temps, d'énergie. Seuls les passionnés s'y risquent, et il est dommage de leur faire perdre la foi.
L'autre risque est, d'une certaine manière, plus grand encore, même s'il ne s'est pas réalisé pour l'instant : il s'agit des réactions des éditeurs. La plupart des créations sont en fait "mugenisés", c'est à dire adaptés d'un jeu vidéo pour Mugen. Ces éléments appartiennent aux firmes qui les créent (Capcom, SNK, Akklaim, etc.), et leur utilisation pour Mugen est simplement tolérée, du fait que ce concept est entièrement gratuit, et constitue une sorte "d'hommage" aux jeux. Mais si certains s'amusent à vendre Mugen, ces sociétés pourraient voir d'un mauvais oeil que des petits malins se fassent du fric sur leur travail. Elles pourraient ainsi décider d'user de leur droit de propriété pour se faire verser des royalties sur leurs créations. Le problème est qu'il y a peu de chance que ce soit les pirates qui paient, mais plutôt les créateurs : pour créer un personnage censé être distribué gratuitement, il faudrait alors payer. Mais les sociétés pourraient également envisager d'interdire purement et simplement l'utilisation de leurs créations pour Mugen. Ce serait alors la fin de ce concept.
C'est pourquoi vous êtes invités à respecter l'éthique morale de Mugen, pour lui permettre de continuer de vivre, tout simplement.