Création d'un Shifumi avec le RGSS3
{Tutoriel de script RPG Maker VX Ace}
Dans ce tutoriel, nous allons survoler la création d'un script simple avec Ruby et le RGSS3. L'objectif de cet article n'est pas de présenter "tout" ce qu'il faut savoir du Ruby et du RGSS3 mais plutôt de présenter rapidement son fonctionnement aux gens pressés, non soucieux de tout savoir mais plutôt désireux d'apprendre "par l'exemple".
- S4suk3, 20/04/2013 à 00h19.


Création d'un Shifumi avec le RGSS3 - S4suk3

Création d'un Shifumi avec le RGSS3


Cet article va présenter comment créer un jeu de pierre-feuille-ciseaux en script de manière rapide, sans s'étaler théoriquement sur les concepts survolés. J'invite donc les lecteurs méticuleux à effectuer leurs propres recherches... parce que c'est tout de même plus cool de connaitre correctement ce que l'on utilise.


icone Introduction


Bonjour ! Si tu as fantasmé sur les scripts des gens, que tu as toujours voulu créer tes propres systèmes, que tu trouves que l'Event-Making, c'est beaucoup de choses pour pas grand chose mais que tu as toujours trouvé que l'apprentissage des scripts était une chose trop complexe (et oui... apprendre le Ruby puis comprendre le RGSS c'est pas toujours évident!), ce tutoriel est pour toi !
En effet, nous allons apprendre à réaliser un Shi-Fu-Mi (qui est l'appellation cool de Pierre-Feuille-Ciseaux) via Ruby et le RGSS3 (de RPG Maker VX Ace donc) en admettant que vous n'avez strictement aucune connaissance en programmation autre que l'Event-Making.
Je suis moi même persuadé que l'apprentissage de la programmation est une démarche rigoureuse et qui demande beaucoup d'implication, mais comme la tendance n'est pas à la rigueure mais au prêt-à-coller, je vais tenter de faire, au mieux, abstraction de pleins de choses compliqués, qui, généralement, font tomber les débutants dans un état de léthargie typique.

Je ne suis pas familier avec ce style de rédaction
que j'ai plagié sur Joke, donc excusez mon humour parfois "mécanique",
je vous jure que je fais de mon mieux.


icone Avant propos sur Ruby et le RGSS


J'ai promis qu'il n y aurait pas de baratin technique... j'ai mentit. En effet, je pense que pour que ce tutoriel soit utile, quelques directives techniques sont de mises. Rassurez-vous, je n'ai pas l'intention de vous assommer de jargon, je vais me contenter d'expliquer sommairement certains concepts propre à Ruby et donner quelques informations sur le RGSS(3).

Smiley Un langage orienté objet


Derrière cette appellation compliqué: "Orienté Objet", se cache un concept relativement facile à décrire. En effet, l'orienté objet consiste à dire que tout est descriptible. Donc que tous les éléments que je vais être amener à utiliser sont basé sur un "modèle" et le jeu du programmeur est de construire ces modèles et de les remplir. Le moule, le modèle, que l'on utilise pour décrire des éléments est appelé une classe. Dans la programmation orienté objet (plus spécifiquement orienté classe, mais ne nous arrêtons pas sur ce détail), on est amené à utiliser des classes déjà existantes et à créer nos propre classe, pour décrire des éléments.
Dans le jeu de la création de classe, il sera possible de créer des liens entre des classes, on appelle ces liens l'héritage, donc on va écrire une classe qui part avec toutes les caractéristiques d'une autre. C'est assez cool parce que ça évite de devoir réécrire inutilement du code.
Je suis assez évasif sur ce concept, mais pas de panique. Si vous n'avez pas (tout) compris, je détaillerais ça quand nous serons amené à coder nos propre classes et vous verrez que dans la pratique, c'est relativement simple, j'ai juste pris la décision de survoler théoriquement "l'idée" de l'orienté objet pour le raffiner par après.

Smiley le RGSS, c'est pleins de classes


Nous avions dit qu'en Ruby nous manipulerions des classes, et bien le RGSS étant représenté principalement en Ruby, il y a énormément de classes. Pour vous en rendre compte, je vous invite à lancer l'éditeur de script (au moyen de la touche F11), en survolant les différentes sections, vous pourrez voir qu'il y a plein de classes.
Pour faire un système en RGSS, il faudra donc créer des nouvelles classes et manipulez celles déjà existantes. Il existe toute une série d'autres classes qui ne sont pas accessible via l'éditeur de script, ces classes sont accessible (en lecture seule) via l'aide, que l'on peut trouver dans l'onglet "Aide" > "Fichier d'aide", ou simplement en appuyant sur F1. Le scripteur avisé est amené à souvent l'a consulter mais dans notre tutoriel, nous n'en aurons à priori pas besoin.

Smiley Si vous n'avez rien compris


Pas de panique ! Nous y serons confrontés via des cas pratiques et ce sera surement beaucoup plus clair pour tout le monde ! Donc ne baissez pas les bras et tâchez de tout de même vous lancer dans la suite, la confrontation à la pratique vous permettra peut être de mieux comprendre pleins de choses !

icone La notion de Scène


Dans RPG Maker, chaque écran est une scène. Si je lance un jeu RPG Maker, que je lance une nouvelle partie, que je circule sur la map, que je me rende dans le menu, que je retourne sur la map, que je fasse un combat, qui m'amène sur une autre map dans le cas où je gagne, que j'aille dans un magasin, que je retourne sur la map et que je meurs (et donc que j'enclenche un Game Over), j'aurais lancé plusieurs scènes. Voici un petit schéma de mon parcours:



Vous l'aurez compris, tous nos "écrans" seront des scènes. En RGSS, une scène est représentée par une classe. Chaque scène correspond à une classe. Si vous ouvrez l'éditeur de script, dans la partie de gauche, vous pourrez voir l'intégralité des scènes du RGSS:



Si vous êtes intelligent, vous aurez vite compris que pour créer notre mini-jeu, nous allons créer une scène spéciale qui sera notre "arène". Si vous ne l'avez pas compris, c'est que je ne suis pas assez explicite (et pas que vous n'êtes pas intelligent) et dans ce cas je vais ajouter que nous avons vu qu'une scène représente chaque écran de notre jeu, donc que nous allons créer un nouvel écran sur laquelle se trouvera notre Shifumi.

icone A la création de notre première scène


Dans un premier temps, je vous invite à vous rendre dans l'éditeur de script et à créer un emplacement en dessous de "Materials", généralement on place ses scripts en dessous de cet emplacement pour qu'ils soient en dessous des scripts qui composent le RGSS et au dessus de l'emplacement "main", qui correspond à la boucle du jeu (donc tous les scripts, après "main" ne seraient jamais exécutés):



Nous avons maintenant un emplacement libre pour écrire nos scripts. Certains programmeurs fractionnent chacune de leur composantes dans des emplacements séparés, moi, quand il s'agit d'aussi petit script que celui que nous allons réaliser aujourd'hui ou que je crée un script destiné à être partagé, je me contente de tout mettre dans un seul emplacement.
Nous pouvons écrire le squelette de notre scène:

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Ici se trouvera le code notre scène
  3. end

La première ligne indique que nous créons une classe du nom de Scene_Shifumi et le < Scene_Base indique que notre classé héritera de Scene_Base.

SmileyAie, qu'est ce que l'héritage?


Rappellez-vous, nous avions dit que le RGSS était une collection de classes déjà codée. L'héritage permet de dire qu'une classe aura le même comportement qu'une autre classe et il ne suffira plus que d'écraser les comportements que l'ont veut modifier.
Dans l'exemple présent, notre classe (Scene_Shifumi) aura exactement le même comportement qu'une Scene_Base, soit une scène ultra générique qui comprend toutes les routines de base d'une scène.

les lignes précédés de # sont des commentaires, ce qui veut dire qu'elles ne seront pas évaluées lors de l'exécution du jeu. Ce genre de ligne est très pratique pour structurer un script et aider le scripteur à s'y retrouver. On s'en sert aussi parfois pour afficher des indications sur le fonctionnement du script. Ces indications sont destinées à l'utilisateur.

Le end sert, quant à lui, à dire que la définition de la classe se termine. Donc tout notre travail de caractérisation de la table se trouvera entre class Scene_QuelqueChose et le end.
A notre que c'est le end qui caractérise la fin d'un bloc, donc que parfois, il y aura plusieurs end en fermeture. Mais nous verrons ça plus en détail par après.

Smiley Testons notre scène !


Tout ça c'est bien joli mais comment puis-je tester ma scène Smiley

Nous allons voir un petit appel de script en Event, je vous invite à créer un événement sur la map de départ de votre projet sur lequel vous allez faire un appel de script avec ceci dedans :

Code (Ruby):
  1. SceneManager.call(Scene_Title)


En le testant, si vous déclenchez cet événement, vous serez renvoyé à l'écran Titre. Je vous invite maintenant à déduire l'appel de Script pour aller sur notre Scene_Shifumi...

Solution

Code (Ruby):
  1. SceneManager.call(Scene_Shifumi)

Si vous ne l'aviez pas trouvé, vous êtes un peu nul :(


En le testant, vous devriez voir une scène toute noire... c'est normal, nous n'avons pas encore fait quoi que ce soit sur cette scène. C'est d'ailleurs ce à quoi nous allons nous atteler dans la rubrique suivante !

icone La structure d'une scène


Avant de nous soucier de "ce que l'on va ajouter" à notre scène, il est important de comprendre la structure de celle-ci. Voici, de manière fort schématique, le déroulement d'une scène :



Cette représentation est un peu naïve et "limité" car il est possible de faire des "pre_terminate", mais pour l'instant, nous allons nous focaliser sur le strict minimum pour ne pas nous encombrer de concepts ennuyeux.
Donc concrètement, quand on appelle une scène, c'est la méthode start (une méthode c'est une action référente à une classe) qui est appelée, donc on va effectuer les premières tâches... afficher les images, les menus etc.
Une fois que cette action est terminée, on va boucler dans la méthode update, jusqu’à ce qu'une interruption soit envoyée, si cette interruption engendre la fin de la scène, par exemple, un changement de scène, on va dans la méthode terminate qui elle va supprimer tout ce qu'il faut avant de changer de scène.

Ce qui est chouette avec ce que nous avons vu de l'héritage, c'est que nous ne sommes pas obligé de réécrire toutes les méthodes, car certaines méthodes de Scene_Base ont généralisé leur comportement. Par exemple, l'update rafraichit toute seule chacune des "Window" (nous y arrivons!) et terminate supprime toute seule les "Window". Il ne faut donc pas les réécrire (sauf si on doit modifier/supprimer d'autre chose).


Smiley Point sur les variables


La notion de variable est assez simple. Sans nous arrêter sur ce qu'est réellement une variable (sa représentation en mémoire etc.), nous allons voir qu'une variable, c'est simplement une étiquette sur une valeur, ça nous permet de stocker des valeurs :

Code (Ruby):
  1. je_suis_une_variable = 10
  2. je_suis_une_variable = je_suis_une_variable + 1


Dans cet exemple, je_suis_une_variable vaudra 11. On peut stocker toute sorte de chose dans une variable, par exemple une image, une Window.
Mais une variable possède une portée limité.
Nous avions parlé des méthodes de Scene. Si je crée une variable dans la méthode start, elle n'existera pas dans la méthode update, parce que sa durée de vie est limité à start.
Pour cela, il existe plusieurs "genres" de variables, celui qui nous intéresse est l'attribut. Nous avons vu qu'une classe permet de décrire des chose à l'infini. Pour ça on utilise des caractéristiques. Les attributs sont un genre de variable qui sert à caractériser une classe. Il suffit de rajouter un "@" devant son nom et on pourra accéder à cette variable partout dans la classe.
Concrètement, quand je n'aurai besoin que d'une valeur temporaire, j'utiliserai une variable normale, et quand j'aurai besoin de garder cette valeur tout au long de ma classe, j'utiliserai un attribut, donc une variable dont le nom commence par @.

Smiley La méthode start


Nous allons donc préparer notre scène à recevoir des éléments. Pour ça, voici comment j'ai écris ma Scene_Shifumi:

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. super
  5. # Initialisation de la scène
  6. end
  7. end


SmileyA quoi sert le "super"?


Rappelez-vous que l'on a dit qu'on utilisait l'héritage pour que notre Scene_Shifumi prenne le comportement de Scene_Base.
Quand je fais une simple scène :

Code (Ruby):
  1. class Scene_Truc < Scene_Base
  2. end


Par défaut, Scene_Truc possède toutes les méthodes de Scene_Base, grâce a l'héritage qui est représenté par < Scene_Base.
Si je crée une méthode start dans ma class Scene_Truc :

Code (Ruby):
  1. class Scene_Truc < Scene_Base
  2. def start
  3. end
  4. end


La méthode de Scene_Base sera écrasée dans Scene_Truc. le mot clé (qui est une méthode aussi) super permet de dire à la méthode qu'elle appellera aussi la méthode de la classe parente (Scene_Base dans cet exemple).
Ce qui nous permet de garder le comportement générique défini dans Scene_Base tout en ajoutant des choses. Dans l'exemple donné, on voit que la méthode start de Scene_Base est définie comme ça :

Code (Ruby):
  1. def start
  2. create_main_viewport
  3. end


Donc concrètement, faire ça :
Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. super
  5. # Initialisation de la scène
  6. end
  7. end


Est identique que de faire :

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. create_main_viewport
  5. # Initialisation de la scène
  6. end
  7. end


(la méthode create_main_viewport existe dans Scene_Shifumi de part l'héritage... une fois de plus).
Cependant, l'utilisation de super est plus astucieuse parce que bien que dans ce cas, le code de Scene_Base start est très court, il arrive que le code de la méthode parente soit beaucoup plus long (et pourtant requis pour le bon déroulement d'une scène, par exemple).

Smiley Notre premier élément


Dans cette section, voici ce que nous allons essayer d'obtenir (enfin, non, nous n'allons pas essayer... nous allons réussir):



Nous pourrions directement créer cette composante dans la méthode start, cependant j'ai pris l'habitude de fractionner mon code en sous procédure. Nous allons donc, dans notre classe, créer une méthode qui se chargera de créer notre fenêtre de titre:

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. super
  5. create_title
  6. end
  7. def create_title
  8. # Ici on créera le titre
  9. end
  10. end


A ce stade-ci, il va falloir utiliser une nouvelle composante du RGSS pour afficher une fenêtre en haut de scène. Cette composante est Window_Help.
Pour comprendre son fonctionnement, je vous invite à vous rendre dans l'éditeur de script. La méthode initialize est celle qui sera appelée la première fois, quand on construira l'objet. On appel ça un constructeur.
En effet, lorsque je fais "UneClasse.new", j'appelle la méthode initialize de la classe UneClasse et je construit une instance de cette classe. Dans notre exemple, nous aurons besoin d'une fenêtre d'une case de hauteur (en effet, nous n'avons besoin de n'écrire qu'une seule ligne), il nous suffit donc de faire :

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. super
  5. create_title
  6. end
  7. def create_title
  8. @title = Window_Help.new(1)
  9. end
  10. end


L'utilisation d'un attribut (rappelez-vous... le @) est obligatoire car notre méthode terminate devra supprimer la fenêtre quand on quitte la scène. Donc même si on a l'impression de n'utiliser notre fenêtre de titre qu'une seule fois, ce n'est pas vrai.
Si on test la scène, on verra que l'on est presque arrivé à ce que l'on voulait, malheureusement, il nous manque du texte. En effet, notre fenêtre est vide. Nous allons donc nous servir d'une méthode de Window_Help qui s'appelle set_text, si vous allez voir le code de Window_Help vous devriez la voir assez vite. Cette méthode nous permet d'écrire du texte dans notre fenêtre :

Code (Ruby):
  1. class Scene_Shifumi < Scene_Base
  2. # Lancement de la scène
  3. def start
  4. super
  5. create_title
  6. end
  7. def create_title
  8. @title = Window_Help.new(1)
  9. @title.set_text("SHI FU MI !")
  10. end
  11. end


Cette fois vous pouvez tester la scène et... magie ! Elle ressemble à ce que nous désirions avoir comme rendu !

Nous avons donc créé notre premier élément graphique et en plus, nous avons étés modernes car nous avons utilisé une méthode ! Sachez que dans les classes vous pouvez créer autant de méthode que vous voulez. Personnellement, je me sers des méthodes pour rendre mon code plus lisible et éviter les trop grosses portions de code !

icone Le menu de sélection


Nous avons un titre... c'est un début. Maintenant, il serait intéressant d'avoir un véritable élément d’interactivité. Soit un menu de sélection des armes (Pierre, feuille ciseaux).
Cette partie est la partie principal de cet article. En effet, nous allons apprendre à créer des interactions entre l'utilisateur et le jeu au moyen d'une composante du RGSS !

Smiley Une classe enfante à Window_Command


Le RGSS met à notre disposition une classe, nommée Window_Command pour représenter des listes de choix. Comme pour notre scène, nous allons créer, en dessous de notre classe Scene_Shifumi, une classe pour la sélection de nos armes ! Je propose que l'on l'appelle Window_Shifumi. Une fois de plus vous pouvez l'ajouter dans un autre emplacement script, cependant, moi j'ai choisi de l'écrire en dessous de ma classe précédente, dans le même emplacement:

Code (Ruby):
  1. class Window_Shifumi < Window_Command
  2. end


On regardant le code de Window_Command, on peut voir que son constructeur prend deux arguments, soit sa position (spécifiée en x et en y). Je vous propose que l'on ajoute directement notre fenêtre à notre scène pour voir ce que ça donne. Pour cela, nous allons créer une nouvelle méthode create_commands:

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. end
  9. # Création de la fenêtre de titre
  10. def create_title
  11. @title = Window_Help.new(1)
  12. @title.set_text("SHI FU MI !")
  13. end
  14. # Création de la fenêtre de sélection
  15. def create_commands
  16. @window_selection = Window_Shifumi.new(0, 48)
  17. end
  18. end
  19.  
  20. # Fenêtre de sélection d'arme
  21. class Window_Shifumi < Window_Command
  22. end


En testant ça... vous ne voyez rien de plus qu'une micro fenêtre (positionnée en 0, 48 sur votre écran) doté d'une petite flèche ! C'est normal, c'est parce qu'il va falloir dire à notre fenêtre ce qu'elle prend comme "commandes sélectionnables".

Smiley Ajouter des commandes


Ajouter une liste de commande à notre fenêtre de sélection est très simple, il suffit d'ajouter une méthode make_command_list dans laquelle on utilise la méthode add_command qui prend deux arguments, le premier étant le texte affiché dans la liste et le second étant un "symbole" donc un texte avec deux points devant (par exemple :truc est un symbole) qui servira a identifier la valeur sélectionné. Donc le choix de ce symbole sera traité quand on ajoutera des contrôles à notre fenêtre de sélection.
Ici, nous avons besoin de trois commandes, Pierre, Feuille, Ciseaux, voici donc comment se présente la classe Window_Shifumi (située en dessous de Scene_Shifumi)

Code (Ruby):
  1. # Fenêtre de sélection d'arme
  2. class Window_Shifumi < Window_Command
  3. # Création de la liste de selection
  4. def make_command_list
  5. add_command("Pierre", :pierre)
  6. add_command("Feuille", :feuille)
  7. add_command("Ciseaux", :ciseaux)
  8. end
  9. end


Afficher le code complet

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. end
  9. # Création de la fenêtre de titre
  10. def create_title
  11. @title = Window_Help.new(1)
  12. @title.set_text("SHI FU MI !")
  13. end
  14. # Création de la fenêtre de sélection
  15. def create_commands
  16. @window_selection = Window_Shifumi.new(0, 48)
  17. end
  18. end
  19.  
  20. # Fenêtre de sélection d'arme
  21. class Window_Shifumi < Window_Command
  22. # Création de la liste de selection
  23. def make_command_list
  24. add_command("Pierre", :pierre)
  25. add_command("Feuille", :feuille)
  26. add_command("Ciseaux", :ciseaux)
  27. end
  28. end



Et nous pouvons tester notre scène ... et oui... ça a tout de même plus de classe que ce que nous avions fait précédemment ! Voici un petit aperçu (pour ceux qui ne testent pas le tutoriel directement) :



En plus, vous pouvez utiliser les flêches haut et bas et le curseur change... c'est vraiment super cool ... nous allons pouvoir, maintenant, effectuer des actions en fonction de notre choix.

icone Traiter la sélection d'une fenêtre de commande


C'est génial parce qu'en très peu de ligne, nous avons déjà pas mal de chose, et nous avons survolé une grande quantité de concepts (sans s’emmêler dans de la théorie !), le soucis c'est comment créer des actions en fonction de notre choix? Parce qu'il faut reconnaître que sans ça, notre petite scène n'a pas beaucoup d'intérêt Smiley

Smiley Créer des cas de figures


Ce qu'il va falloir faire, c'est de proposer des "cas de figures", typiquement, écrire les méthode à appeler si une sélection est effectuée.
Dans un premier temps, notre application se contentera d'afficher dans la console (pour rappel, dans le menu Jeu, il est possible de cocher "Afficher la console") la rubrique choisie. Pour cela, rien de plus facile, il suffit de créer trois méthodes: pierre, feuille et ciseaux dans notre scène :

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. end
  9. # Création de la fenêtre de titre
  10. def create_title
  11. @title = Window_Help.new(1)
  12. @title.set_text("SHI FU MI !")
  13. end
  14. # Création de la fenêtre de sélection
  15. def create_commands
  16. @window_selection = Window_Shifumi.new(0, 48)
  17. end
  18. # Cas de sélection de Pierre
  19. def pierre
  20. p "Vous avez choisi la pierre"
  21. end
  22. # Cas de sélection de Feuille
  23. def feuille
  24. p "Vous avez choisi la feuille"
  25. end
  26. # Cas de sélection de Ciseaux
  27. def ciseaux
  28. p "Vous avez choisi les ciseaux"
  29. end
  30. end


La méthode p permet d'afficher un message dans la console, donc dans un premier temps, nous n'allons nous contenter que d'afficher en console le choix effectué.
Maintenant que nous avons nos méthodes a effectuer en cas de sélection, nous allons devoir dire à notre fenêtre de sélection qu'elle doit appeler ces méthodes en fonction de la sélection effectuée (et validée par une pression de la touche C dans RPG Maker, généralement Espace ou Enter par défaut).
Pour cela nous allons devoir nous servir de la méthode set_handler de Window_Base (donc que notre Window_Shifumi possède aussi grâce à l'héritage), cette fonction prend deux arguments, le premier étant un symbole, le second étant une méthode à appeler. Concrètement, ça revient à dire "Si le symbole courant à la pression de la touche C correspond à ça, on lance cette méthode". La liste de symboles ayant été définies avec nos add_command, donc nous pouvons faire :

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. end
  9. # Création de la fenêtre de titre
  10. def create_title
  11. @title = Window_Help.new(1)
  12. @title.set_text("SHI FU MI !")
  13. end
  14. # Création de la fenêtre de sélection
  15. def create_commands
  16. @window_selection = Window_Shifumi.new(0, 48)
  17. @window_selection.set_handler(:pierre, method(:pierre))
  18. @window_selection.set_handler(:feuille, method(:feuille))
  19. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  20. end
  21. # Cas de sélection de Pierre
  22. def pierre
  23. p "Vous avez choisi la pierre"
  24. end
  25. # Cas de sélection de Feuille
  26. def feuille
  27. p "Vous avez choisi la feuille"
  28. end
  29. # Cas de sélection de Ciseaux
  30. def ciseaux
  31. p "Vous avez choisi les ciseaux"
  32. end
  33. end


J'ai utilisé method(:nom_methode) pour pouvoir passer la méthode en argument à set_handler. En effet cette méthode prend en argument quelque chose qui doit être exécuté. Si vous testez la scène, vous allez pouvoir remarquer que le message en fonction de la sélection s'affiche bien dans la console.

Maintenant nous avons assez de matière pour créer notre application, en effet, nous savons afficher des fenêtre, créer des fenêtre de sélection, relier nos sélections à des actions, nous allons pouvoir coder le raisonnement logique de notre jeu !

icone Penser le déroulement d'un système


Le plus dur et le moins amusant est derrière nous, nous allons maintenant pouvoir focaliser notre attention sur quelque chose de vraiment amusant.
Jusqu’à présent, nous avons résolu séquentiellement chacun de nos besoin. En effet, nous avions besoin d'une scène, nous avons créé une scène. Nous voulions afficher un titre, nous l'avons fait, nous avions besoin d'un outil de sélection, nous l'avions fait. Il est temps d'apprendre quelque chose d'un peu plus abstrait.
En tant qu'analyste programmeur, on est souvent amené à devoir penser des applications/systèmes complexe dont le déroulement n'est pas toujours linéaire.
En tant que créateur de systèmes pour RPG Maker, c'est le même problème. Quand on crée un script, il arrive que le déroulement ne soit pas explicite. Par exemple, bien que notre système soit assez simple, au moment de la sélection "l'arme", notre application peut prendre trois directions différentes.
Dans cette rubrique nous allons tâcher de représenter le processus de notre système.

Smiley Déroulement du système


Je vous propose ici un schéma du déroulement de notre SHIFUMI... attention, il fait très peur parce qu'il y a pleins de flèches dans tous les sens. Rassurez vous, je vais vous expliquer chaque étape et vous verrez que c'est en réalité très simple !



SASUKE M'A TUER*
non, ce n'est pas une faute, c'est une blague

La première partie a déjà été presque entièrement faite, il ne reste plus qu'a générer le choix de l'ordinateur et nous le ferons un peu plus tard, le reste il s'agit simplement de vérifier qui a gagné. Dans le cas ou le choix de l'ordinateur équivaut à celui du joueur, c'est match nul et on renvoi vers le début de la scène après avoir affiché un message de match nul. Sinon on affiche si le joueur a gagné ou a perdu et quoi qu'il arrive, on renvoi vers la map. Soit l'endroit d'où l'on vient.

Ce n'est pas un peu... complexe pour si peu ?


Personnellement, je trouve que ce genre de schéma permet de se représenter tous les états d'une application, et il m'arrive souvent d'en croquer quelques un sur une feuille de papier pour représenter le processus d'une application.
Mais si vous êtes super à l'aise avec l'abstraction et que vous avez une capacité de vous projeter une application sans dessin, vous n'êtes évidemment pas obligé de faire ce genre d’organigrammes.

icone Choix et conditions


En réalisant notre organigramme, on peut se rendre compte qu'il nous manque des outils pour continuer. Le premier étant la sélection aléatoire d'une des armes (pierre, papier ou ciseaux) de la part de l'ordinateur !

Smiley Liste et sélection aléatoire


En programmation, il arrive souvent que l'on doive stocker plusieurs valeurs de manière ordonnées. Pour cela, on utilise une liste, ou un tableau. (La nuance entre ces deux concepts existe, cependant, nous ne nous étendrons pas sur le sujet).
Pour créer une liste il suffit de dire qu'une variable est égal à [valeur1, valeur2, etc.]. Nous allons pouvoir utiliser une liste pour stocker les différents choix possible. Personnellement, j'utilise des symboles pour représenter mes armes donc :

Code (Ruby):
  1. liste_arme = [:pierre, :feuille, :ciseaux]


SmileyPourquoi utiliser une liste alors que l'on a besoin que d'une seule valeur !


J'ai décidé d'utiliser une liste car comme pour les fenêtres, les scènes, et à peu près tout en Ruby, il est possible de leur appliquer des méthodes. La liste des méthodes des tableaux est ici : documentation des tableaux de Ruby et nous allons pouvoir nous servir d'une méthode particulière pour récupérer une cellule aléatoire du tableau. Cette méthode s'appelle sample.
Donc en faisant :

Code (Ruby):
  1. liste_arme = [:pierre, :feuille, :ciseaux]
  2. valeur_aleatoire = liste_arme.sample
ou encore
Code (Ruby):
  1. valeur_aleatoire = [:pierre, :feuille, :ciseaux].sample


Je fournirai à la variable valeur_aleatoire une cellule sélectionnée au hasard dans le tableau [:pierre, :feuille, :ciseaux].
Nous pouvons donc, avec ce que nous venons d'apprendre, clôturer la partie 1 du schéma que nous avions établit précédemment :



Et pour ce faire, je vous propose de créer une nouvelle méthode qui s'occupera gérer la génération de notre sélection de l'ordinateur, une fois de plus on fractionne le tout en méthode pour rendre ça plus lisible ! Le résultat de notre sélection sera stockée dans un attribut car nous en aurons besoin dans d'autres méthodes !

Et cette fois ! Je vous laisse le faire et je vous invite à ne cliquer sur Afficher la solution qu'une fois que vous êtes sur de vous !


Afficher la solution

Voici à quoi doit ressembler Scene_Shifumi à notre étape !

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. generate_choice
  9. end
  10. # Création de la fenêtre de titre
  11. def create_title
  12. @title = Window_Help.new(1)
  13. @title.set_text("SHI FU MI !")
  14. end
  15. # Création de la fenêtre de sélection
  16. def create_commands
  17. @window_selection = Window_Shifumi.new(0, 48)
  18. @window_selection.set_handler(:pierre, method(:pierre))
  19. @window_selection.set_handler(:feuille, method(:feuille))
  20. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  21. end
  22. # Génère le choix de l'ordinateur
  23. def generate_choice
  24. list_weapons = [:pierre, :feuille, :ciseaux]
  25. @computer_choice = list_weapons.sample
  26. end
  27. # Cas de sélection de Pierre
  28. def pierre
  29. p "Vous avez choisi la pierre"
  30. end
  31. # Cas de sélection de Feuille
  32. def feuille
  33. p "Vous avez choisi la feuille"
  34. end
  35. # Cas de sélection de Ciseaux
  36. def ciseaux
  37. p "Vous avez choisi les ciseaux"
  38. end
  39. end



Smiley Les structures conditionnelles


Peut être y avez vous déjà été confrontés quand vous faisiez de l'Event-Making (lol). Les conditions nous permettent de faire varier un programme. En se référant une fois de plus à notre organigramme, on peut facilement voir quand il faudra utiliser une condition. Pas dans le cas de la sélection d'une arme par le joueur car c'est l'appelle des méthodes qui va se charger de gérer la structures conditionnelles, mais par contre, pour définir s'il s'agit d'une victoire, d'un match nul ou d'une défaite, il nous faudra utiliser les conditions.
Voyons voir comment fonctionne une condition !
Typiquement, une condition se structure de cette manière :



SmileyEn programmation... il n y a pas de nuances... soit c'est vrai, soit c'est faux...


Oui... en programmation pas de nuance. Ruby est capable de répondre à des questions simples qui n'ont que deux réponses possibles, Vraie ou faux (représenté par true et false).
On peut s'interroger sur l'égalité entre deux valeurs (a == b), les comparer (a > b, a < b, a >= b, a <= b), et pleins d'autre choses !
Nous ne nous intéresserons uniquement à l'égalité car nous n'aurons besoin que d'elle. Cependant, la personne soucieuse d'élargir ses connaissances en Ruby devrait impérativement passer par cette case... ce qu'on appelle les booléens.
Pour en revenir à notre schéma précédent, voici comment l'on code une condition :

Code (Ruby):
  1. if ma question
  2. # Succession d'action si la réponse
  3. # est vraie
  4. else
  5. # Succession d'action si la réponse
  6. # est fausse
  7. end
  8.  
  9. # suite du programme


Un exemple super concret !

Code (Ruby):
  1. if @computer_choice == :pierre
  2. p "L'ordinateur à choisi Pierre... lol"
  3. else
  4. p "L'ordinateur n'a pas choisi Pierre... lal"
  5. end


Si vous êtes un peu nul en mémoire, surtout quand c'est de l'Anglais... retenez que if veut dire si, else veut dire sinon! Smileyc'était le bon conseil du Docteur S4suk3 !


Il y a plusieurs subtilités à savoir quand on manipule des conditions, par exemple, le else n'est pas obligatoire. On pourrait imaginer ce schéma :



Et en code ça nous donnerait, pour reprendre l'exemple avec le test de @computer_choice, par exemple, ceci :

Code (Ruby):
  1. if @computer_choice == :pierre
  2. p "L'ordinateur a choisi Pierre"
  3. end
  4. p "Suite du programme"


On peut aussi imbriquer des conditions, par exemple placer dans la succession d'action du if une autre condition, de même que l'on pourrait faire une autre (ou plusieurs autres) condition(s) dans le else.
Dans notre objectif, créer un Shifumi, nous serons amené à manipuler plusieurs cas. Voici un exemple tout simple pour savoir quel arme a été attribuée à l'ordinateur :

Code (Ruby):
  1. if @computer_choice == :pierre
  2. p "L'ordinateur a choisi Pierre"
  3. else
  4. if @computer_choice == :feuille
  5. p "L'ordinateur a choisi Feuille"
  6. else
  7. p "L'ordinateur a choisi Ciseaux"
  8. end
  9. end


Il faut reconnaître que cette forme est un petit peu trop lourde, alors nous allons voir qu'il est possible de poser plusieurs questions et ce au moyen de la primitive elsif, voici un code qui fait exactement la même chose que celui proposé précédemment:

Code (Ruby):
  1. if @computer_choice == :pierre
  2. p "L'ordinateur a choisi Pierre"
  3. elsif @computer_choice == :feuille
  4. p "L'ordinateur a choisi Feuille"
  5. else
  6. p "L'ordinateur a choisi Ciseaux"
  7. end


Concrètement, que se passe-t-il ici? On évalue d'abord la première condition, "est-ce que @computer_choice vaut :pierre ?" Si oui, on affiche le message qui indique que l'ordinateur a choisi :pierre et on sort de la condition, sinon on évalue la seconde condition, "est-ce que @computer_choice vaut :feuille ?" Si oui, on affiche le message qui indique que l'ordinateur a choisi :feuille et on sort de la condition, sinon, comme nous n'avons que trois choix possible, c'est que l'ordinateur a choisi Ciseaux et on l'affiche et on sort de la condition. Cet exemple est donc identique au précédent (mais est tout de même plus court Smiley)

Smiley Implémentation de la logique dans notre système


Maintenant nous avons assez de matière pour coder les décisions de victoires, défaites ou match nul ! Pour rappel des règles du Shifumi :

• La pierre écrase les ciseaux (donc la pierre bat les ciseaux)
• La feuille emballe la pierre (lol) (donc la feuille "bat" la pierre)
• Les ciseaux découpent la feuille (donc les ciseaux battent la feuille)
• Si les deux choix (joueur, ordinateur) sont identique, alors c'est match nul

Nous avions préparé trois méthodes (pierre, feuille, ciseaux) qui seront appelées en fonction du choix du joueur. C'est dans ces trois méthodes que nous allons coder nos conditions !
Il aurait été possible de ne créer qu'une seule méthode qui vérifie la victoire en fonction de deux arguments, mais nous partons du principe que nous débutons avec Ruby et le RGSS, donc autant faire trois petites méthodes facilement compréhensible.
Dans un premier temps nous nous contenterons d'afficher un petit message funky pour dire qui a gagner et dans le cas d'un match nul, nous renverrons au début de la scène (pour cela c'est très simple, il suffit d'utiliser le même code que celui que nous utilisons pour tester notre scène, il va re-appeler la scène) et dans un cas de victoire ou de défaite, il suffit de renvoyer vers Scene_Map (au lieu de Scene_Shifumi).
Je vous laisse coder ces trois fonctions ! (Et je vous propose la solution en caché ^^), attention, ce n'est pas parce que nos conditions ne sont pas dans le même ordre que votre proposition est obligatoirement mauvaise. Il n'y a pas d'ordre précis et optimal. Personnellement, je commence par tester si les deux choix sont identiques, ensuite si il y a défaite, et sinon, c'est qu'il y a victoire :

Afficher la solution

Voici le code des trois méthodes de Scene_Shifumi

Code (Ruby):
  1. # Cas de sélection de Pierre
  2. def pierre
  3. if @computer_choice == :pierre
  4. p "Vous avez tous les deux choisis Pierre, Match Nul"
  5. SceneManager.call(Scene_Shifumi)
  6. elsif @computer_choice == :feuille
  7. p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
  8. SceneManager.call(Scene_Map)
  9. else
  10. p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
  11. SceneManager.call(Scene_Map)
  12. end
  13. end
  14. # Cas de sélection de Feuille
  15. def feuille
  16. if @computer_choice == :feuille
  17. p "Vous avez tous les deux choisis Feuille, Match Nul"
  18. SceneManager.call(Scene_Shifumi)
  19. elsif @computer_choice == :ciseaux
  20. p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
  21. SceneManager.call(Scene_Map)
  22. else
  23. p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
  24. SceneManager.call(Scene_Map)
  25. end
  26. end
  27. # Cas de sélection de Ciseaux
  28. def ciseaux
  29. if @computer_choice == :ciseaux
  30. p "Vous avez tous les deux choisis Ciseaux, Match Nul"
  31. SceneManager.call(Scene_Shifumi)
  32. elsif @computer_choice == :Pierre
  33. p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
  34. SceneManager.call(Scene_Map)
  35. else
  36. p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
  37. SceneManager.call(Scene_Map)
  38. end
  39. end




Et pour être sur que tout fonctionne, voici le code complet (les deux classes) de notre mini jeux de shifumi :

Afficher le code complet

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. generate_choice
  9. end
  10. # Création de la fenêtre de titre
  11. def create_title
  12. @title = Window_Help.new(1)
  13. @title.set_text("SHI FU MI !")
  14. end
  15. # Création de la fenêtre de sélection
  16. def create_commands
  17. @window_selection = Window_Shifumi.new(0, 48)
  18. @window_selection.set_handler(:pierre, method(:pierre))
  19. @window_selection.set_handler(:feuille, method(:feuille))
  20. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  21. end
  22. # Génère le choix de l'ordinateur
  23. def generate_choice
  24. list_weapons = [:pierre, :feuille, :ciseaux]
  25. @computer_choice = list_weapons.sample
  26. end
  27. # Cas de sélection de Pierre
  28. def pierre
  29. if @computer_choice == :pierre
  30. p "Vous avez tous les deux choisis Pierre, Match Nul"
  31. SceneManager.call(Scene_Shifumi)
  32. elsif @computer_choice == :feuille
  33. p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
  34. SceneManager.call(Scene_Map)
  35. else
  36. p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
  37. SceneManager.call(Scene_Map)
  38. end
  39. end
  40. # Cas de sélection de Feuille
  41. def feuille
  42. if @computer_choice == :feuille
  43. p "Vous avez tous les deux choisis Feuille, Match Nul"
  44. SceneManager.call(Scene_Shifumi)
  45. elsif @computer_choice == :ciseaux
  46. p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
  47. SceneManager.call(Scene_Map)
  48. else
  49. p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
  50. SceneManager.call(Scene_Map)
  51. end
  52. end
  53. # Cas de sélection de Ciseaux
  54. def ciseaux
  55. if @computer_choice == :ciseaux
  56. p "Vous avez tous les deux choisis Ciseaux, Match Nul"
  57. SceneManager.call(Scene_Shifumi)
  58. elsif @computer_choice == :Pierre
  59. p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
  60. SceneManager.call(Scene_Map)
  61. else
  62. p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
  63. SceneManager.call(Scene_Map)
  64. end
  65. end
  66. end
  67.  
  68. # Fenêtre de sélection d'arme
  69. class Window_Shifumi < Window_Command
  70. # Création de la liste de selection
  71. def make_command_list
  72. add_command("Pierre", :pierre)
  73. add_command("Feuille", :feuille)
  74. add_command("Ciseaux", :ciseaux)
  75. end
  76. end



Je vous invite maintenant à tester la scène (avec la console affichée pour voir les résultats)... et ... MAGIE ! Notre système marche ! Nous avons effectué 90% de notre application. C'est super !

icone Affichage des messages


Dans la section précédente, nous avons établit toute la logique de notre application, ce qui fait que actuellement, elle fonctionne ! Maintenant, il faudrait que notre système puisse afficher des message de victoire ou de défaite.
Pour ça nous allons créer une fenêtre qui ne s'affichera que quand il le faut.

Smiley Une fenêtre simple


Pour ça, nous allons nous servir de la représentation la plus simple de fenêtre, la Window_Base. L'objectif de ce genre de fenêtre est simplement d'afficher des informations. En vous référant à l'éditeur de script on peut voir que son constructeur prend 4 arguments, sa position en x, sa position en y, sa largeur et sa hauteur.
Je vous invite à créer une méthode create_window_message qui aura pour rôle de créer dans un attribut nommé message, une fenêtre simple. Je lui ai donné comme dimension 280 sur 80. Pour calculer son centre, car une fenêtre est par défaut orientée en fonction de son coin haut gauche, j'ai utilisé ces formules :

• Calcul de x : (largeur_fenetre_vx/2) - largeur/2 ce qui donne (544/2) - (280/2) = 132
• Calcul de y : (hauteur_fenetre_vx/2) - hauteur/2 ce qui donne (416/2) - (80/2) = 168

C'est une petite ruse pour positionner correctement la fenêtre. J'ai donc ajouté un appel de create_window_message et j'ai écris create_window_message de cette manière :

Code (Ruby):
  1. # Crée la fenêtre de message
  2. def create_window_message
  3. @message = Window_Base.new(132, 168, 280, 80)
  4. end


Vous pouvez tester la scène, c'est cool, on a bien une fenêtre bien placée. Maintenant l'idéal serait que cette fenêtre ne s'affiche que quand on en a besoin. Pour ce faire, nous allons modifier notre méthode pour qu'elle crée la fenêtre mais qu'elle ne soit pas visible.

Code (Ruby):
  1. # Crée la fenêtre de message
  2. def create_window_message
  3. @message = Window_Base.new(132, 168, 280, 80)
  4. @message.hide
  5. end


Maintenant nous avons notre fenêtre qui est bien crée mais elle reste masquée tant qu'on ne lui demande pas de s'afficher !

Rappel du code complet

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. generate_choice
  9. create_window_message
  10. end
  11. # Création de la fenêtre de titre
  12. def create_title
  13. @title = Window_Help.new(1)
  14. @title.set_text("SHI FU MI !")
  15. end
  16. # Création de la fenêtre de sélection
  17. def create_commands
  18. @window_selection = Window_Shifumi.new(0, 48)
  19. @window_selection.set_handler(:pierre, method(:pierre))
  20. @window_selection.set_handler(:feuille, method(:feuille))
  21. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  22. end
  23. # Génère le choix de l'ordinateur
  24. def generate_choice
  25. list_weapons = [:pierre, :feuille, :ciseaux]
  26. @computer_choice = list_weapons.sample
  27. end
  28. # Crée la fenêtre de message
  29. def create_window_message
  30. @message = Window_Base.new(132, 168, 280, 80)
  31. @message.hide
  32. end
  33. # Cas de sélection de Pierre
  34. def pierre
  35. if @computer_choice == :pierre
  36. p "Vous avez tous les deux choisis Pierre, Match Nul"
  37. SceneManager.call(Scene_Shifumi)
  38. elsif @computer_choice == :feuille
  39. p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
  40. SceneManager.call(Scene_Map)
  41. else
  42. p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
  43. SceneManager.call(Scene_Map)
  44. end
  45. end
  46. # Cas de sélection de Feuille
  47. def feuille
  48. if @computer_choice == :feuille
  49. p "Vous avez tous les deux choisis Feuille, Match Nul"
  50. SceneManager.call(Scene_Shifumi)
  51. elsif @computer_choice == :ciseaux
  52. p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
  53. SceneManager.call(Scene_Map)
  54. else
  55. p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
  56. SceneManager.call(Scene_Map)
  57. end
  58. end
  59. # Cas de sélection de Ciseaux
  60. def ciseaux
  61. if @computer_choice == :ciseaux
  62. p "Vous avez tous les deux choisis Ciseaux, Match Nul"
  63. SceneManager.call(Scene_Shifumi)
  64. elsif @computer_choice == :Pierre
  65. p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
  66. SceneManager.call(Scene_Map)
  67. else
  68. p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
  69. SceneManager.call(Scene_Map)
  70. end
  71. end
  72. end
  73.  
  74. # Fenêtre de sélection d'arme
  75. class Window_Shifumi < Window_Command
  76. # Création de la liste de selection
  77. def make_command_list
  78. add_command("Pierre", :pierre)
  79. add_command("Feuille", :feuille)
  80. add_command("Ciseaux", :ciseaux)
  81. end
  82. end



Smiley Ecrire du texte dans la fenêtre


Une fenêtre vide c'est un peu tout pourri, donc nous allons essayer d'y écrire du texte Smiley. Pour ça, rien de plus facile ! Une fois de plus, le RGSS met à notre disposition une méthode qui va nous permettre d'écrire du texte dans notre fenêtre ... (heureusement me direz-vous Smiley).
Cette méthode s'appelle draw_text et elle va nous permettre d'écrire un texte dans la fenêtre. Voyons sa nomenclature:

Code (Ruby):
  1. draw_text(x, y, width, height, text, [align=0])


Concrètement, on va préparer un rectangle (invisible, je vous rassure) dans notre fenêtre dans laquelle on écrira le texte. Ce rectangle est défini par un x et un y (relatif à notre fenêtre) et une longueur (width)/hauteur(height).
C'est souvent une partie chiante parce qu'il faudra tester "au cas par cas" pour vérifier si nos textes sont bien placés :'(
Le dernier argument est mis entre crocher car il n'est pas obligatoire. Par défaut, il vaut 0. Align, comme vous vous en doutez indiquera l'alignement par rapport au rectangle que nous avions défini dans les autres arguments. 0 = alignement à gauche, 1 = alignement au centre, 2 = alignement à droite.

Voici un petit exemple d'écriture de texte via la méthode vue précédemment. (je vous invite à l'écrire dans la méthode create_window_message en supprimant la commande qui masque la fenêtre histoire de voir ce que l'on fait.
Ajoutons donc ceci :

Code (Ruby):
  1. @message.draw_text(0, 0, 280, 38, "Vous: Pierre, Ordi : Ciseaux")


Code comple de la méthode

Code (Ruby):
  1. def create_window_message
  2. @message = Window_Base.new(132, 168, 280, 80)
  3. #@message.hide
  4. @message.draw_text(0, 0, 280, 38, "Vous: Pierre, Ordi : Ciseaux")
  5. end


J'ai commenté le masquage de la fenêtre car nous ne faisons ici que des tests !


En testant ce script, vous devriez voir dans notre fenêtre centrée, un message, "Vous: Pierre, Ordi : Ciseaux". Je vous parlais de la création d'un rectangle, dans lequel sera placé le texte. Voici la représentation, en rouge, de ce rectangle, dans l'exemple donné plus haut :



Les plus fins observateurs remarqueront que le contenu de notre fenêtre possède des marges. En effet, et ces marges sont définies par la méthodes standard_padding de Window_Base et vaut par défaut 12.

Nous sommes maintenant capable d'afficher du texte et je vais vous proposer une petite fonction moderne (mon abus de l'utilisation du mot moderne est un troll envers un lecteur qui se reconnaitra :3). L'idée c'est d'écrire une méthode qui aura deux arguments, le premier sera un texte, qui sera la première ligne de notre boite, qui pourra, par exemple, afficher ça : "Vous: Pierre, Ordi : Ciseaux" et dont l'objectif sera d'afficher le choix du joueur et le choix généré pour l'ordinateur. Le deuxième argument pourra prendre 3 valeur, 0, 1, 2. Dans le cas ou le nombre vaudra 0, on affichera "Match Nul", si le nombre vaudra 1, "Vous avez Perdu", sinon, "Vous avez gagné".
Vous l'avez compris, cette méthode nous permettra d'afficher, de manière un peu plus civilisée que via la console, le résultat de la participation au jeu :
Il faudra Ecrire le message en fonction de l'argument, ensuite faire un branchement conditionnel qui affichera le bon message en fonction de la valeur du second argument. La dernière action sera celle qui affichera la fenêtre (qui était masquée) au moyen de la méthode show. Voici l'implémentation que je vous suggère pour la méthode que je baptise display_message :

Code (Ruby):
  1. # Affiche un message
  2. def display_message(text, number)
  3. @message.draw_text(0, 0, 280, 38, text)
  4. message = "Vous gagnez !"
  5. if number == 0
  6. message = "Match Nul !"
  7. elsif number == 1
  8. message = "Vous perdez !"
  9. end
  10. @message.draw_text(0, 20, 280, 38, message)
  11. @message.show
  12. end


Peut être que plusieurs chose vous choquent... l'absence du else, le fait que je passe par une variable. Ce choix a été prit pour éviter de réécrire la seconde méthode draw_text qui est, a mon point de vue, lourde. Donc j'initialise une variable qui prendra la seule valeur que je ne testerai pas.
Ensuite il me suffit de tester les deux autres valeurs potentielles. L'initialisation de ma variable message est donc une forme de else.
On pourra noter que mes rectangles de traçage de texte peuvent plus ou moins s'enchâsser !

icone Finalisation de l'application


On arrive tout au bout de notre système (ça aura été long :3 ), la première étape sera d'utiliser notre superbe méthode display_message.

Smiley Utilisation de display_message


Cette partie est ultra facile. Pourquoi? Parce que nous avons conçus nos outils. Il faut donc substituer, dans les méthodes pierre, feuille, ciseaux les utilisations de la méthode p par la méthode que nous venons d'écrire:

Afficher la solution complète

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. generate_choice
  9. create_window_message
  10. end
  11. # Création de la fenêtre de titre
  12. def create_title
  13. @title = Window_Help.new(1)
  14. @title.set_text("SHI FU MI !")
  15. end
  16. # Création de la fenêtre de sélection
  17. def create_commands
  18. @window_selection = Window_Shifumi.new(0, 48)
  19. @window_selection.set_handler(:pierre, method(:pierre))
  20. @window_selection.set_handler(:feuille, method(:feuille))
  21. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  22. end
  23. # Génère le choix de l'ordinateur
  24. def generate_choice
  25. list_weapons = [:pierre, :feuille, :ciseaux]
  26. @computer_choice = list_weapons.sample
  27. end
  28. def create_window_message
  29. @message = Window_Base.new(132, 168, 280, 80)
  30. @message.hide
  31. end
  32. # Affiche un message
  33. def display_message(text, number)
  34. @message.draw_text(0, 0, 280, 38, text)
  35. message = "Vous gagnez !"
  36. if number == 0
  37. message = "Match Nul !"
  38. elsif number == 1
  39. message = "Vous perdez !"
  40. end
  41. @message.draw_text(0, 20, 280, 38, message)
  42. @message.show
  43. end
  44. # Cas de sélection de Pierre
  45. def pierre
  46. if @computer_choice == :pierre
  47. display_message("Vous : Pierre, Ordi : Pierre", 0)
  48. SceneManager.call(Scene_Shifumi)
  49. elsif @computer_choice == :feuille
  50. display_message("Vous : Pierre, Ordi : Feuille", 1)
  51. SceneManager.call(Scene_Map)
  52. else
  53. display_message("Vous : Pierre, Ordi : Ciseaux", 2)
  54. SceneManager.call(Scene_Map)
  55. end
  56. end
  57. # Cas de sélection de Feuille
  58. def feuille
  59. if @computer_choice == :feuille
  60. display_message("Vous : Feuille, Ordi : Feuille", 0)
  61. SceneManager.call(Scene_Shifumi)
  62. elsif @computer_choice == :ciseaux
  63. display_message("Vous : Feuille, Ordi : Ciseaux", 1)
  64. SceneManager.call(Scene_Map)
  65. else
  66. display_message("Vous : Feuille, Ordi : Pierre", 2)
  67. SceneManager.call(Scene_Map)
  68. end
  69. end
  70. # Cas de sélection de Ciseaux
  71. def ciseaux
  72. if @computer_choice == :ciseaux
  73. display_message("Vous : Ciseaux, Ordi : Ciseaux", 0)
  74. SceneManager.call(Scene_Shifumi)
  75. elsif @computer_choice == :Pierre
  76. display_message("Vous : Ciseaux, Ordi : Pierre", 1)
  77. SceneManager.call(Scene_Map)
  78. else
  79. display_message("Vous : Ciseaux, Ordi : Feuille", 2)
  80. SceneManager.call(Scene_Map)
  81. end
  82. end
  83. end
  84.  
  85. # Fenêtre de sélection d'arme
  86. class Window_Shifumi < Window_Command
  87. # Création de la liste de selection
  88. def make_command_list
  89. add_command("Pierre", :pierre)
  90. add_command("Feuille", :feuille)
  91. add_command("Ciseaux", :ciseaux)
  92. end
  93. end



ESCROC ... ESCROC... j'ai testé et ça ne marche pas... le message ne s'affiche JAMAIS !


Effectivement. En fait, la fenêtre va bien s'afficher mais tout de suite après la commande de changement de scène va être appelé. C'est dans la rubrique suivante que nous allons voir comme pallier ce problème.

Smiley L'attente de l'appui d'une touche


Une nouvelle problématique s'offre à nous, une fois que notre message s'affiche, il nous faut attendre l'appui d'une touche (la touche C) pour passer à la scène suivante.
Pour ceci, nous allons modifier une nouvelle méthode de la classe Window_Base, il s'agit de la méthode pre_terminate. Nous avions vu que grâce à l'héritage, il n'était pas nécessaire d'écrire certaines méthodes. La méthode pre_terminate est appelée juste avant de supprimer de manière automatique les éléments de notre scène. Pour éviter que notre message, une fois affiché, soit effacé car la scène est terminée, nous allons mettre dans la méthode pre_terminate une attente jusqu'à ce que la touche C soit pressée. Voici le code :

Code (Ruby):
  1. # Attente de la pression du bouton C
  2. def pre_terminate
  3. super
  4. loop do
  5. Graphics.update
  6. Input.update
  7. break if Input.trigger?(:C)
  8. end
  9. end


Alors, la présence du mot super est pour appeler la méthode pre_terminate de Window_Base (qui est vide mais ne sait-on jamais ! Peut être qu'un script personnalisé l'a amélioré Smiley).
Ensuite, loop do indique que le code compris entre loop do et end sera répété potentiellement à l'infini (en respectant la même logique d'imbrication que les if/else/end).
Comme la portion de code comprise entre loop do et end, il faut rafraichir les graphisme et la détection des touches. C'est le rôle de Graphics.update et de Input.update.
La dernière ligne indique que l'on va sortir de cette boucle, si la touche C est pressée. C'est la méthode break qui permet de sortir de la boucle. Donc Si la touche C est pressée, on sort de la boucle.
L'écriture :

Code (Ruby):
  1. break if Input.trigger?(:C)


est identique à :

Code (Ruby):
  1. if Input.trigger?(:C)
  2. break
  3. end


Mais lorsque l'on a qu'une seule commande à exécuter, on peut le compresser comme la première forme.
Concrètement, une fois que le message est affiché, nous indiquons que nous changeons de scène, donc notre scène va appeler la méthode pre_terminate (juste avant terminate) et donc nous aurons une boucle qui attend l'appui de la touche C. Et une fois que cette touche est pressée, on sort de la boucle et s'en suit la méthode terminate qui elle, va supprimer les éléments et renvoyer sur la scène que nous avions indiqué !

icone Conclusion


Boum, enfin SmileyNous avons créer un script complet qui, malgré son aspect très simple, a tout de même survolé de multiples concepts. C'est article n'aura pas été d'une rigueure exemplaire car j'ai été extrêmement diminué dans mon éloquence pour tâcher de me faire comprendre de tous.

Rappel du code complet

Code (Ruby):
  1. # Scène de jeu principal
  2. class Scene_Shifumi < Scene_Base
  3. # Lancement de la scène
  4. def start
  5. super
  6. create_title
  7. create_commands
  8. generate_choice
  9. create_window_message
  10. end
  11. # Création de la fenêtre de titre
  12. def create_title
  13. @title = Window_Help.new(1)
  14. @title.set_text("SHI FU MI !")
  15. end
  16. # Création de la fenêtre de sélection
  17. def create_commands
  18. @window_selection = Window_Shifumi.new(0, 48)
  19. @window_selection.set_handler(:pierre, method(:pierre))
  20. @window_selection.set_handler(:feuille, method(:feuille))
  21. @window_selection.set_handler(:ciseaux, method(:ciseaux))
  22. end
  23. # Génère le choix de l'ordinateur
  24. def generate_choice
  25. list_weapons = [:pierre, :feuille, :ciseaux]
  26. @computer_choice = list_weapons.sample
  27. end
  28. def create_window_message
  29. @message = Window_Base.new(132, 168, 280, 80)
  30. @message.hide
  31. end
  32. # Affiche un message
  33. def display_message(text, number)
  34. @message.draw_text(0, 0, 280, 38, text)
  35. message = "Vous gagnez !"
  36. if number == 0
  37. message = "Match Nul !"
  38. elsif number == 1
  39. message = "Vous perdez !"
  40. end
  41. @message.draw_text(0, 20, 280, 38, message)
  42. @message.show
  43. end
  44. # Cas de sélection de Pierre
  45. def pierre
  46. if @computer_choice == :pierre
  47. display_message("Vous : Pierre, Ordi : Pierre", 0)
  48. SceneManager.call(Scene_Shifumi)
  49. elsif @computer_choice == :feuille
  50. display_message("Vous : Pierre, Ordi : Feuille", 1)
  51. SceneManager.call(Scene_Map)
  52. else
  53. display_message("Vous : Pierre, Ordi : Ciseaux", 2)
  54. SceneManager.call(Scene_Map)
  55. end
  56. end
  57. # Cas de sélection de Feuille
  58. def feuille
  59. if @computer_choice == :feuille
  60. display_message("Vous : Feuille, Ordi : Feuille", 0)
  61. SceneManager.call(Scene_Shifumi)
  62. elsif @computer_choice == :ciseaux
  63. display_message("Vous : Feuille, Ordi : Ciseaux", 1)
  64. SceneManager.call(Scene_Map)
  65. else
  66. display_message("Vous : Feuille, Ordi : Pierre", 2)
  67. SceneManager.call(Scene_Map)
  68. end
  69. end
  70. # Cas de sélection de Ciseaux
  71. def ciseaux
  72. if @computer_choice == :ciseaux
  73. display_message("Vous : Ciseaux, Ordi : Ciseaux", 0)
  74. SceneManager.call(Scene_Shifumi)
  75. elsif @computer_choice == :Pierre
  76. display_message("Vous : Ciseaux, Ordi : Pierre", 1)
  77. SceneManager.call(Scene_Map)
  78. else
  79. display_message("Vous : Ciseaux, Ordi : Feuille", 2)
  80. SceneManager.call(Scene_Map)
  81. end
  82. end
  83. # Attente de la pression du bouton C
  84. def pre_terminate
  85. super
  86. loop do
  87. Graphics.update
  88. Input.update
  89. break if Input.trigger?(:C)
  90. end
  91. end
  92. end
  93.  
  94. # Fenêtre de sélection d'arme
  95. class Window_Shifumi < Window_Command
  96. # Création de la liste de selection
  97. def make_command_list
  98. add_command("Pierre", :pierre)
  99. add_command("Feuille", :feuille)
  100. add_command("Ciseaux", :ciseaux)
  101. end
  102. end



J'espère que ce tutoriel vous aura permis de mieux comprendre certains mécanismes basiques du RGSS et de Ruby et que vous n'hésiterez pas à continuer votre formation. Ce tutoriel est le premier mais je tâcherai d'écrire un maximum de "livre blanc" qui survolent plusieurs concepts au moyen de cas pratiques !
Tout bientôt on se retrouvera pour expliquer comment ajouter des ressources graphiques !
Si vous voulez continuer, je vous invite à lire cet excellent ouvrage sur Ruby : Lien vers l'excellent ouvrage.

A bientôt pour de nouveaux tutoriels !

Index

Tags

Annonces
Bilou Concept
BilouCorp
Découvertes
Event Extender
Jeux
RPG Maker
Script
Tutoriel

Auteurs

2cri
Grim
Hiino
Joke
Nuki
PypeBros
Raho
S4suk3

Suivez nous
Rss

Poster un commentaire



Commentaires

qmsdkqsd
oukilé "Terminate" ? Posté le : 21/10/2016 à 16h46
Lolobleurp
EDIT: Et je n'arrive pas à afficher la fenêtre "simple" pour le texte par rapport à Window_Base, j'ai voulu changer les coordonnées mais toujours rien, quelqu'un pourrais m'aider ? Posté le : 23/03/2016 à 08h54
Lolobleurp
Comment créer plusieurs fenêtres de sélection ? Posté le : 22/03/2016 à 08h58
Alex
Un des rares tutos que j'ai pu comprendre facilement! Merci
J'aimerais bien voir comment faire des ressources garphiques maintenant si vous savez un autre tuto pour ça! Posté le : 20/03/2016 à 17h33
Darkrai911
Je n'ai qu'une chose à dire: MERCI!!!
Trois semaines que je cherche des tutos sur le RGSS3, et je tombe sur ça!!! Merci encore, et encore! Posté le : 15/08/2015 à 23h02
Artheoss
Je suis scotché !
Je n'ai lu qu'un dixième et je ne peux m'empêcher de crier au génie !
La rédaction est parfaite, l'explication est claire etc...
Je risque d'en apprendre beaucoup aujourd'hui sur le RGSS !
Merci infiniment pour ce tuto, je retourne à ma lecture ^^ Posté le : 18/11/2014 à 21h15
Aki
Je suis satisfaite d'être passée ici.
Je n'ai que trop peu de notion et cest explication m'ont founit les reponse que je cherché et que certain scripteur de ma connaissance semblaient avoir du mal a m'expliquer.
Merci infiniment pour laide apporter.
Je vais tacher de faire autre chose en me servant de se que jai aprris dans se script.
Bonne continuation. Posté le : 15/11/2014 à 05h27
JeanCad
Excellent... et c'est pas le premier tutoriel que je consulte!
Vraiment professionnel et on comprend du premier coup! Posté le : 23/08/2014 à 02h41
Joke
Merci pour tes encouragements, Raph =)

Mais si on transmet notre savoir jusqu'à la fin on sera fini ! Il vaut mieux le transmettre à l'infini ! x) Posté le : 25/04/2013 à 15h56
Raph
Excellent site ! Des tutoriels utiles, expliqués, et approfondis ! J'espère que vous transmettrez votre savoir jusqu'à la fin. Merci encore. Posté le : 24/04/2013 à 20h45
testament
OK, excuse de m'être mal exprimer. Donc maintenant je comprend mieux le code. Merci de tes explications.
Posté le : 20/04/2013 à 23h33
S4suk3
Je ne vois pas de réelle différence avec créer une classe et définir une classe. Je pense que tu veux dire "instancier un objet de tel classe". Donc faire truc = MaClasse.new
A priori, si tu connais la structure de ton constructeur, tu peux le faire avant mais je préfère écrire d'abord ma classe avant de l'utiliser. Cependant, une classe se spécialise et en cours de développement il est courant que l'on ajoute des méthodes, des attributs etc. Posté le : 20/04/2013 à 12h00
testament
Oh gosh, ce tuto est super bien.
J'ai une question n'étant pas adepte de la prog, faut-il obligatoirement créer la classe avant de la définir ou peut-on faire l'inverse?
Cela peux paraître stupide a première vue, mais c'est une question que je me pose.
Sinon ton tuto me rappel ce que Nuki avais fait en event avec un shi fu mi aussi.
Bon travail de ta part s4suk3.
Posté le : 20/04/2013 à 11h40
Olowynd
Et voila, j'ai appris pas mal de choses sur les bases du scripting, c'est cool =) j'essayerais de mettre tout ça en application bientôt, peut-être en créant un "morpion" si j'y arrive =P ou en commençant par d'autres trucs plus simples. Posté le : 20/04/2013 à 11h34
Olowynd
Le tutoriel qu'il me fallait pour me lancer dans le scripting =D
Merci ! Posté le : 20/04/2013 à 09h55
Joke
Ce tutoriel est une mine d'or, qui mérite amplement son label de qualité BilouCorp ! :D

Tu as réussis à introduire plusieurs notions propre au RGSS3 (Que je ne connaissais pas, newbie que je suis !) que plusieurs personnes reviennent sans arrêt demander... Le tout dans un exemple vraiment simple, clair, qui rend le tout incroyablement compréhensible !

Merci beaucoup pour cette belle publication qui je pense est incontournable ! =) Posté le : 20/04/2013 à 01h26
S4suk3
Merci beaucoup, heureux que tu l'ai lu ! Posté le : 20/04/2013 à 01h21
Heaven
Super tutoriel que plusieurs personnes (don moi) l'attendait,
j'ai hâte de voir la suite (si il y en a une)


Heav'n Posté le : 20/04/2013 à 01h17