Skip to content
This repository has been archived by the owner on Jul 24, 2020. It is now read-only.

Créer des jauges en combat

Xavier Van de Woestyne edited this page Jul 20, 2017 · 3 revisions

Dans ce tutoriel, nous allons voir étape par étape comment personnaliser le système de combat de base de RPG Maker VXAce, au moyen des évènements de combats, les court-circuits. Nous avions vu dans la section juste au dessus comment créer une jauge, nous allons mettre en pratique ce que nous avons étudié dans l'ajout des jauges en combat.

Première difficulté

Quand on programme un système en évènement relatif au système de combat, on ne connait généralement pas le nombre d'ennemi. Il faudra donc travailler avec des offsets, qui seront des variables qui donneront le premier index. Pour "plus de lisibilité", j'utiliserai des labels. Par exemple, comme je ne sais pas à l'avance (et que ça change d'un combat à l'autre) le nombre de jauges à afficher, je décrirai un label pour le premier ID d'image de la jauge.

De même que pour travailler sur chaque monstre individuellement, il me faudra ce qu'on appelle un itérateur, qui sera un simple compteur qui bouclera pour chaque monstre.

Structure générale du projet

Nous n'utiliserons qu'un seul évènement commun, nommé BattleGauge qui appellera plusieurs évènements communs que nous aurons créés. Le seul évènement qui sera in_battle sera BattleGauge.

Image des jauges dont je me sers :

miniA miniB

La première étant pour le fond et la seconde pour le corps de la jauge. Le fond est appelé miniA.png et le corps miniB.png.

Première étape : Initialiser les valeurs

La première étape de ce tutoriel sera de créer un évènement commun (que nous nommerons [BattleGauge]Initialize dont le rôle sera d'initialiser les labels que nous utiliserons.

Code

Le code est volontairement commenté à foison, nous allons détailler le rôle des variables que nous définissons.

  • L[:troop_id] est assez simple, c'est juste une variable pour avoir rapidement accès à l'id du groupe que l'on combat.
  • L[:troop_size] est le nombre d'ennemi que l'équipe doit combattre.

Ces commandes sont trouvables dans la documentation, dans la section En Combat

  • L[:offset_bg] et L[:offset_fg] donnent les indices minimums pour les fonds de jauges et pour les corps de jauges. Grâce à ces indices, on sait que les images de corps seront toujours au dessus des images de fond, car leurs id commencent après tous les fonds affichables. En voyant l'itérateur, nous verrons comment se servir de ces variables pour fournir une image (enfin, ici, deux) par monstre.
  • L[:last_hp] est l'indice minimum des variables dans lesquels nous stockeront les points de vie des monstres. (Pour n'avoir à modifier la taille de la jauge que quand un monstre prend un dégat).

L'itérateur

L'itérateur est un label un peu particulier, il s'agit d'une variable qui commence par valoir zéro, et qui s'incrémente à chaque passage dans la boucle. Comme les ennemis dans un groupe sont référencés par un numéro, le premier étant zéro, l'itérateur permet d'attribuer un passage de boucle par ennemi. Par exemple, pour avoir l'identifiant de l'image de fond de la jauge d'un ennemi, il suffit de faire L[:offset_bg] + iterator. Pour manipuler l'itérateur, je crée deux évènements communs. Le premier sert à l'initialiser à zéro et s'appelle [BattleGauge]IteratorToZero:

Code

Son rôle est simple, elle attribue zéro au label L[:iterator]. Si j'utilise un évènement commun, c'est parce que je m'en sers plusieurs fois.

Le second évènement, nommé [BattleGauge]IteratorIncr s'occupera d'incrémenter l'itérateur :

Code

Il se contente d'ajouter 1, et d'appliquer un modulo par la taille de l'équipe pour que la boucle ne dépasse jamais le nombre d'ennemi. Par exemple imaginons cet évènement :

Evenement_commun("[BattleGauge]IteratorToZero")
Boucle 
  # Quelquechose
  Evenement_commun("[BattleGauge]IteratorIncr")
Fin_boucle

Le label L[:iterator] sera toujours compris entre zéro et le Afnombre d'ennemi (-1, car on commence à zéro). Cet itérateur nous permettra donc de faire des boucles qui ne se focaliseront que sur les ennemis, étape par étape.

Afficher les jauges

L'enjeu de cette partie est assez important car elle va permettre de comprendre l'intérêt de l'itérateur. Ici nous allons devoir afficher toutes les jauges pleines au dessus des monstres. Pour ça, il va falloir boucler sur tous les monstres du groupe que l'on combat dans un évènement commun [BattleGauge]DisplayGauges:

Code

Note, une petite modification dans la documentation fait que la commande monster_battler_height n'a pas plus besoin de l'ID du groupe en premier argument :), il n'est donc pas nécéssaire de l'utiliser.

Cette partie n'est pas vraiment complexe (même si elle le parait). Concrètement, on calcule les positions des jauges. Comme vous pouvez le voir, on se sert d'une addition d'un offset avec l'itérateur pour récupérer le bon identifiant d'image. Il y a quelques ajustements pour positionner correctement les jauges. Le -33 est pour centrer la jauges au dessus de l'ennemi (la jauge fait 66pixels de large). L'usage de max permet de garantir que la jauge sera toujours visible, si un ennemi est trop grand et qu'elle doit sortir, elle sera affichée collée contre le haut de l'écran.

On en profite aussi pour préparer les variables propres à chaque monstre qui stockent leurs points de vie.

Comme l'itérateur est incrémenté via l'évènement commun, il faut lui demander explicitement de sortir de la boucle quand on a parcouru tous les monstres. Soit quand l'itérateur est égal à la taille du groupe - 1. Ou alors il aurait été possible de faire cette condition après l'incrémentation, et là il aurait fallu vérifier que l'itérateur est égal à zéro pour sortir de la boucle.

Donc on peut établir certains axiomes. Dans une boucle qui incrémente l'itérateur, partant de 0 :

  • L[:offset_bg] + L[:iterator] : ID du fond de la jauge pour le monstre parcouru
  • L[:offset_fg] + L[:iterator] : ID du corps de la jauge pour le monstre parcouru
  • V[L[:last_hp] + L[:iterator]] : Variable contenant les derniers points de vie stockés du monstre parcouru.

Boucle générale

Toutes les phases présentées précédemment concernaient l'initialisation. Maintenant, nous allons créer la boucle principale qui se répétera durant tout le combat. Pour cela on crée un évènement commun [BattleGauge]GeneralLoop. Son rôle est assez simple :

  • On remet l'itérateur à zéro et on boucle sur ce qui suit :
  • On récupère les points de vie du monstre référencé par l'itérateur
  • Si le monstre est mort on va à la fin de la boucle (via une étiquette) et on supprime ses images de jauges
  • Pour savoir si un monstre a été touché on vérifie que V[L[:last_hp] + L[:iterator]] est différent des points de vie que l'on a récupéré.
  • Si le monstre a été touché, on calcule son pourcentage de vie restante et on modifie l'image référencée par L[:offset_fg] + L[:iterator].
  • A la fin on incrémente l'itérateur

Ce qui donne :

Code

Le code a l'air complexe, mais il est en vérité très simple. Chaque étape est assez explicite.

Evènement principal

Maintenant que nous avons tous les ingrédients nécéssaire, il suffit simplement de créer un évènement commun BattleGauge qui appellera chacun des évènements communs, dans le bon ordre, que nous avons créé et qui lui aura l'activation "en combat" :

Code

Quand tout est bien fait, vous pouvez tester (via la base de données par exemple), un combat avec un groupe de monstres et si vous avez bien respecté la démarche, vous devriez voir des jauges apparaitre et se mettre à jour en combat. Par exemple :

example

Conclusion

Nous avons vu un premier usage des hacks possibles avec RME. N'hésitez pas à proposer les vôtres :)

Ce qu'il faut retenir, c'est que la notion d'itérateur est très importante, pour la construction de systèmes complexes. Il ne faut pas hésiter à relire ce cours pour en comprendre l'intérêt et leur fonctionnement.

Pour aller plus loin

Notre système ne tient pas compte des monstres cachés et leur affiche tout de même une jauge. Je vous propose en exercice de recoder le système pour qu'il évite les monstres cachés en vous servant de cette commande :

enemy_hidden?(position)

renvoie true si l'ennemi en combat référencé par sa position en combat est invisble, false sinon

Nom Type Description
position Fixnum Position du monstre en combat (0 = premier) (attention ce n'est pas l'ID du monstre dans la base de données!!!)

Pour ça, il faut ne pas afficher sa jauge et ne pas l'itérer normalement. Bonne chance !

Clone this wiki locally