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

Boucles évènementielles

Xavier Van de Woestyne edited this page Jan 11, 2020 · 13 revisions

Attention, cette fonctionnalité n'est disponible que depuis RME 2.1.0 et est encore en phase d'incubation. N'hésitez pas à faire remonter des rapports de bugs si vous découvrez un problème à l'usage !

Quand on construit des systèmes évènementiels, on manipule très souvent des boucles. Même si les boucles RPGMaker permettent de faire énormément, elles sont tout de même très verbeuses. En effet, on ne dispose que de deux primitives pour construire des boucles :

  • créer une boucle ;
  • sortir de la boucle (ou encore Aller à l'étiquette).

Dans beaucoup de cas, c'est parfaitement suffisant. Par exemple si je veux effectuer un système complexe en évènement, il est possible d'économiser les pages en respectant cette structure :

Un système classique

Même si c'est une approche commode de procéder, il arrive parfois que dès lors que l'on veuille travailler sur des boucles un peu plus spécifiques, par exemple, des boucles qui doivent maintenir un compteur, il faille écrire plus de code. On arrive souvent à des boucles très verbeuses/longues pour, au final, n'exécuter qu'une toute petite tâche.

Un premier scénario

Imaginons que nous voudrions faire compter un personnage jusqu'à un nombre décidé par le joueur. Voici comment il serait possible de procéder naïvement :

Un système de comptage

Concrètement, notre système est très proche du squelette présenté précédemment, on retrouve :

  • une phase d'initialisation ;
  • la boucle de calcul ;
  • après la boucle, la phase de conclusion.

Dans le cas des compteurs, il faut d'abord avoir une variable qui représente l'objectif, ensuite une autre variable qui représente l'état courant (on appelle souvent ça un itérateur). Ensuite, dans la boucle on défini une condition de sortie pour définir quand le système à fini de compter. Ensuite on a le corps du système, l'action qui doit être répétée. Et après notre boucle, la phase de conclusion.

Tout ce code nécéssaire pour construire un simple compteur s'appelle, dans le jargon des programmeurs, du boilerplate. Quand on veut construire des systèmes ambitieux, ces petits détails récurents peuvent parfois ralentir l'ambition. C'est pour cela que RME introduit des commandes pour enrichir les boucles !

Un compteur implicite derrière chaque boucles

La première commande que nous allons observer est loop_step. Cette petite commande, qui ne prend pas d'arguments doit impérativement s'utiliser dans une boucle (sinon elle renverra nil, ce qui correspond à "rien du tout"), et elle compte le nombre de fois que l'on traverse une boucle sans passer par un sortir de la boucle. Elle nous permet donc de supprimer la variable compteur (et son incrémentation) :

Un système de comptage avec loop_step

La logique d'incrémentation du compteur est encodé dans la fonction loop_step, il ne faut donc plus s'en soucier ! Par contre, pour ceux qui essaient le code, vous remarquerez qu'au premier passage, loop_step vaut 0. C'est parce que la commande compte le nombre de fois que l'on a "traversé" la boucle. Pour avoir exactement le même comportement que dans la version "pure event-making", il faudrait modifier l'attribution de la variable de cette manière : V[2] = loop_step + 1. Mais c'est du détail !

Il est bien sûr possible d'imbriquer des boucles, la commande restera cohérente (et si ce n'est pas le cas, c'est un bug, et il en faut pas hésiter à nous le communiquer pour que nous puissions le corriger !

Bon, c'est "un peu plus court", mais je dois toujours gérer la logique "de sortie de la boucle". Heureusement, RME offre des décorateurs aux boucles pour construire des boucles plus expressives.

Une boucle qui implémente un compteur

Essayons de raccourcir notre système en utilisant la commande loop_times. Cette commande est un décorateur de boucles. Il doit impérativement être utilisé juste avant une boucle, et il va "modifier" le comportement de la boucle. Ici, la commande loop_times(N) va permettre de dire à la boucle :

J'aimerais que tu t'exécutes N fois avant de sortir

De ce fait, plus besoin d'écrire nos conditions de sorties. Essayons de voir ce que cela donne :

Un système de comptage avec loop_times et loop_step

Cette fois-ci, on n'a plus du tout de conditions dans notre boucle. Par contre, rien ne vous empêche de tout de même sortir de la boucle. Sachez juste que quand vous "reviendrez" dans la boucle, elle repartira de zéro.

Après loop_step, loop_state !

Comme je vous l'ai dit, loop_step donne le nombre de passage dans une boucle. Cependant, parfois, on voudrait ne pas faire "que" des boucles qui vont de 0 à x. Parfois, on voudrait parcourir d'autres valeurs. Dans nos exemples précédents, nous ajoutions 1 à loop_step pour mimer le comportement de notre système en "event-making pur`. Voyons de quelle manière il serait possible de dire à la boucle :

J'aimerais que tu boucles de x à y.

Pour cela, nous allons utiliser un autre décorateur de boucle. Comme pour loop_times, il doit impérativement se trouver au dessus de la boucle qu'il va décorer. Je vous présenter loop_range(a, b). Ce décorateur va aller de a à b (où a et b sont inclus). Donc dans notre cas, nous pourrions faire loop_range(1, V[1]) au dessus de notre boucle.

Mais la subtilité ne s'arrête pas là. Comme je vous l'ai dit, loop_step compte le nombre de fois que l'on est passé dans la boucle. Donc peu importe que l'on demande à notre boucle d'aller de 1 à x+1 ou de 0 à x, notre loop_step aura toujours la même valeur !

Heureusement, la commande loop_state arrive à la rescousse ! Elle ressemble beaucoup à loop_step si ce n'est que c'est le décorateur qui va définir quelle valeur elle doit avoir. Dans le cas où l'on a pas de décorateur ou qu'on utilise loop_times, loop_step et loop_state ont la même valeur. Si par contre nous utilisons loop_state avec loop_range(12, 22), a la première étape, loop_state vaudra 12, ensuite 13, ensuite 14 ... pour finir à 22 !

Sans plus attendre, réécrivons notre système avec loop_range !

Un système de comptage avec loop_range et loop_state

Cette fois-ci, nous n'avons plus besoin du "+1" qui nous ennuyait dans les exemples précédents ! C'est le décorateur qui va aller "piocher" la bonne valeur dans l'intervalle. Imaginons maintenant que nous voudrions... pour une raison obscure, que notre compteur parte du nombre choisi et déscende jusqu'a 1 ? Rien de plus simple, il suffit d'inverser nos deux paramètres de loop_range(x, y). Par exemple :

Un système de comptage avec loop_range et loop_state

Simple !

Aller plus loin avec loop_for

Actuellement, nous n'avions que manipulé des intervalles numériques. La commande loop_for prend un tableau et loop_state aura la valeur de chaque cellule du tableau. Par exemple, si je voulais que notre compteur "dise bonjour à Joke, Grim et Zangther", je pourrais faire quelque chose comme ça :

Say Hello to the RMEx Team

De même qu'il existe des commandes RME qui renvoie des tableaux. Par exemple, la commande team_members, qui renverra, dans un tableau, la liste de tous les identifiants de l'équipe. Avec un peu d'astuce, il est possible de faire très facilement des systèmes relativement complexes :

Iteration sur l'équipe

loop_for et les Selecteurs

Les Selecteurs sont une fonctionnalité puissante de RME, ils permettent d'appliquer des "batches" de modification à plusieurs évènements, images etc. Cependant, pour qu'il selecteur puisse être utiliser avec une commande, il faut que la commande ait été prévue pour. Or, il existe beaucoup de commandes qui n'ont pas été pensées pour fonctionner avec les sélecteurs. Par exemple, la commande event_jump.

Pas de panique, les boucles, et spécifiquement loop_for permet de palier très facilement à ce problème. En effet, la boucle loop_for peut parfaitement prendre un selecteur en argument ! Par exemple, imaginons que je veuille faire sauter l'ensemble des événements sur place ! Rien de plus simple :

Tout le monde saute

Pour conclure !

Les décorateurs de boucles sont une fonctionnalité puissante qui permet de réduire énormément de lignes de code évènementiel tout en restant, selon moi, lisible. De plus, ils se marient parfaitement avec les sélecteurs et offrent plus de fonctionnalités ! N'hésitez pas à vous en servir et surtout, si vous trouvez des soucis (ou des problèmes d'ergonomies), n'hésitez surtout pas à nous le communiquer pour que l'on puisse le corriger au plus vite. (Poussez le système dans ses limites en imbriquant des boucles).

Inspiration

Ce système à été initalement implémenté par @Grim dans PICOMV, et je me suis grandement inspiré de son implémentation et de ses choix de designs (avec son accord). Merci à lui !

Clone this wiki locally