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.
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.
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).
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.
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.
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 !
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.
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): class Scene_Shifumi < Scene_Base
# Ici se trouvera le code notre scène
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.
Aie, 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.
Testons notre scène !
Tout ça c'est bien joli mais comment puis-je tester ma scène
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): 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): 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 !
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).
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): je_suis_une_variable = 10
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
@.
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): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
# Initialisation de la scène
end
end
A 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): class Scene_Truc < Scene_Base
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): class Scene_Truc < Scene_Base
def start
end
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): def start
create_main_viewport
end
Donc concrètement, faire ça :
Code (Ruby): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
# Initialisation de la scène
end
end
Est identique que de faire :
Code (Ruby): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
create_main_viewport
# Initialisation de la scène
end
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).
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): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
end
def create_title
# Ici on créera le titre
end
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): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
end
def create_title
@title = Window_Help.new(1)
end
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): class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
end
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
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 !
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 !
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): class Window_Shifumi < Window_Command
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
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".
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): # Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
end
Afficher le code complet
Code (Ruby): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
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.
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
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
end
# Cas de sélection de Pierre
def pierre
p "Vous avez choisi la pierre"
end
# Cas de sélection de Feuille
def feuille
p "Vous avez choisi la feuille"
end
# Cas de sélection de Ciseaux
def ciseaux
p "Vous avez choisi les ciseaux"
end
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Cas de sélection de Pierre
def pierre
p "Vous avez choisi la pierre"
end
# Cas de sélection de Feuille
def feuille
p "Vous avez choisi la feuille"
end
# Cas de sélection de Ciseaux
def ciseaux
p "Vous avez choisi les ciseaux"
end
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 !
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.
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.
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 !
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): liste_arme = [:pierre, :feuille, :ciseaux]
Pourquoi 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): liste_arme = [:pierre, :feuille, :ciseaux]
valeur_aleatoire = liste_arme.sample
ou encore
Code (Ruby): 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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
generate_choice
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Génère le choix de l'ordinateur
def generate_choice
list_weapons = [:pierre, :feuille, :ciseaux]
@computer_choice = list_weapons.sample
end
# Cas de sélection de Pierre
def pierre
p "Vous avez choisi la pierre"
end
# Cas de sélection de Feuille
def feuille
p "Vous avez choisi la feuille"
end
# Cas de sélection de Ciseaux
def ciseaux
p "Vous avez choisi les ciseaux"
end
end
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 :
En 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): if ma question
# Succession d'action si la réponse
# est vraie
else
# Succession d'action si la réponse
# est fausse
end
# suite du programme
Un exemple super concret !
Code (Ruby): if @computer_choice == :pierre
p "L'ordinateur à choisi Pierre... lol"
else
p "L'ordinateur n'a pas choisi Pierre... lal"
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!
c'é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): if @computer_choice == :pierre
p "L'ordinateur a choisi Pierre"
end
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): if @computer_choice == :pierre
p "L'ordinateur a choisi Pierre"
else
if @computer_choice == :feuille
p "L'ordinateur a choisi Feuille"
else
p "L'ordinateur a choisi Ciseaux"
end
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): if @computer_choice == :pierre
p "L'ordinateur a choisi Pierre"
elsif @computer_choice == :feuille
p "L'ordinateur a choisi Feuille"
else
p "L'ordinateur a choisi Ciseaux"
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
)
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): # Cas de sélection de Pierre
def pierre
if @computer_choice == :pierre
p "Vous avez tous les deux choisis Pierre, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :feuille
p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Feuille
def feuille
if @computer_choice == :feuille
p "Vous avez tous les deux choisis Feuille, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :ciseaux
p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Ciseaux
def ciseaux
if @computer_choice == :ciseaux
p "Vous avez tous les deux choisis Ciseaux, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :Pierre
p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
SceneManager.call(Scene_Map)
end
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
generate_choice
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Génère le choix de l'ordinateur
def generate_choice
list_weapons = [:pierre, :feuille, :ciseaux]
@computer_choice = list_weapons.sample
end
# Cas de sélection de Pierre
def pierre
if @computer_choice == :pierre
p "Vous avez tous les deux choisis Pierre, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :feuille
p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Feuille
def feuille
if @computer_choice == :feuille
p "Vous avez tous les deux choisis Feuille, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :ciseaux
p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Ciseaux
def ciseaux
if @computer_choice == :ciseaux
p "Vous avez tous les deux choisis Ciseaux, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :Pierre
p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
SceneManager.call(Scene_Map)
end
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
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 !
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.
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): # Crée la fenêtre de message
def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
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): # Crée la fenêtre de message
def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
@message.hide
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
generate_choice
create_window_message
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Génère le choix de l'ordinateur
def generate_choice
list_weapons = [:pierre, :feuille, :ciseaux]
@computer_choice = list_weapons.sample
end
# Crée la fenêtre de message
def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
@message.hide
end
# Cas de sélection de Pierre
def pierre
if @computer_choice == :pierre
p "Vous avez tous les deux choisis Pierre, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :feuille
p "Vous aviez choisi Pierre et l'ordinateur Feuille, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Pierre et l'ordinateur Ciseaux, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Feuille
def feuille
if @computer_choice == :feuille
p "Vous avez tous les deux choisis Feuille, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :ciseaux
p "Vous aviez choisi Feuille et l'ordinateur Ciseaux, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Feuille et l'ordinateur Pierre, vous gagnez"
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Ciseaux
def ciseaux
if @computer_choice == :ciseaux
p "Vous avez tous les deux choisis Ciseaux, Match Nul"
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :Pierre
p "Vous aviez choisi Ciseaux et l'ordinateur Pierre, vous perdez"
SceneManager.call(Scene_Map)
else
p "Vous aviez choisi Ciseaux et l'ordinateur Feuille, vous gagnez"
SceneManager.call(Scene_Map)
end
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
end
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
. 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
).
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): 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): @message.draw_text(0, 0, 280, 38, "Vous: Pierre, Ordi : Ciseaux")
Code comple de la méthode
Code (Ruby): def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
#@message.hide
@message.draw_text(0, 0, 280, 38, "Vous: Pierre, Ordi : Ciseaux")
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): # Affiche un message
def display_message(text, number)
@message.draw_text(0, 0, 280, 38, text)
message = "Vous gagnez !"
if number == 0
message = "Match Nul !"
elsif number == 1
message = "Vous perdez !"
end
@message.draw_text(0, 20, 280, 38, message)
@message.show
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 !
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.
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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
generate_choice
create_window_message
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Génère le choix de l'ordinateur
def generate_choice
list_weapons = [:pierre, :feuille, :ciseaux]
@computer_choice = list_weapons.sample
end
def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
@message.hide
end
# Affiche un message
def display_message(text, number)
@message.draw_text(0, 0, 280, 38, text)
message = "Vous gagnez !"
if number == 0
message = "Match Nul !"
elsif number == 1
message = "Vous perdez !"
end
@message.draw_text(0, 20, 280, 38, message)
@message.show
end
# Cas de sélection de Pierre
def pierre
if @computer_choice == :pierre
display_message("Vous : Pierre, Ordi : Pierre", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :feuille
display_message("Vous : Pierre, Ordi : Feuille", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Pierre, Ordi : Ciseaux", 2)
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Feuille
def feuille
if @computer_choice == :feuille
display_message("Vous : Feuille, Ordi : Feuille", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :ciseaux
display_message("Vous : Feuille, Ordi : Ciseaux", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Feuille, Ordi : Pierre", 2)
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Ciseaux
def ciseaux
if @computer_choice == :ciseaux
display_message("Vous : Ciseaux, Ordi : Ciseaux", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :Pierre
display_message("Vous : Ciseaux, Ordi : Pierre", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Ciseaux, Ordi : Feuille", 2)
SceneManager.call(Scene_Map)
end
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
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.
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): # Attente de la pression du bouton C
def pre_terminate
super
loop do
Graphics.update
Input.update
break if Input.trigger?(:C)
end
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é
).
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): break if Input.trigger?(:C)
est identique à :
Code (Ruby): if Input.trigger?(:C)
break
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é !
Conclusion
Boum, enfin
Nous 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): # Scène de jeu principal
class Scene_Shifumi < Scene_Base
# Lancement de la scène
def start
super
create_title
create_commands
generate_choice
create_window_message
end
# Création de la fenêtre de titre
def create_title
@title = Window_Help.new(1)
@title.set_text("SHI FU MI !")
end
# Création de la fenêtre de sélection
def create_commands
@window_selection = Window_Shifumi.new(0, 48)
@window_selection.set_handler(:pierre, method(:pierre))
@window_selection.set_handler(:feuille, method(:feuille))
@window_selection.set_handler(:ciseaux, method(:ciseaux))
end
# Génère le choix de l'ordinateur
def generate_choice
list_weapons = [:pierre, :feuille, :ciseaux]
@computer_choice = list_weapons.sample
end
def create_window_message
@message = Window_Base.new(132, 168, 280, 80)
@message.hide
end
# Affiche un message
def display_message(text, number)
@message.draw_text(0, 0, 280, 38, text)
message = "Vous gagnez !"
if number == 0
message = "Match Nul !"
elsif number == 1
message = "Vous perdez !"
end
@message.draw_text(0, 20, 280, 38, message)
@message.show
end
# Cas de sélection de Pierre
def pierre
if @computer_choice == :pierre
display_message("Vous : Pierre, Ordi : Pierre", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :feuille
display_message("Vous : Pierre, Ordi : Feuille", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Pierre, Ordi : Ciseaux", 2)
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Feuille
def feuille
if @computer_choice == :feuille
display_message("Vous : Feuille, Ordi : Feuille", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :ciseaux
display_message("Vous : Feuille, Ordi : Ciseaux", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Feuille, Ordi : Pierre", 2)
SceneManager.call(Scene_Map)
end
end
# Cas de sélection de Ciseaux
def ciseaux
if @computer_choice == :ciseaux
display_message("Vous : Ciseaux, Ordi : Ciseaux", 0)
SceneManager.call(Scene_Shifumi)
elsif @computer_choice == :Pierre
display_message("Vous : Ciseaux, Ordi : Pierre", 1)
SceneManager.call(Scene_Map)
else
display_message("Vous : Ciseaux, Ordi : Feuille", 2)
SceneManager.call(Scene_Map)
end
end
# Attente de la pression du bouton C
def pre_terminate
super
loop do
Graphics.update
Input.update
break if Input.trigger?(:C)
end
end
end
# Fenêtre de sélection d'arme
class Window_Shifumi < Window_Command
# Création de la liste de selection
def make_command_list
add_command("Pierre", :pierre)
add_command("Feuille", :feuille)
add_command("Ciseaux", :ciseaux)
end
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 !