-29%
Le deal à ne pas rater :
PC portable – MEDION 15,6″ FHD Intel i7 – 16 Go / 512Go (CDAV : ...
499.99 € 699.99 €
Voir le deal

Aller en bas
Ekron
Ekron
Membre

Nombre de messages : 89
Localisation : Paris
Distinction : aucune
Date d'inscription : 30/12/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Ruby/RGSS ou la puissance cachée de RPG Maker

Mer 8 Jan 2014 - 22:28
Il y a quelques jours, je me suis lancé dans l'écriture d'un tutoriel traitant du Ruby pour RPG Maker et je me permets maintenant de vous le partager en espérant aider ceux qui recherchent un moyen de débuter (actuellement, seuls les trois premiers chapitres sont écrits). En effet, ce tutoriel est à destination des débutants, même si, en admettant que j'en aie le temps, je prévois une éventuelle section sur le Ruby « avancé ». (Entre guillemets parce que tout dépend du point de vue, même dans cette partie, les explications resteront évidentes pour un programmeur Ruby expérimenté.)
Comme je l'explique dans l'introduction, j'ai tendance à dépasser un peu le sujet pour englober des domaines un peu plus variés et ainsi amener le lecteur à s'intéresser à d'autres sujets. Cela me sert également à rassurer les lecteurs qui n'ont jamais écrit une ligne de code puisque j'explique que le Ruby est parmi les langages les plus simples qui existent aujourd'hui.
Si vous avez une question, ou une remarque (comme une erreur ou un passage peu clair à me signaler par exemple) n'hésitez pas à poster dans la suite de ce sujet. (Même pour une erreur d'orthographe, je ne suis malheureusement pas un expert dans ce domaine...)
Ce n'est que le début, j'ai conscience qu'il n'apporte pas encore grand-chose, mais j'essaierai de le compléter dès que j'aurai un peu de temps.
Je vous souhaite une bonne lecture !



Ruby / RGSS ou la puissance cachée de RPG Maker

Sommaire :
Partie 1 : Les bases de la programmation
-> Chapitre 1 : Programmer, c'est vraiment pour moi ?
-> Chapitre 2 : Programmer ? Vous savez déjà faire !
-> Chapitre 3 : Afficher un message à l'écran
-> Chapitre 4 : Les variables
-> Chapitre 5 : Les conditions


Vous avez vu comme moi les dizaines et les dizaines de scripts pour RPG Maker qui circulent sur le net. Vu ce que ces scripts sont capables de faire : il vous suffit de les copier-coller dans votre projet et d'un coup, votre menu se transforme ou votre système de combat change du tout au tout. C'est dans le Ruby / RGSS que se situe la réelle puissance de RPG Maker, et si vous avez un minimum d'expérience du logiciel, vous saurez que j'ai raison. Voilà pour le titre.

Enfin non. Il reste un mot. « Cachée. » Pourquoi ai-je écrit ce mot à votre avis ? Pourtant l'éditeur de scripts est là, bien visible, et il y a fort à parier que vous vous en êtes déjà servi pour personnaliser votre jeu. Mais l'avez-vous vraiment personnalisé vous-même ou avez-vous juste ajouté un changement qu'un autre a écrit ? Là est la vraie raison de la présence de ce mot dans mon titre : la majeure partie des gens qui utilisent ce logiciel ne savent pas utiliser l'éditeur de scripts autrement que pour ajouter ce que d'autres ont fait, et c'est vraiment dommage. C'est dommage parce que tout d'abord cela vous prive d'un grand contrôle sur votre jeu : vous êtes dépendant de ce que les autres ont fait pour vous, et vous ne pouvez pas contrôler ce qu'ont fait les autres. C'est dommage également parce que la compréhension de l'architecture d'un jeu dans RPG Maker peut apporter énormément en compréhension de l'architecture globale d'un jeu vidéo et peut vous resservir si un jour vous souhaitez vous passer de ce logiciel. Cela peut vous apporter également beaucoup en compréhension du monde informatique et de la programmation en général ; je ne dis pas que vous serez des programmeurs hors-pairs, mais c'est un premier pas. Et je reste persuadé que dans notre monde actuel, dans lequel les technologies informatiques prennent une place gigantesque  qui ne cesse de croître, apprendre à programmer est presque aussi important que d'apprendre à lire.

Dans ce tutoriel je souhaiterais vous enseigner les rudiments du Ruby ainsi que son application dans RPG Maker. J'essaierai de vous montrer comment fonctionnent les scripts qui sont à la base d'un projet et je vous expliquerai comment les modifier correctement, comment créer les vôtres et comment comprendre ceux que d'autres ont créé. Mais ce n'est pas tout, je vais également essayer de glisser ici et là quelques notions plus générales sur la création de jeu vidéo et de programme (bien que ces parties ne soient pas obligatoires, je vous recommande tout de même de les lire, ne serait-ce qu'à titre d'information) afin de vous ouvrir un peu les yeux sur un monde que peu osent aborder car beaucoup le croient trop dur. Il est vrai que la programmation peut être très très complexe, mais on peut faire énormément avec des choses simples. Vous allez voir !

Note : Ce tutoriel a été pensé et écrit pour RPG Maker VX Ace. Il est très probable que certaines partie (notamment sur le Ruby général) puissent resservir dans les autres versions de la série voire dans d'autres contextes, mais il est également possible que certaines applications ne fonctionnent pas dans les versions antérieures. Sachez en outre que ce tutoriel s'adresse à des makers ayant un minimum d'expérience du logiciel, notamment en eventmaking. Vous aurez besoin de savoir créer un projet, de savoir placer des événements et de remplir ces événements seuls, je ne vais pas pouvoir tout expliquer. Si jamais vous pensez être un peu juste à ce niveau-là, je vous invite à commencer par un tutoriel de débutant sur le logiciel (le forum en est rempli).



Partie 1 : Les bases de la programmation


Chapitre 1 : Programmer, c'est vraiment pour moi ?

Nous y voilà. Tout d'abord, entendons-nous sur les bases : depuis tout à l'heure, je vous parle de programmer, mais êtes-vous réellement sûr de savoir ce que cela signifie ?

C'est simple, quand on programme, on rédige des programmes informatiques, on écrit du code pour expliquer à notre ordinateur ce que l'on attend de lui. Mais pourquoi écrit-on du code ? Pourquoi ne peut-on pas simplement dire à notre ordi « Fais ça » en bon français ? Pourquoi l'ordinateur ne comprend-il pas les langages humains ?

Pour se faire comprendre de l'ordinateur, il faut parler son langage, le « langage binaire » (je le mets entre guillemets car la dénomination correcte est « langage machine », le binaire n'étant pas un langage mais une base de comptage). Voici un exemple d'instruction que je pourrais donner à mon ordinateur :
0100011101011111010101000111010
Ceci pourrait signifier « ajoute 7 et 2 » ou « affiche un pixel à l'écran » ou quantité d'autres choses. Je dois vous dire que je ne connais pas ce langage par cœur, d'ailleurs je crois que très peu de gens sur Terre savent l'utiliser réellement. C'est beaucoup trop compliqué à comprendre, à écrire puis à relire. Programmer une calculatrice comme ça relève déjà d'un effort surhumain alors imaginez un jeu vidéo ! C'est mission impossible.

Ruby/RGSS ou la puissance cachée de RPG Maker 1390245255-editeur-hexa
Pour ceux que cela intéresse, voici ce que l'on voit lorsque l'on ouvre une application. Dans la partie incompréhensible de l'image, la colonne de gauche ce sont des adresses qui permettent de se repérer dans le fichier (il est très très grand). Le programme en lui-même se situe dans la colonne du milieu et il est écrit en langage machine. Vous ne voyez pas que des 0 et des 1 pour la bonne et simple raison que le logiciel avec lequel j'ai ouvert le programme utilise la notation hexadécimale qui est un raccourci de la notation binaire (2 caractères en hexadécimal équivalent à 8 en binaire).

On a donc inventé des langages de programmation plus simples mais comme l'ordinateur ne pouvait pas les comprendre, on a dû créer des programmes qui « traduisent » ces langages de programmation en langage machine. Des langages de programmation, il en existe des centaines, et je dois vous avouer que je ne connais pas tous les noms. Parmi ceux qu'ils faut connaître, vous avez :
- les basiques, le langage machine et le langage assembleur ;
- les ultra-classiques, le C, le C++ et le Java ;
- les importants, le C# (se prononce « cé charpe »), le Python, le PHP... et le Ruby.
Il en existe beaucoup beaucoup d'autres (vous avez une liste à cette adresse : http://fr.wikipedia.org/wiki/Liste_des_langages_de_programmation), mais ce qu'il est important de noter, c'est que le Ruby fait partie des langages les plus utilisés aujourd'hui. Cela est notamment dû à une technologie assez populaire qui se nomme « Ruby on Rails » et qui permet de programmer un site web en Ruby. C'est assez intéressant dans la mesure où une partie de ce que je vais vous apprendre pourra être réutilisée si vous le souhaitez.

Il faut savoir que l'on classe les langages de programmation par niveau. Les langages bas-niveau sont les langages qui sont dits « proches de la machine », c'est-à-dire qu'ils effectuent des opérations très basiques et donc qu'il faut écrire beaucoup de lignes pour une chose aussi simple que d'afficher du texte à l'écran par exemple. Les langages haut-niveau sont plus proches des langages humains (enfin de l'anglais pour être précis) : quand vous écrivez une instruction en langage de haut niveau elle fait beaucoup de choses d'un seul coup et produira plusieurs instructions en langage machine quand elle sera traduite. Notez toutefois que si les langages de haut-niveau se rapprochent des langages humains, les ordinateurs ne sont pas (encore) capables de comprendre l'anglais ou le français, car ce sont des langues avec un vocabulaire très riche et une structure excessivement complexe.

Mais si les langages de haut-niveau sont plus simples, pourquoi n'utilise-t-on pas toujours le langage de plus haut-niveau possible ? La réponse est simple : plus le langage est haut-niveau, moins vous avez de liberté. C'est assez logique quand on y pense : un langage est de haut-niveau parce qu'il vous permet d'écrire des programmes compliqués avec peu de lignes. Donc plus le langage est de haut-niveau et plus il fait de choses à votre place, ces choses que vous n'avez pas écrites mais qui doivent être faites quand même, choses sur lesquelles vous n'aurez aucun contrôle. (J'ai conscience que cette explication doit vous paraître assez abstraite, mais j'illustrerai mon propos par la suite.) Pour résumer, un langage de haut-niveau permet de programmer rapidement, mais un langage de bas-niveau permet d'avoir un contrôle plus fin sur l'exécution de son programme. En fait, tout est question de compromis en fonction du programme que vous voulez réaliser.

Maintenant, où se situent les langages que je vous ai cités ? D'un point de vue informatique, le langage machine et l'assembleur sont tout en bas : ils sont les langages les plus bas-niveau qui soient. Le langage assembleur n'est qu'une traduction mot-à-mot du langage machine (enfin pas toujours, mais ce n'est pas très important) : à une instruction en langage machine correspond une instruction en langage assembleur (les instructions assembleur sont des abréviations qui s'inspirent de l'anglais et sont donc un peu plus lisibles pour nous que les 0 et les 1, d'où l'intérêt de ce langage). Autant vous dire que l'assembleur est presque aussi complexe que le langage machine.
Le C est le langage de programmation de référence : c'est probablement celui qui est connu par le plus de programmeurs dans le monde et il est encore utilisé aujourd'hui bien qu'il soit assez vieux ; il est encore très efficace ! C'est un langage de haut-niveau qu'il faut connaître, au moins de nom.
Le C++ est une évolution du C. Il est un peu plus haut-niveau (mais pas énormément) dans la mesure où il fournit des outils « tout-prêts » supplémentaires, mais dire qu'il est plus simple que le C est faux. Le C++, si on se donne la peine de creuser, est relativement complexe mais il est également très employé, notamment parce qu'il est aussi rapide que le C.
Les langages comme Python, PHP, C# et Ruby sont des langages de très haut-niveau. Il est assez facile de les utiliser mais ils sont un peu plus limités que le C (et un peu plus lents, il faut bien le dire), toutefois, cela suffit pour beaucoup d'applications.

Dans le domaine des jeux vidéos, on utilise majoritairement le C++ et des outils qui sont développés en C++ car c'est le langage qui allie le mieux rapidité (d'écriture du code) et performance. D'ailleurs, RPG Maker est programmé en C++ !

À ce niveau-là, je pense que j'ai perdu une bonne partie des lecteurs, persuadés que RPG Maker était programmé en Ruby et que c'était pour ça qu'on était là. Eh bien non. Le milieu du jeu vidéo est fait de telle manière qu'il existe énormément d'outils permettant de simplifier leur création (Unity, UDK... pour les jeux en 3D, RPG Maker, Game Maker... pour les jeux en 2D). Ces outils sont programmés dans un premier langage (souvent le C++) qui est invisible pour l'utilisateur. Puis, dans un second temps, ils proposent à l'intérieur de leur interface un second langage qui permet de programmer le jeu en lui-même : on appelle ce langage un langage de scripts. Le langage de scripts le plus répandu est le Lua, UDK utilise un langage maison qui s'appelle l'UnrealScript et RPG Maker utilise le Ruby. Ce que vous voyez dans votre éditeur de scripts, ce n'est donc pas le code du logiciel RPG Maker (vous ne pouvez pas modifier le logiciel en modifiant ce code), c'est le code de votre jeu !

Ruby/RGSS ou la puissance cachée de RPG Maker 1390246538-77203-udk
UDK, l'un des moteurs de jeu 3D les plus puissants actuellement sur le marché. Version complète gratuite pour un usage non commercial.

Votre code Ruby est enregistré dans des fichiers. À l'exécution, RPG Maker va lire ces fichiers et va exécuter les opérations qu'ils décrivent « à la volée », c'est ce que l'on appelle « l'interprétation ». Autrement dit, lorsque vous publiez votre jeu, vous livrez RPG Maker avec. Enfin pas tout RPG Maker, puisque le joueur ne peut pas accéder à l'interface du logiciel grâce à votre jeu, mais vous livrez la partie de RPG Maker qui se charge d'interpréter le code Ruby.

Résumons ! Ruby est un langage de programmation très haut-niveau, c'est-à-dire qu'il est assez simple parce qu'il s'occupe de beaucoup de choses que nous n'aurons pas à gérer. Le code de votre jeu est écrit en Ruby. Quand vous lancez votre jeu, RPG Maker commence à lire les instructions puis les exécute au fur et à mesure que vous avancez dans le jeu.



Chapitre 2 : Programmer ? Vous savez déjà faire !

Le titre de ce chapitre est volontairement incitatif, mais vous allez voir qu'il n'en est pas faux pour autant. Mais avant tout, parlons un peu de RGSS. Ces initiales reviennent fréquemment dans le monde du making, d'ailleurs l'acronyme est même dans le titre du tutoriel. On entend dire beaucoup de choses à propos de RGSS : ce serait tantôt un langage de programmation, tantôt une bibliothèque de fonctionnalités propres à RPG Maker, il y en a même qui confondent RGSS et RTP. Ces erreurs sont compréhensibles, notamment car avec certaines versions de RPG Maker, les RTP sont fournis avec le RGSS sous l’appellation RGSS. Mais RGSS signifie Ruby Games Scripting System ce qui est peut se traduire peu ou prou par Système de script Ruby pour jeux (vidéos). Le RGSS n'est pas un langage inspiré de Ruby, c'est tout simplement le nom de l'interpréteur de Ruby qui est fourni dans RPG Maker. L'intepréteur, pour ceux qui ne se souviennent déjà plus, c'est le nom commun du programme qui lit le code Ruby et l'exécute.

Il est donc faux de dire que l'on code en RGSS ou en Ruby / RGSS, mais l'on code en Ruby pour RGSS. En effet, les interpréteurs peuvent varier des uns aux autres. La raison pour laquelle Enterbrain a choisi de coder son propre interpréteur au lieu d'utiliser les alternatives libres (et très performantes) qui existent déjà, c'est qu'il manquait des fonctionnalités. RGSS implémente ainsi complètement les mécanismes de base de Ruby et rajoute par-dessus des fonctionnalités nécessaires à la création de votre jeu vidéo (des fonctionnalités graphiques et audios par exemple).

Il y a eu trois versions différentes de RGSS, correspondant respectivement à RPG Maker XP, RPG Maker VX et RPG Maker VX Ace. Celle que nous allons étudier est la dernière, RGSS 3 pour RPG Maker VX Ace. Chacune des nouvelles versions apporte son lot de différences avec la précédente aussi, les scripts qui fonctionnent sur l'un des logiciels de la suite ne fonctionneront pas forcément sur les autres. Ceci dit, les différences ne sont pas non plus insurmontables.

Bien ! Assez palabré, il est temps de s'y mettre. Ouvrez donc le logiciel, nous allons commencer. Je vous ai dit au début de ce chapitre que vous aviez forcément déjà programmé, il est temps que je vous le prouve. Pour cela, faisons une petite expérience. Créez (rapidement) un bâtiment pouvant figurer un cinéma puis mettez un PNJ à l'accueil. Le cinéma passe un film interdit aux moins de 12 ans, le PNJ doit donc demander au héros s'il a plus ou moins de 12 ans. Si le héros a moins de 12 ans, la barrière menant à la salle ne s'ouvre pas et le PNJ lui dit qu'il n'a pas le droit d'entrer. Si le héros à plus de 12 ans, la barrière s'ouvre et le PNJ lui souhaite un bon film.

J'espère que vous savez tous faire ça. Il suffit de créer un petit dialogue avec un choix, un interrupteur qui s'active ou non en fonction du choix, et une condition sur l'interrupteur qui détermine si la barrière doit s'ouvrir ou non. Eh bien, si l'on y réfléchit, vous avez donné des instructions à l'ordinateur et quand vous avez lancé votre jeu, celui-ci les a comprises et exécutées. C'est la définition même de programmer. Alors certes, le langage que vous avez utilisé est d'un niveau encore plus haut que le Ruby puisqu'il est très simple et très limité (vous ne pouvez rien faire d'autre que ce que les quelques boutons vous proposent) mais ça reste un langage que vous avez correctement utilisé, félicitations !

Qui plus est, rien que dans ce petit événement, vous avez utilisé des notions importantes de programmation : les interrupteurs qui changent de valeur au cours du jeu en fonction des actions de l'utilisateur (on les appelle « booléens » en programmation) et les conditions qui permettent d'effectuer telle ou telle action en fonction d'éléments précis (comme des interrupteurs).

C'est comme cela que nous allons aborder la programmation. Nous aurons des objets (des interrupteurs ou booléens par exemple), ces objets auront des valeurs que nous modifierons au fil de l'exécution et en fonction de ces valeurs nous effectuerons telle ou telle action. Puis nous allons voir des objets un peu plus compliqués et un peu plus abstraits et enfin nous apprendrons à créer nos propres objets et à faire des opérations dessus (mais ça, ce n'est pas pour tout de suite).

Bien sûr, tout cela sera un peu plus difficile que la programmation graphique avec laquelle il vous suffit de cliquer et le logiciel génère le code. Ici, c'est vous qui allez écrire ce code et ce code obéit à des règles de syntaxe précises. C'est un peu comme en français : on commence notre phrase par une majuscule et on la termine par un point pour que celui qui lit s'y retrouve. Eh bien là c'est pareil, nous devons respecter un certain nombre de conventions pour que notre brave RGSS sache à quoi s'en tenir. Cependant, l'ordinateur est une machine qui ne tolère que peu l'approximation. Si vous oubliez de mettre une majuscule ou un point, il à fort à parier que l'humain qui vous relira comprendra tout de même ce que vous voulez dire. En revanche, en programmation, si vous transgressez une règle du langage (même une petite sans faire exprès), l'ordinateur ne va pas aimer du tout et va vous montrer qu'il ne comprend pas avec un bon gros message d'erreur. Dans le cadre du Ruby, on dit également qu'il va « lever une exception ». Cette expression est assez employée et je risque de la réutiliser moi-même, c'est pour cela que je vous la donne. Cependant, n'attendez pas de moi que je vous explique le mécanisme des exceptions maintenant ; dans l'état actuel de vos connaissances, ce serait du suicide. Pour en revenir à la syntaxe, ce genre d'erreur est assez fréquent chez les programmeurs débutants, notamment dans des langages comme le C qui ont une syntaxe très stricte. Vous verrez que le Ruby est plutôt souple sur ce point. C'est un avantage car cela nous évite bien des erreurs, mais c'est aussi un inconvénient car cela peut parfois gêner la bonne compréhension d'un code. Heureusement, je vous montrerai quelques astuces pour palier ce problème.

Bien, il est temps de voir où on écrit du code Ruby. Dans RPG Maker, il y a deux endroits distincts avec chacun leur fonction. Tout d'abord, il y a l'éditeur de scripts, celui que vous redoutez tant, mais que vous allez apprendre à adorer (sans rire !) puis il y a la commande « Script » dans les événements. Vous devez la connaître également, c'est sans doute l'une des seules que vous ne savez pas utiliser. Rassurez-vous, nous allons apprendre à nous servir de ces deux outils. L'éditeur est celui des deux dans lequel nous allons passer le plus de temps. C'est simple, c'est lui qui permet d'écrire des scripts, il possède d'ailleurs plusieurs outils bien pratiques comme la coloration syntaxique (le code est coloré pour que l'on s'y repère plus facilement), l'indentation automatique (il y a des tabulations automatiques pour que l'on puisse repérer plus facilement les blocs de codes), la recherche dans plusieurs scripts (très très pratique)... Certains scripts que nous écrirons seront activés automatiquement par le programme. Le script de combat, par exemple, le programme sait qu'il doit l'appeler à chaque fois que l'on démarre un combat, pas besoin de lui dire explicitement « active ce script ». En revanche, mettons que nous codions un script de mini-jeu. Il n'y a pas de commande dans les événements qui dit « démarrer un mini-jeu ». Il faudra donc dire au programme quand il faut appeler ce script, et il faudra le lui dire avec une ou plusieurs petites lignes de Ruby. C'est à ça que sert la commande « Script » des événements.

Bon, c'en est fini de ces deux chapitres un peu théoriques. J'espère que vous ne vous sentez pas assommés par trop d'explications. Il n'est pas nécessaire de tout retenir (il y a quand même des choses importantes, notamment ce que j'ai dit dans le dernier paragraphe, ça il faut que vous le sachiez, dussiez-vous l'imprimer, le coller en poster dans votre chambre et le répéter par cœur tous les jours). Je me suis quelque peu éloigné du sujet principal, je l'admets volontiers, mais comme je vous l'ai dit, mon but n'est pas que de vous apprendre le Ruby, mais également de vous introduire un petit peu un monde que vous ne connaissez peut-être pas. J'espère que cela vous aura un peu intéressé.
Dans le prochain chapitre, nous allons (enfin !) commencer à faire un peu de Ruby.



Chapitre 3 : Afficher un message à l'écran

Quand on commence un nouveau langage de programmation, il est d'usage que les premières lignes écrites soient celles qui permettent d'afficher « Hello world! » à l'écran (c'est une tradition !). D'ailleurs, dans beaucoup de logiciels de développement, le code de base que le logiciel donne à la création d'un nouveau projet est celui-ci. Ceci permet de vérifier de manière très simple que la « traduction » puis l’exécution du code se feront correctement sur notre machine. Cela permet également de comparer les différents langages entre eux, et c'est ce que nous allons faire !

Voici un premier exemple en... Assembleur x86 !


Code:
section .data    ; Variables initialisées
        Buffer:           db 'Hello world !', 10    ; En ascii, 10 = '\n'. La virgule sert à concaténer les chaînes
        BufferSize:     equ $-Buffer    ; Taille de la chaîne
 
section .text    ; Le code source est écrit dans cette section
        global _start     ; Définition de l'entrée du programme
 
_start:    ; Entrée du programme
 
       mov eax, 4    ; Appel de sys_write
        mov ebx, 1    ; Sortie standard STDOUT
        mov ecx, Buffer    ; Chaîne à afficher
        mov edx, BufferSize    ; Taille de la chaîne
        int 80h    ; Interruption du kernel
 
       mov eax, 1    ; Appel de sys_exit
        mov ebx, 0    ; Code de retour
        int 80h    ; Interruption du kernel


(Merci wikipédia.) Comme vous le voyez, c'est un peu compliqué : on manipule les registres directement (eax, ebx... sont sont des noms de registres, c'est-à-dire la mémoire interne du processeur), on doit utiliser les interruptions systèmes... Enfin bref, c'est un sacré bordel.

Voici la même chose en C :
Code:

#include <stdio.h>

int main ()
{
 printf("Hello world!");
 return 0;
}



C'est un peu plus digeste. Je ne vais pas tout détailler, on n'est pas dans un cours de C, mais globalement, on inclut les fonctionnalités nécessaires (stdio.h), on définit le point d'entrée du programme (l'endroit d'où il démarre), main, puis on utilise printf qui permet d'afficher du texte.

Et enfin, voici exactement le même programme en Ruby :


Code:
puts("Hello world!")



Oui. C'est tout. Vous voyez maintenant pourquoi le Ruby est haut-niveau. Il suffit d'une seule ligne de code pour une chose aussi simple que d'afficher du texte là où il en faut cinq au C et une quinzaine à l'assembleur.

Bien, maintenant, ouvrez votre éditeur de scripts, insérez une nouvelle ligne dans l'arborescence à gauche à l'aide du clic droit et nommez ce nouveau script comme vous le voulez. (Il s'appelle « Test » pour ma part, mais nul doute que vous saurez trouver plus original.) C'est dans ce script que nous allons commencer notre apprentissage.

Sachez que le RGSS lit les scripts de haut en bas, il termine donc par le script « Main ». Ce script est le point d'entrée du jeu, c'est là que le jeu commence. Tout ce qui est avant « prépare le terrain » pour que l'exécution puisse se faire correctement. Toutes les lignes de code doivent donc être écrite dans un script qui est au-dessus du script Main, sinon elles ne seront prises en compte qu'après la fin du jeu. Et si vous demandez à Ruby d'écrire du texte à la fin du jeu, la fenêtre se fermera tellement vite que vous ne pourrez pas le voir. Donc, on demandera à Ruby d'afficher du texte avant le début du jeu, comme ça on ne perdra pas de temps.

Faisons donc cela ! Dans votre script nouvellement créé, entrez la ligne qui permet d'afficher du texte :

Code:
puts("Hello world!")

puis démarrez votre jeu.

Votre jeu se lance et puis rien ne s'affiche... Tiens. Aurais-je oublier de mentionner quelque chose ? C'est bien possible... Ah oui ! La méthode puts (qui permet d'afficher du texte) utilise ce que l'on appelle la sortie standard. La sortie standard (aussi appelé console) c'est une sorte de petite boîte noire avec du texte blanc qui n'est pas sans rappeler l'informatique des années 50. Pour l'activer dans RPG Maker, menu « Jeu » → « Afficher la console ». Maintenant démarrez à nouveau votre jeu, la console devrait s'afficher et dedans, vous devriez lire votre premier message ! Félicitations !

Ruby/RGSS ou la puissance cachée de RPG Maker 1390247036-console
Votre premier script !

Mais comment se fait-il que cette ligne affiche du texte ? puts est ce que l'on appelle une méthode (c'est plus ou moins l'équivalent d'une fonction dans d'autres langages comme le C), c'est une sorte de sous-programme. Les programmeurs qui ont conçu le Ruby ont écrit plusieurs lignes de code qui permettent d'afficher du texte à l'écran puis ils ont rassemblé ces lignes de code sous le nom de puts. Comme ça, tout ceux qui veulent maintenant afficher du texte à l'écran n'ont plus à réécrire toutes ces lignes de code, mais ils n'ont qu'à utiliser puts ! C'est malin, vous ne trouvez pas ? Eh bien c'est un peu la philosophie de tous les programmeurs : regrouper le maximum de lignes de code sous forme de méthodes / fonctions pour ne pas avoir à tout réécrire à chaque fois. Plus tard, je vous montrerai même comment créer vos propres méthodes.

Cependant, les programmeurs qui ont conçu le Ruby ont beau être très doués, ils ne pouvaient pas deviner ce que vous alliez vouloir afficher. C'est pour cela qu'il y a les parenthèses : entre les parenthèses, on donne à la méthode ce dont elle a besoin pour travailler. Ces objets que l'on passe à une méthode pour qu'elle travaille dessus s’appellent des paramètres. Retenez bien ce mot, je m'en resservirai. Ici notre paramètre, c'est du texte. Seulement, en programmation, le texte, on appelle cela une chaîne de caractères. Encore un nom barbare à retenir. Et les guillemets autour de cette chaîne de caractères permettent de la délimiter, ils sont obligatoires !

Je vois d'ici vos têtes déçues. Vous auriez voulu créer un beau message dans une jolie fenêtre et tout ce que je vous ai montré c'est comment écrire dans la console. Et pourtant tous les débutants de quasiment tous les langages de programmation de la Terre commencent par la console. C'est un outil extrêmement puissant (surtout sur les systèmes d'exploitation plus évolués comme Linux, dans lequel la console permet de faire énormément de choses !) et vous serez sans doute amenés à vous en servir pour déboguer vos scripts les plus complexes (bon, on n'en est pas encore là). Toujours pas convaincu ?...

Bon. Je vais vous présenter un nouvelle méthode alors : msgbox. Celle-ci s'utilise exactement de la même manière que puts. Remplacez donc
Code:
puts("Hello world!")

par
Code:
msgbox("Hello world!")

et lancez votre programme. Grâce à cette nouvelle méthode, vous allez pouvoir afficher un message directement dans le jeu grâce à une sorte de petite fenêtre popup qui va s'ouvrir avant l'écran titre. C'est ce genre de fenêtre que Ruby utilise pour vous signaler une erreur, vous serez donc sans doute amenés à la rencontrer de nouveau.

Ruby/RGSS ou la puissance cachée de RPG Maker 1390247186-msgbox
La fameuse message box.

Bien sûr, je pense que ce que vous attendiez réellement, c'est un moyen d'écrire du texte dans une fenêtre de message « normale » de RPG Maker, la même que celle que l'on utilise en sélectionnant l'option « Afficher un message » de l'éditeur d'événements. Allez, comme je suis de bonne humeur, voici la ligne qui permet cela :

Code:
$game_message.add("Hello world!")



Si vous remplacez la ligne de msgbox par cette ligne et que vous lancez le jeu, RGSS va lever une exception. Vous ne comprendrez forcément tout de suite le détail de l'erreur qui s'affiche, mais ça viendra. Je vais tout de même vous donner une indication. « $game_message » est le nom de l'objet qui gère les messages dans RPG Maker. « add » est le nom de la méthode appartenant à l'objet susmentionné (oui, une méthode peut appartenir à un objet, nous en reparlerons) qui permet d'ajouter un nouveau message. Enfin, le point entre les deux permet d'accéder à une méthode d'un objet. Autrement dit, on accède à la méthode add de l'objet $game_message et on lui passe notre chaîne de caractères en paramètre. Si vous avez compris la phrase précédente dans son intégralité, vous êtes sur la bonne voie. Sinon, n'hésitez pas à retourner en arrière pour relire les passages qui vous semblent un peu obscurs et si jamais ces difficultés persistent, posez la question !

La raison pour laquelle l'appel à cette méthode ne fonctionne pas est simple : au moment où nous essayons de l'appeler, l'objet $game_message n'a pas encore été initialisé, on ne peut donc pas l'utiliser. En effet, $game_message est initialisé après le début du script Main et avant l'affichage de l'écran titre. Il existe un moyen d'afficher un message avec cette méthode avant l'écran titre, mais cela nécessite de modifier le fonctionnement des scripts déjà existants et je ne vous ai pas encore montré comment le faire proprement. Nous pourrions également définir notre propre fenêtre et l'initialiser correctement avant le début du script Main pour afficher notre texte, mais ça, je ne vous montrerai pas comment faire. Enfin pas maintenant. Ce serait mettre la charrue avant les bœufs.

Il existe tout de même une façon pour vous de voir l'effet de cette méthode : c'est d'utiliser un appel de script à partir des événements. Créez un nouvel événement sur votre map puis choisissez le bouton « Script » et enfin entrez la ligne que je vous ai donnée. Démarrez votre jeu, remplissez les conditions de démarrage de votre événement (appuyez sur la touche Entrée si vous n'avez rien changé) et vous devriez voir votre message s'afficher. L'intérêt peut paraître relativement minime dans la mesure où vous auriez eu exactement le même effet en utilisant le bouton dédié à l'affichage de texte. Cependant, sachez que cette méthode, contrairement à l'utilisation du bouton dédié, vous permettra de visualiser correctement le résultat des futurs codes que nous allons écrire, c'est pourquoi je vous l'ai montrée. Par contre, il est vrai qu'elle a l'inconvénient de nécessiter l'entrée dans le jeu, inconvénient que ne présentent pas puts ou msgbox.

Ruby/RGSS ou la puissance cachée de RPG Maker 1390247399-message
Enfin un vrai beau message !

Je ne peux pas choisir à votre place quelle méthode d'affichage vous voulez utiliser, je vous en ai montré trois, à vous de décider. Cependant, je ne saurais que trop vous conseiller l'une des deux premières car, même si elles sont moins esthétiques, elles ne nécessitent que d'appuyer sur la flèche verte (ou F12) pour lancer le jeu. Nous allons faire beaucoup beaucoup de tests, et afficher du texte sera l'un des moyens principaux que nous allons utiliser pour voir si ce que nous faisons fonctionne correctement ou pas. À vous de voir, mais il se peut que vous en ayez vite assez de devoir lancer le jeu à chaque fois.

Ce sera tout pour ce chapitre. Dans le suivant, nous allons nous attaquer à un concept très important : les variables. Vous connaissez déjà le terme puisque RPG Maker l'utilise, mais vous verrez que les variables en Ruby sont un outil bien plus puissant.


Dernière édition par Ekron le Dim 26 Jan 2014 - 16:19, édité 5 fois
Spytje
Spytje
Administrateur

Nombre de messages : 5935
Localisation : La terre
Distinction : Spiraliste [Korn']
Forestia : Projet du mois juillet 2014
Papy Pulkigrat [Yama']
Date d'inscription : 16/03/2008

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Mer 8 Jan 2014 - 22:46
Intéressant vraiment, très bien expliqué et logique, merci pour ton tutoriel, j'attends la suite avec impatience !
Ewaldar
Ewaldar
Membre

Nombre de messages : 1386
Age : 30
Localisation : Suisse
Distinction : aucune
Date d'inscription : 29/12/2011
http://ewaldar.wixsite.com/les-ames-perdues

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Jeu 9 Jan 2014 - 17:23
Ruby/RGSS ou la puissance cachée de RPG Maker 354280 Ruby/RGSS ou la puissance cachée de RPG Maker 354280 Ruby/RGSS ou la puissance cachée de RPG Maker 354280 Ruby/RGSS ou la puissance cachée de RPG Maker 354280 

Non franchement, c'est du super boulot ! As-tu pensé à l'insérer sur le site du zéro, je suis sûr qu'il aurait un certain succès, et tu pourrais te faire aider dans ton travail également.
Ekron
Ekron
Membre

Nombre de messages : 89
Localisation : Paris
Distinction : aucune
Date d'inscription : 30/12/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 13 Jan 2014 - 18:25
spywaretof > Merci beaucoup !

XtremeViper > Merci à toi aussi ! Concernant le site du zéro (devenu OpenClassrooms depuis) je trouve leurs nouvelles conditions d'édition relativement déplorables, ceci ajouté au fait que le nouveau système de rédaction se fait toujours attendre depuis plus d'un an et qu'il y a peu de communauté pour RPG Maker, je ne suis pas persuadé que ce soit une bonne idée de publier mon tutoriel là-bas. Je suis cependant flatté que tu y aies songé.



Chapitre 4 : Les variables

Avant d'entrer dans le vif du sujet, je voulais juste faire une petite parenthèse sur autre chose : les commentaires. Si vous avez déjà étudié un peu des scripts écrits par d'autres, pour les inclure dans votre projet par exemple, vous avez sans doute déjà dû remarquer ces lignes que l'éditeur de scripts colore en vert. Ces lignes ne font rien, en fait elles sont ignorées par l'interpréteur. Elles sont là pour donner des indications aux personnes qui vont lire le code, et, croyez-moi, c'est très pratique. Il est important de bien commenter ses codes, tout d'abord pour vous : si vous voulez relire un code que vous avez écrit il y a plusieurs mois ou années, vous serez bien content d'avoir des commentaires pour vous guider, mais également pour les autres : si vous partagez votre script, les commentaires permettront aux initiés de comprendre ce que font les lignes que vous avez écrites sans avoir à passer du temps à analyser votre code, et ils permettront d'indiquer à ceux qui veulent juste utiliser votre script comment ils doivent l'installer, le configurer et l'utiliser.

Il existe deux types de commentaires : le commentaire monoligne et le commentaire multiligne. Pour le commentaire monoligne, il suffit de faire précéder votre commentaire d'un #, comme ceci :
Code:
Ceci n'est pas un commentaire
# Ceci est un commentaire
Ceci n'est pas un commentaire
Ainsi, tout la ligne après le # sera ignorée, mais la ligne au-dessus et la ligne en dessous seront bien interprétées. Un commentaire multiligne commence avec « =begin » et se termine avec « =end ». Tout ce que sera entre ces deux mots-clés sera ignoré :
Code:
Ceci n'est pas un commentaire
=begin Cette ligne est un commentaire
Celle-ci aussi

Celle-là aussi
=end
Celle là n'en est plus un
Voilà, ce sera tout pour cette fonctionnalité bien utile.

Bien, il est temps d'aborder le sujet principal du chapitre : les variables. Vous savez déjà ce qu'est une variable puisque vous les utilisez avec RPG Maker. Une variable c'est une information que l'ordinateur retient pour que l'on puisse l'utiliser plus tard. Ça peut être le nom du héros, son nombre de point de vie, ce qu'il a mangé le midi, etc. L'important c'est que l'ordinateur stocke une information... quelque part.

Savez-vous où est ce quelque part ? Non ? Dans ce cas, nous allons faire un petit aparté sur la mémoire de l'ordinateur. Cela vous servira plus tard si vous essayez de comprendre comment fonctionne Ruby à l'intérieur (c'est passionnant mais assez compliqué) et puis un peu de culture harware ne peut pas vous faire de mal. (Pour ceux qui ne le savent pas, le hardware désigne la partie physique d'un ordinateur, ses composants donc, en opposition au software qui désigne la partie logicielle.)

Un ordinateur possède plusieurs types de mémoire, mais parmi ces types, il y en a deux qui vont nous intéresser vraiment : le disque dur et la mémoire vive (RAM). Ils ont chacun leurs caractéristiques :
- la mémoire vive est très rapide mais elle s'efface quand on arrête l'ordinateur, les ordinateurs en possèdent en général plusieurs Go ;
- le disque dur est beaucoup moins rapide (même s'il y a beaucoup de progrès avec les SSD pour ceux qui connaissent) mais il présente l'avantage de ne pas perdre les informations à l'extinction, les ordinateurs en possèdent facilement plusieurs centaines de Go voire quelques To.
Pour faire du stockage permanent, comme un fichier de sauvegarde de jeu ou un document Word (ce sont des choses que l'on veut pouvoir retrouver si on redémarre l'ordinateur), on est obligés d'utiliser le disque dur. En revanche, pour faire du stockage temporaire, pour retenir une donnée dont on a besoin uniquement pendant l'exécution d'un programme, on a le choix. Et on va choisir en priorité la mémoire vive car elle est très rapide (environ un million de fois plus rapide que le disque dur, ça peut varier en fonction du type de disque dur et de mémoire vive, mais c'est un bon ordre de grandeur).

Ruby/RGSS ou la puissance cachée de RPG Maker 1390247702-barrette-ram-grande
Une barrette de RAM.

Ruby/RGSS ou la puissance cachée de RPG Maker 1390247758-logo-disque-dur
Un disque dur vu de l'intérieur.

Pour stocker nos variables, nous allons donc les mettre dans la mémoire vive. La mémoire vive est une sorte de gigantesque (plus ou moins gigantesque en fonction de la quantité dont vous disposez) tableau à deux colonnes : une colonne d'adresse et une colonne contenant la valeur. La valeur, c'est nous qui la choisissons et l'adresse nous sert à savoir où on la met. En effet, si on n'avait pas l'adresse où est stockée notre valeur, on ne saurait pas où aller la chercher ! La mauvaise nouvelle c'est que les adresses sont un peu compliquées à retenir, elles ressemblent à ça : 0x2F7D231A. La bonne nouvelle c'est qu'on s'en fiche vu qu'on n'a pas à les retenir. À la place de mémoriser les adresses où sont stockées nos variables, on va donner un nom à ces variables et RGSS fera le lien entre le nom et l'adresse. C'est pas magnifique ?

La question est maintenant de savoir ce qu'on peut mettre dans une variable. Eh bien... À peu près tout : du texte, des nombres, des tableaux... En fait, on peut y mettre des objets. Les objets sont une notion centrale dans Ruby car la philosophie de ce langage est « tout est objet ». Les entiers sont des objets, les nombres à virgule sont des objets, les chaînes de caractères sont des objets, les classes, les méthodes, les tableaux... Tout ça, ce sont des objets. Et donc, tout ça on peut les mettre dans une variable. Bien entendu, la notion d'objet est encore abstraite pour vous, mais nous l'étudierons en détails plus tard car c'est d'une importance capitale. Et pour donner une valeur à une variable, on fait comme ceci :
Code:
variable = valeur

Attention, le code ci-dessus ne veut pas dire que variable est égal à valeur ! Il veut dire que variable prend la valeur de valeur et devient égal à valeur. La nuance est très importante, car nous verrons plus tard un autre signe qui permet de savoir si deux valeurs sont égales. Bien sûr, si vous écrivez ceci et que vous lancez votre jeu, Ruby va lever une exception car valeur ne renvoie à rien.

Étudions d'un peu plus près les objets classiques de Ruby. Tout d'abord, nous avons le nombre entier, son nom en Ruby est Integer (pour les anglophobes, c'est simplement la traduction anglaise de « entier »). Un nombre entier, c'est tout simplement un nombre, positif ou négatif, qui ne possède pas de partie décimale. Pour mettre un nombre entier dans une variable, c'est on ne peut plus simple :
Code:
entier = 5
Notre variable vaut maintenant 5 !

Dans la ligne de code juste au-dessus, en réalité, on a fait deux opérations d'un coup. La première chose c'est que l'on a créé une variable appelée « entier », on a donc dit à RGSS de nous réserver un peu d'espace en mémoire et de nous permettre d'y accéder en écrivant « entier ». Dans un deuxième temps, nous avons également mis la valeur cinq dans la variable et ainsi inscrit cinq dans la case mémoire qui avait été réservée pour nous. Ces deux opérations portent un nom :
- on a tout d'abord déclaré une variable que l'on a appelé « entier » ;
- puis on affecté la valeur 5 à cette variable.
Comme on a déclaré et affecté en même temps, on peut résumer le tout en disant que l'on a initialisé la variable « entier » à 5.

Ce qu'il faut bien comprendre, c'est que, maintenant, on peut utiliser notre variable comme on utiliserait la valeur qu'elle contient. Par exemple, écrire
Code:
puts(entier)
revient strictement à écrire
Code:
puts(5)
(Pas de guillemets parce qu'on n'affiche pas à chaîne de caractères mais une variable puis un entier.)

Et on peut faire des calculs avec notre variable. On compte traditionnellement cinq opérations mathématiques de base : l'addition, la soustraction, la multiplication, la division et la modulo. Nul doute que vous connaissez très bien les quatre premières, mais qu'en est-il de la dernière ? Eh bien le modulo c'est tout simplement le reste de la division entière. Par exemple, cinq modulo deux donne un parce que lorsque l'on divise cinq par deux, le quotient entier est deux et il reste un. Voici quelques exemples d'opérations :
Code:
puts(2 + 3) # Addition : affichera 5
puts(7 – 12) # Soustraction : affichera -5
puts(4 * 3) # Multiplication : affichera 12
puts(24 / 3) # Division : affichera 8
puts(7 % 3) # Modulo : affichera 1

Moins utile mais également disponible, vous avez la puissance :
Code:
puts (2 ** 10) # Affichera 1024, soit deux exposant dix

Bien entendu, on peut très bien déclarer une variable comme étant le résultat d'une opération :
Code:
resultat = 3 * 7 + 5 / 3 # resultat vaudra 23 car Ruby respecte la priorité des opérateurs et la multiplication et la division se font avant l'addition
Enfin, il est bien entendu possible de faire des opérations avec des variables directement.

Ruby/RGSS ou la puissance cachée de RPG Maker 1390248595-irb1
Je vous présente irb (interactive ruby), un outil très pratique qui interprète les commandes Ruby que l'on tape dans le terminal (le truc violet, c'est un terminal). Comme ça vous pouvez voir les commandes que je tape et le résultat directement. Notez d'ailleurs que je n'étais pas obligé d'utiliser puts puisque irb m'affiche la valeur de chaque variable, mais avec RPG Maker on doit l'utiliser si on veut voir la valeur d'une variable. (La raison pour laquelle l'appel à puts affiche 52 et nil est un peu compliquée et je ne voudrais pas vous embrouiller, donc on va dire pour simplifier que nil indique la fin de l'instruction puts, ce qui n'est pas faux dans l'absolu.)
Je ré-utiliserai irb de temps en temps pour que vous puissiez voir que je ne raconte pas que des bêtises, c'est un outil extrêmement pratique pour apprendre et comprendre le comportement du langage.

Maintenant, essayons ceci :
Code:
resultat = 7 / 2
puts(resultat)
Vous vous dites certainement que mon exemple est stupide et que c'est évident que ça va afficher 3,5. Très bien, essayez-donc. Non sérieusement, allez-y !

Alors ? Convaincu ? Si tout s'est bien passé, la méthode puts a dû vous afficher 3 et non 3,5 comme vous l'attendiez. Rassurez-vous, c'est normal (je ne vous l'aurais pas fait faire sinon) et ce n'est pas que Ruby ne sait pas compter. En fait, pour lui, comme vous divisez deux nombres entiers, le résultat est forcément un entier lui aussi. Or, 3,5 n'étant pas un entier, Ruby le tronque pour ne garder que la partie entière. Ceci explique cela. En fait, l'opérateur / se comporte comme une division entière quand on lui donne deux entiers. Ainsi, avec la division entière et le modulo, nous sommes capables de reconstituer parfaitement le résultat d'une division euclidienne. C'est d'ailleurs ce que nous allons faire ! Je veux que vous me codiez un programme qui définit deux nombres entiers et qui affiche ensuite « nombre1 = nombre2 * quotient + reste ». Allez, au travail !

La solution est simple :
Code:
nombre1 = 8
nombre2 = 3
print(nombre1)
print(" = ")
print(nombre2)
print(" * ")
print(nombre1 / nombre2)
print(" + ")
print(nombre1 % nombre2)

print a la même utilité que puts à ceci près qu'il ne revient pas à la ligne à chaque fin d'instruction, on peut donc tout écrire sur une seule ligne. Cependant, c'est un peu pénible de devoir écrire print 7 fois, mais heureusement, je vous montrerai un peu plus loin dans le chapitre comment condenser ces 7 lignes en une seule.

Maintenant, mettons que j'aie un PNJ dans mon jeu et qu'à chaque fois que mon héros lui parle, je souhaite augmenter la valeur d'une variable de 1. On pourrait très bien faire ça en événements d'ailleurs. Eh bien, profitons-en ! Puisque nous pouvons le faire en événements simples, faisons-le (enfin faites-le) ! Comme vous devez savoir faire, je n'ai même pas besoin de vous dire quoi que ce soit. En admettant que la variable utilisée soit la numéro 1 et qu'elle s'appelle « Test » (oui, je fais toujours l'effort de choisir des noms très originaux), vous devriez voir ceci :
Code:
Variable : [0001:test] += 1

Savez-vous ce que signifie ce « += » ? Cela signifie « ajouter 1 à la variable test et enregistrer le résultat dans la variable test ». C'est l'équivalent de cette ligne en Ruby :
Code:
test = test + 1

Eh bien, grande nouvelle, cet opérateur est également disponible en Ruby ! Vous pouvez donc parfaitement écrire :
Code:
test += 1
Cet opérateur permet de faire deux choses d'un seul coup : addition puis ré-affectation. Si on n'avait pas mis le égal, on n'aurait eu que l'addition, autrement dit, on aurait bien ajouté 1 à la valeur de test, mais on n'aurait pas « sauvegardé » le résultat dans test. C'est assez logique quand on y pense, puisque quand on fait :
Code:
nombre1 = nombre2 + 1
On veut changer la valeur de nombre1 mais pas celle de nombre2, par conséquent, quand on fait
Code:
nombre2 + 1
on ne veut pas toucher à la valeur de nombre2.

Deuxième grande nouvelle, cet opérateur est disponible pour toutes les opérations que nous avons vues précédemment :
Code:
test = 0 # test vaut 0
test += 3 #test vaut 3
test *= 7 #test vaut 21
test -= 4 # test vaut 17
test /= 3 # test vaut 5
test %= 3 # test vaut 2
test **= 4 # test vaut 16
Dans d'autres langages, on dispose également des opérateurs ++ (incrémentation) et -- (décrémentation) qui permettent de, respectivement, augmenter la valeur d'une variable de 1 et diminuer la valeur d'une variable de 1 (on dit aussi incrémenter une variable et décrémenter une variable). Cependant, ils n'existent pas en Ruby. La raison c'est que Ruby utilise d'autres moyens pour gérer la majorité des cas dans lesquels on pourrait en avoir besoin. Dans le reste des cas, on a toujours += 1 qui est strictement équivalent. Je vous le dis pour que vous ne soyez pas surpris, si vous voyez ces opérateurs en action dans d'autres langages, de ne pas voir cette technique utilisée en Ruby.

Bref, la question qui reste en suspend c'est : comment faire si je veux obtenir un résultat décimal dans ma division ? Eh bien il suffit de ne pas utiliser un nombre entier, mais un nombre réel. En programmation, c'est ce que l'on appelle des float et c'est justement ce que je voulais vous présenter ! Avant cela, il est toutefois nécessaire que j'attire votre attention sur un détail. Vous avez très certainement remarqué que le Ruby (comme la quasi-totalité des langages de programmation existants) est plutôt proche de l'anglais. Eh bien la notation des nombres décimal ne fait pas exception et diffère quelque peu de notre bonne vieille notation à la française. En effet, là où nous écririons 3,5 avec une virgule pour séparer la partie entière de la partie décimale, nos amis anglophones écriraient 3.5 avec un point à la place de la virgule. En fait si vous mettez une virgule, vous n'aurez pas d'erreur... Mais l'effet obtenu sera bien différent de l'effet escompté : vous créerez en fait ce que l'on appelle un Array, chose que nous étudierons un peu plus tard.

Pour créer un float, c'est donc très simple :
Code:
monFloat = 3.5
puts(monFloat) # Affichera 3.5

Maintenant, vous pouvez faire de vraies divisions :
Code:
nombre1 = 2.75
nombre2 = 0.5
puts (nombre1 / nombre2) # Affichera 5.5

Cependant, l'utilisation des float ne permet toujours pas de diviser 7 par 2 puisqu'ils restent deux nombres entiers et le résultat de leur division sera un entier. Il existe une méthode permettant de transformer un nombre entier en nombre réel, nous verrons cela quand nous parlerons de transtypage. Mais il existe également une façon de faire bien plus simple : pour que Ruby sache que nous voulons un résultat réel, il suffit de lui dire que nous travaillons avec deux nombres réels et il faut donc leur ajouter une partie décimale. Or, dire qu'ils n'ont pas de partie décimale revient à dire que leur partie décimale est égale à 0. Pour ceux qui n'auraient pas encore compris, voici comment faire :
Code:
puts (7.0 / 2.0) # Affichera 3.5
Il suffit de leur rajouter une partie décimale nulle, ainsi, on ne modifie pas le nombre et on fait comprendre à Ruby que ce sont des réels. En fait, il suffit simplement que l'un des deux nombres soit un réel pour que Ruby vous donne un résultat réel :
Code:
puts (7.0 / 2)
et
Code:
puts(7 / 2.0)
afficheront également 3.5 comme résultat.

Les opérateur +, -, *, /, % et ** sont également disponibles pour les float et fonctionnent de la même manière. Même chose pour leurs formes raccourcies (+=, -=, *=, /=,%= et **=).

Les float ne présentent pas de difficulté particulière, aussi, je vous propose de passer à la suite. Nous allons parler d'un type que vous connaissez au moins de nom puisque j'en ai déjà parlé très brièvement : les booléens. Les booléens sont l'équivalent en programmation de ce que vous appelez les interrupteurs sur RPG Maker, c'est-à-dire qu'ils ne peuvent contenir que deux valeurs : on ou off. En informatique, on utilise plutôt vrai ou faux, et comme on est en anglais, nos booléens pourront valoir true ou false. Leur déclaration est on ne peut plus simple :
Code:
boolean1 = true
boolean2 = false
Leur usage est globalement le même que celui des interrupteurs. Par exemple, dès que vous allez vouloir activer / désactiver une fonctionnalité vous allez utiliser un booléen pour mémoriser l'état de cette fonctionnalité. Les booléens vont également avoir une utilité importante quand nous parlerons des conditions (prochain chapitre, si tout va bien). Il n'y a pas grand-chose à signaler sur eux, si ce n'est que l'on peut également les afficher avec puts :
Code:
boolean = true
puts(boolean) # Affichera true

Bien, passons maintenant à la partie que je juge la plus intéressante. Vous les connaissez, vous les attendiez et le moment est enfin venu : nous allons parler des chaînes de caractères ! Une chaîne de caractères, c'est tout simplement du texte, comme je vous l'ai expliqué. Quand on passe une chaîne de caractères à une méthode, comme puts, on l'entoure de guillemets pour la délimiter ; eh bien quand on assigne une chaîne de caractères à une variable, c'est pareil :
Code:
maChaine = "Plein de texte."
puts(maChaine) # Affiche Plein de texte.

Notez bien sûr que lorsque l'on affiche la chaîne de caractères contenue dans une variable, on ne met pas de guillemets, comme pour tous les autres types de variables. Si on mettait des guillemets, ce ne serait plus une variable mais une chaîne de caractères, donc on afficherait « maChaine » au lieu de « Plein de texte. » (Si vous avez compris ça, vous avez tout compris !)

Les chaînes de caractères sont compatibles avec les opérateurs + et * (et leur forme raccourcie respective). L'opérateur + nécessite deux chaînes de caractères et il va rajouter la deuxième à la fin de la première :
Code:
chaine1 = "Salut !"
chaine2 = "Comment ça va ?"
chaine3 = chaine1 + " " + chaine2
puts(chaine3) # Affichera Salut ! Comment ça va ?
Cette opération, qui consiste à rajouter une chaîne à la fin d'une autre s'appelle la concaténation. Comme vous pouvez le constater, on peut faire plusieurs concaténations en une fois. Ici, je rajoute une espace entre les deux chaînes de façon à ce qu'elles ne soient pas collées. Il est cependant nécessaire que les objets concaténés soient des chaînes de caractères : on ne peut pas ajouter un entier à la fin d'une chaîne de caractères. (Notez que la concaténation fonctionne aussi et exactement de la même façon avec l'opérateur <<).

L'opérateur * nécessite une chaîne de caractères et un entier (on ne multiplie pas une chaîne de caractères par une autre, ça n'a pas de sens). Si on « multiplie » notre chaîne par un entier n, elle sera répétée n fois. Exemple :
Code:
chaine = "Coucou ! "
puts (chaine * 3) # Affichera Coucou ! Coucou ! Coucou !

Un peu plut tôt, nous avons fait un exercice avec affichage du quotient et du reste d'une division entière. Nous avons pour cela utilisé plusieurs lignes de print, ce qui est plutôt pénible. Je vous avais dit que je vous montrerai comment faire pour éviter cela et c'est ce que je vais faire. Pour insérer une variable qui n'est pas une chaîne de caractères dans une chaîne de caractères, on utilise ceci :
Code:
#{variable}

Exemple :

Ruby/RGSS ou la puissance cachée de RPG Maker 1390249200-irb2
Le retour d'irb qui m'aide à prouver mes dires !

Reprenez l'exemple sur la division euclidienne et améliorez-le avec ce que vous venez d'apprendre. Vous devriez obtenir quelque chose de similaire à ceci :
Code:
nombre1 = 8
nombre2 = 3
puts("#{nombre1} = #{nombre2} * #{nombre1 / nombre2} + #{nombre1 / nombre2}")
Beaucoup plus concis, vous ne trouvez pas ?

Il existe également un moyen de faire ceci en utilisant la concaténation. Je vous ai dit qu'on ne pouvait concaténer que des chaînes de caractères entre elles, et je maintiens mon propos. Il nous faut donc transformer nos entiers / flottants / booléens / autres en chaînes de caractères, et pour cela, on utilise le transtypage.

Le transtypage (ou cast en anglais) est une opération qui consiste à transformer le type d'un objet : à transformer un entier en une chaîne de caractères par exemple, pour que celle-ci puisse être concaténée. En Ruby, le transtypage est très simple : pour les objets qui existent déjà, en général une méthode a été créée pour vous simplifier la tâche. (Pour les objets que nous créerons, nous devrons le faire nous-même, mais nous verrons cela en temps utile.)

Les transtypages les plus utiles sont :
- d'un entier / flottant / booléen vers une chaîne de caractères, avec .to_s() ;
- d'un entier vers un flottant avec .to_f() ;
- d'un flottant vers un entier avec .to_i().

Les plus observateurs d'entre vous auront remarqué les points avant les noms des méthodes que nous allons utiliser : en effet, ce sont des méthodes qui appartiennent à des objets. Comme je vous l'ai dit, en Ruby, tout est objet. Les entiers, les flottants, les chaînes de caractères et les booléens sont des objets. À partir de là, rien de bien étonnant à ce qu'ils aient des méthodes. C'est assez particulier, mais en Ruby on peut très bien écrire ce genre de choses :
Code:
puts (7.to_f() / 2)
Et cette ligne affichera 3.5 car nous avons transformé 7 en flottant en utilisant la méthode .to_f() (7 est un objet !) avant de le diviser par 2. Flottant / entier = flottant. Bien entendu, dans ce cas précis, il est plus rapide d'écrire 7.0, la forme décimale. D'ailleurs, faites attention, quand on écrit 7.0 on ne fait pas appel à la méthode .0 sur l'objet 7 ! La confusion peut venir du fait que quand on appelle une méthode sans paramètre, les parenthèses sont facultatives, c''est-à-dire que l'on pourrait très bien écrire :
Code:
puts(7.to_f / 2)
Ça fonctionnerait tout aussi bien. Je les utilise pour ma part par habitude et par souci de clarté : je sais que j'appelle une méthode ainsi. (Je ne vous impose pas de faire de même.) Mais du coup, attention ! 7.0 n'est pas un appel de méthode, c'est juste la notation de la forme décimale !

Revenons un peu au sujet original, à savoir la concaténation. Nous savons désormais que nous pouvons concaténer un nombre en le transformant en chaînes de caractères avec .to_s(). Donc, nous pouvons réécrire notre programme de division euclidienne comme suit :
Code:
nombre1 = 8
nombre2 = 3
puts(nombre1.to_s + " = " + nombre2.to_s + " * " + (nombre1 / nombre2).to_s + " + " + (nombre1 % nombre2).to_s)
Voilà, c'est simplement une autre méthode pour écrire la même chose. Méthode qui aura eu le mérite de nécessiter l'introduction du transtypage (une notion importante). Vous pouvez choisir la méthode que vous préférez, vous pouvez même utiliser les deux. Pour ma part, si vous voulez savoir (si vous ne voulez pas savoir, fermez les yeux), je préfère la concaténation, simple question d'habitude. Il y a donc de fortes chances que ce soit elle que j'utilise en majorité dans la suite de ce tutoriel, mais cela ne doit pas vous empêcher d'utiliser l'autre si vous préférez.

Je vous ai dit qu'en Ruby tout était objet, y compris les entiers, les flottants, les chaînes de caractères et les booléens, soit les quatre objets que nous avons étudié dans ce chapitre. Étant des objets, ils ont des méthodes, dont les méthodes de transtypage font partie, mais ils ont aussi d'autres méthodes. Nous allons en voir quelques-unes.

Les booléens possèdent très peu de méthodes et aucune qui soit susceptible de nous intéresser. Les entiers possèdent quelques méthodes intéressantes :
Code:
entier.abs()
Retourne la valeur absolue du nombre.
Code:
entier1.gcd(entier2)
Retourne le PGCD de entier1 et entier2.
Code:
entier1.lcm(entier2)
Retourne le PPCM de entier1 et entier2.
Code:
entier1.round(précision)
Arrondira le nombre en fonction de la précision. Étant donné que les entiers ne présentent pas de décimale, on pourrait penser que cette méthode est inutile, mais ce qui est amusant, c'est que l'on peut donner une précision négative qui indiquera ainsi à la fonction d'arrondir la partie entière, exemple :
Code:
puts(57.round(-1)) # Affichera 60

C'est à peu près tout ce que l'on peut dire sur les entiers. Rien de bien bouleversant. Pour les flottants, vous retrouvez les même méthodes que pour les entiers plus quelques-unes :
Code:
flottant.ceil()
Arrondit le nombre à l'entier supérieur.
Code:
flottant.floor()
L'inverse de ceil(), arrondit le nombre à l'entier inférieur.
Il existe également une méthode qui s'appelle truncate() et qui permet de tronquer le flottant pour en faire un entier, mais to_i() a déjà exactement le même comportement.

Il semblerait que les méthodes des flottants ne présentent guère plus d'intérêt. Nous allons maintenant regarder d'un plus près celles qui concernent les chaînes de caractères, et vous allez voir que là, il y a des choses intéressantes.
Code:
chaine.capitalize()
Retourne la même chaîne avec une majuscule au premier caractère (si c'est une lettre) et le reste en minuscule (utile pour un nom de héros qu'il faudrait saisir par exemple).
Code:
chaine.downcase()
Retourne la même chaîne avec les lettres toutes minuscules.
Code:
chaine.gsub("chaine1", "chaine2")
Cherche toutes les occurrences de "chaine1" dans la chaîne et les remplace par "chaine2". Exemple : Je me suis trompé, au lieu d'écrire « Salut les jeunes ! » j'ai écrit « Salut les jaunes ! ». La solution évidente consisterait à utiliser gsub pour remplacer le a par un e :
Code:
puts("Salut les jaunes !".gsub("a", "e")) # Affichera Selut les jeunes !
Problème : gsub remplace toutes les occurrences. La bonne façon de faire c'est d'utiliser un groupe de lettres unique dans la chaîne :
Code:
puts("Salut les jaunes !".gsub("au", "eu")) # Affichera Salut les jeunes !
Notez que les deux chaînes (celle que l'on remplace et celle par laquelle on remplace) ne sont pas nécessairement de la même taille. gsub est une fonction qui accepte également en premier paramètre ce que l'on appelle les expressions régulières (regexp) qui font toute sa puissance. C'est un concept un peu compliqué et nous le reverrons bien plus tard si j'ai le courage d'aller jusque là.
Code:
chaine.insert(entier, "chaîne")
Insert la chaîne précisée en deuxième paramètre juste après le caractère numéro X où X est passé en premier paramètre. Exemples :
Code:
puts("abd".insert(2, "c")) # Affichera abcd
puts("bdc".insert(0, "a")) # Affichera abcd

Code:
chaine.lenght()
Retourne la taille de la chaîne. (La méthode size() agit de la même manière.)
Code:
chaine.reverse()
Inverse l'odre des caractères de la chaîne (le premier se retrouve dernier, le deuxième avant-dernier, etc.).
Code:
chaine.swapcase()
Transforme les minuscules en majuscules et les majuscules en minuscules.
Code:
chaine.upcase()
Retourne la même chaîne toute en majuscules.

Bien sûr, il y en a que je vous donne et qui n'ont pas un intérêt évident, mais des méthodes comme lenght(), gsub() ou insert() sont parfois très pratiques, souvenez vous-en.

Je vous dirais bien que nous allons terminer sur une note plus joyeuse, mais il faut encore que je vous parle de quelque chose et ce n'est pas forcément ce qu'il y a de plus simple. Nous allons voir comme nommer nos variables (très important, en Ruby en particulier). En Ruby, le nom d'une variable doit être composé de caractères alphanumériques (des chiffres ou des lettres) auquel on ajoute le caractère underscore (« _ », aussi appelé « tiret du 8 »). Cependant, une variable doit toujours commencer par une lettre minuscule ou un underscore. Essayez de donner des noms pertinents à vos variables comme « vitesse », « mana », etc. et non « x » ou « y ». Il peut arriver que le nom que l'on souhaite donner à une variable soit composé de plusieurs mots (c'est même une bonne chose, ça montre qu'il est précis !) comme « vitesse bateau moteur », or les espaces sont interdites dans les noms de variables. Pour cela, deux écoles s'affrontent :
- vitesse_bateau_moteur
- vitesseBateauMoteur
Choisissez la forme que vous préférez, pour ma part, on m'a presque obligé à utiliser la seconde pendant mes cours d'info, donc ne vous étonnez pas de la voir fréquemment dans la suite du tutoriel.

Si jamais vous nommez une variable avec un nom commençant par une majuscule, celle-ci deviendra une constante. Une constante, comme son nom l'indique, c'est une variable dont la valeur ne pourra pas changer. Si jamais vous essayez de changer la valeur de votre constante au cours de l'exécution, RGSS lèvera une exception. Les constantes sont assez utilisées pour certaines valeurs que vous ne voulez surtout pas changer (le nombre maximum de sorts que peut apprendre votre héros par exemple).
Code:
MaxSortsHeros = 100
...
MaxSortsHeros += 1 # PAF ! Erreur !

Jusque là, c'était plutôt simple, mais sachez également que la façon dont on nomme une variable à une incidence sur la portée de cette variable. La portée d'une variable c'est l'ensemble dans endroits du programme dans lesquels on peut l'utiliser. Les variables que l'on crée depuis le début du chapitre (avec les règles que je vous ai énoncées ci-dessus) sont dites locales. Les règles concernant les variables locales sont un peu compliquées en Ruby (et je ne voudrais pas vous embrouiller avec des notions que je ne sais même pas si j'aborderai), donc je vais simplifier. Une variable locale n'existe que dans la méthode, la classe ou le module dans lequel ou laquelle elle a été définie (ce sont des choses que nous reverrons plus tard). Si elle a été définie en dehors de toute classe, méthode ou module (ce que nous avons fait jusqu'à présent), alors elle est valable partout sauf dans les classes, les méthodes et les modules. (Il y a d'autres structures que ces trois-là qui limitent l'usage des variables locales, mais ce sont les plus connues ; l'utilisation des autres est assez anecdotique.)

Nous avons beaucoup utilisé les variables locales dans ce chapitre et continuerons probablement à les utiliser car notre façon de programmer est encore assez naïve : elle n'est pas structurée. Elle le deviendra à partir de la partie 2 et là nous les utiliserons moins. Quand on utilise une variable locale, il faut faire attention à n'en avoir besoin que le contexte dans lequel elle est définie. Parfois on a besoin d'une variable à plusieurs endroits, dans plusieurs scripts et structures différentes. Dans ce cas, on utilise une variable globale qui s'écrit de la même manière qu'une variable locale à ceci près que l'on rajoute un $ devant :
Code:
$nom = "Alex"

Une variable globale est définie partout, sans exception (après avoir été initialisée, bien sûr). Sachant cela, on peut se demander l'intérêt des variables locales. C'est simple : imaginons que nous ayons besoin d'une variable à l'intérieur d'une méthode, mais uniquement à l'intérieur de celle-ci, alors nous allons utiliser une variable locale. Si on fait ça, à la fin de la méthode, Ruby verra que la variable locale n'a plus de raison d'être et il libérera la mémoire qu'une variable globale aurait occupé inutilement. Bien sûr, sur une variable qui ne contient pas grand-chose, la différence sera infime, mais on considère tout de même qu'il s'agit d'une meilleure manière de programmer. Donc non, le fait de connaître les variables globales ne vous dispense pas de réfléchir un minimum à la portée de vos variables. (Pour ceux que le sujet intéresse, le mécanisme qui se charge de libérer la mémoire qui n'est plus utilisée s'appelle le garbage collector ou ramasse-miettes en français et c'est un algorithme très intéressant.)

Il existe deux autres portées de variables en Ruby :
- les attributs ou variables d'instance, avec un @ devant (@variable) ;
- les variables de classe, avec deux @ devant (@@variable).
Cependant, je ne peux pas encore vous dire à quoi servent ces variables et quelle est leur portée précise tant que nous n'avons pas abordé la programmation orientée objet (ce sera pour la deuxième partie).

Bon, il me semble que ce chapitre était assez riche en informations. Résumons ! Une variable permet de stocker une information dans la mémoire vive pour pouvoir la réutiliser lors de l'exécution. Une variable peut contenir n'importe quel objet et parmi ceux-ci, nous avons vu les integer, les float, les boolean (nom anglais des booléens) et les string (nom anglais des chaînes de caractères). Nous avons vu que ces objets possèdent des méthodes, notamment des méthodes de transtypage. Nous avons également vu que la portée d'une variable change en fonction du nom qu'on lui donne.

Si jamais vous n'avez pas tout retenu, ce n'est pas très grave, vous allez apprendre en pratiquant. Par contre, si vous avez l'impression qu'un concept vous échappe, essayez de le relire et de le comprendre. Si ça ne va toujours pas, n'hésitez pas à demander. Comme toujours, si vous repérez un passage que vous jugez mal expliqué, signalez-le moi, ça me permettra de corriger mais également de cerner ce qu'il faut que j'améliore pour les prochains chapitres. En parlant de ça, le prochain chapitre portera normalement sur les conditions.


Dernière édition par Ekron le Lun 20 Jan 2014 - 21:23, édité 1 fois
Ewaldar
Ewaldar
Membre

Nombre de messages : 1386
Age : 30
Localisation : Suisse
Distinction : aucune
Date d'inscription : 29/12/2011
http://ewaldar.wixsite.com/les-ames-perdues

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 13 Jan 2014 - 20:55
Il manque toutefois une chose dans tout cela : des screenshots ! Je pense que cela rebute pas mal de lire tant d'informations, sans avoir un coup de main visuel sous la patte.

Pour le moment, cela reste encore relativement basique, mais dès que tu vas t'attaquer à du plus difficile, ça va être une autre paire de manches.

Ekron
Ekron
Membre

Nombre de messages : 89
Localisation : Paris
Distinction : aucune
Date d'inscription : 30/12/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 13 Jan 2014 - 21:45
J'y avais pensé, mais en dehors des chapitres où j'aborderai la partie graphique du RGSS (partie 3 si je m'en tiens à mon plan), je ne vois très bien quoi prendre en screen... L'éditeur de code ? Le truc c'est que le code, je le donne déjà en écrit... Tu penses que ce serait mieux de le mettre en screen ?

Je pourrais essayer de faire des schémas pour aérer le tout sinon...
Spytje
Spytje
Administrateur

Nombre de messages : 5935
Localisation : La terre
Distinction : Spiraliste [Korn']
Forestia : Projet du mois juillet 2014
Papy Pulkigrat [Yama']
Date d'inscription : 16/03/2008

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 13 Jan 2014 - 21:48
Comme dit mon ami du dessus des screens pour certains seraient pas mal bien que pour l'instant pas vraiment nécessaire.

C'est vraiment du très bon tutoriel que tu nous offre là, un grand merci !

Le Ruby, seul langage informatique utile sur ce forum !

...

HS : Si un modérateur pouvaient passer par ici offrir quelques points pour ce tutoriel, ce serait vraiment bien !
Elisa'
Elisa'
Staffeux retraité

Nombre de messages : 2924
Age : 26
Localisation : Par là-bas !
Distinction : Mon héritière que je chéris Ruby/RGSS ou la puissance cachée de RPG Maker 344805Ruby/RGSS ou la puissance cachée de RPG Maker 344805
[Coco' Smile]
Plus que 2 ans avant d'épouser Coco' ! Compte à rebours lancé !
[Auto-distinction]

Adepte du "Je le savais" alors qu'elle le savait pas.
Date d'inscription : 30/05/2009

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 13 Jan 2014 - 22:51
+15 points de participation pour ce beau tuto, merci à toi !
Ekron
Ekron
Membre

Nombre de messages : 89
Localisation : Paris
Distinction : aucune
Date d'inscription : 30/12/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 20 Jan 2014 - 21:26
spywaretof > Merci, tes commentaires sont très motivants !

Elisa' > Merci à toi aussi !

Comme on me l'a proposé plusieurs fois, j'ai édité en rajoutant des images et j'ai pu en profiter pour introduire irb. Qu'en pensez-vous ? Cela vous parait-il plus clair ? L'introduction à irb vous parait-elle judicieuse ?

Merci pour vos retours ! Smile

Le chapitre 5 avance petit à petit, mais j'ai beaucoup de travail en ce moment...
Spytje
Spytje
Administrateur

Nombre de messages : 5935
Localisation : La terre
Distinction : Spiraliste [Korn']
Forestia : Projet du mois juillet 2014
Papy Pulkigrat [Yama']
Date d'inscription : 16/03/2008

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 20 Jan 2014 - 21:40
C'est très bien comme ça, les images permettront à certains de voir plus clairement ce qui est expliqué.

Vivement le prochain chapitre Smile
Ekron
Ekron
Membre

Nombre de messages : 89
Localisation : Paris
Distinction : aucune
Date d'inscription : 30/12/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 16:17
Merci spywaretof. Smile



Chapitre 5 : Les conditions

Autant vous prévenir, nous allons attaquer le cran supérieur. Cela ne veut pas dire que ce que nous allons voir ici est plus compliqué que ce que nous avons déjà vu, mais nous allons dans ce chapitre (et dans tous les suivants) nous resservir de ce que vous avez appris, en particulier des variables qui sont un concept à maîtriser absolument. (D'autant que, si jamais vous prenait l'envie de développer dans un autre langage, sachez qu'on les retrouve partout !).

Nous allons donc parler un peu des conditions. Quand on veut se la péter un peu, on appelle ça des structures conditionnelles et, au même titre que les boucles que nous verrons au chapitre suivant, elles font partie de ce que l'on appelle les structures de contrôle. Cependant, avant d'entrer dans le vif su sujet, nous allons faire (un tout petit) peu de théorie afin que vous puissiez comprendre au mieux ce qu'il se passe lorsque vous utilisez une condition, cela vous permettrez de vous servir plus efficacement de cette fonctionnalité.

Nous allons faire une petite introduction aux expressions booléennes (si vous êtes observateurs, vous remarquerez sans doute la ressemblance avec les booléens, et ce n'est pas pour rien). Celles-ci appartiennent à une partie des mathématiques qui se nomme l'algèbre de Boole, du nom de l'homme qui l'a inventée (ou découverte selon votre opinion à propos de cet éternel débat). C'est un sujet passionnant que l'on retrouve dans beaucoup de domaines, dont la théorie de l'information (à la base de l'informatique) qui, à partir d'un certain niveau d'abstraction est quasiment entièrement basée là-dessus. Cependant, la construction et les propriétés d'une algèbre dépassent de beaucoup le cadre de ce tutoriel, je n'en parlerai donc pas. L'algèbre de Boole utilise des théorèmes et outils puissants pour simplifier les problèmes de logique formelle ; nous pourrions nous-mêmes utiliser ces outils pour simplifier certaines de nos expressions booléennes. Cependant, c'est un sujet qui nécessiterait un tutoriel à lui seul et qui n'aurait quasiment aucune application dans le Ruby pour RPG Maker, je n'en parlerai donc pas non plus. Pour ceux que cela déçoit, je suis désolé, mais ce tutoriel n'a pas pour but de faire de vous des ingénieurs en informatique qui se doivent de maîtriser parfaitement les concepts algébriques qui se cachent derrière les outils qu'ils utilisent ; il faut bien que je fixe des limites, sinon je ne vais pas m'en sortir...

Bien, maintenant que nous avons clairement défini ce que nous allons étudier et ce que nous allons éviter, il est temps de s'y mettre ! Qu'est-ce qu'une expression booléenne ? Le mot « booléenne », comme vous l'avez sans doute remarqué, se rapporte à « booléen » et un booléen, vous savez ce que c'est. C'est un objet qui peut prendre deux valeurs : true ou false. Une expression, en informatique, c'est tout ce qui peut avoir une valeur. Par exemple, une variable est une expression car elle peut avoir une valeur, l'entier 2 est également une expression car il vaut 2.

Par conséquent, vous êtes capable de deviner ce que signifie « expression booléenne ». C'est tout ce qui peut prendre la valeur true ou la valeur false. Par exemple, « true » est une expression booléenne puisqu'elle vaut bien true ou false. En revanche, le flottant 18.7 n'est pas une expression booléenne car il ne vaut ni true ni false. Vous saisissez ? Il n'y a rien de bien complexe.

Eh bien les expressions sont au cœur des conditions et ce pour une raison très simple. Un branchement conditionnel est un test qui, en fonction de son résultat, amène vers telle ou telle partie du programme ou du script. Or, ce test ne peut prendre que deux valeurs : soit il est vrai soit il est faux. C'est là que l'on retrouve nos fameuses expressions booléennes.

Pour que cette explication ne soit pas que purement théorique, nous allons voir brièvement une première façon d'utiliser les conditions en Ruby (nous verrons les autres plus loin dans le chapitre, ne vous inquiétez pas). La voici en pseudo-code (le pseudo-code est un code non normalisé, proche de notre langue maternelle qui premet d'écrire un premier algorithme indépendant du langage dans lequel il sera implémenté) :
Code:
instruction if test

Si vous vous souvenez de ce que je vous ai dit au début de ce tutoriel, une instruction est un ordre donné à l'ordinateur, comme puts. if est un des mots-clés de Ruby qui permettent d'effectuer un test. Il faut comprendre cette ligne comme une instruction qui ne sera effectué que si le test qui la suit est évalué à true.

Utilisons notre grand ami irb pour voir comment cela fonctionne en pratique :

Ruby/RGSS ou la puissance cachée de RPG Maker 1390746296-irb3

Comme vous pouvez le voir, dans le premier cas, notre test vaut true, donc l'instruction puts("Hello world!") est exécutée. En revanche, dans le deuxième cas, notre test est évalué à false, donc l'instruction ne s'exécute pas.

Un peu plus curieux, cette ligne là :
Code:
puts("Hello world!") if 1

Je vous invite à la tester et vous verrez que l'instruction est bien exécutée. Pourtant, 1 ne vaut ni true ni false alors comment le if fait-il pour savoir ce qu'il doit faire et pourquoi ne plante-t-il pas ? Eh bien en fait, Ruby utilise le transtypage pour transformer la valeur que vous lui avez passé en un booléen. Vous savez déjà ce qu'est le transtypage puisque nous en avons fait, avec la méthode .to_s() par exemple. Ce type de transtypage est appelé transtypage explicite puisque que l'on dit explicitement à Ruby quand il doit transtyper et en quoi à l'aide de l'utilisation de la méthode adéquate. La transtypage qu'utilise if est un transtypage dit implicite, Ruby se charge de tout, sans aucune action de notre part !

Cependant, comment savoir ce que if va considérer comme true et ce qu'il va considérer comme false ? Il existe en fait une règle très simple : les deux seules choses qui valent false pour if sont false lui-même et nil ; tout le reste vaut true. Donc vous pouvez essayer de remplacer mon 1 par n'importe quel autre entier, flottant, chaîne caractères ou quoi que ce soit d'autres, tant que ce n'est pas false ou nil, l'instruction s'exécutera.

Bien, tout cela est très intéressant, mais il reste un problème important : pour l'instant nous ne sommes capables que de conditions statiques. C'est-à-dire que nos conditions utilisent des valeurs fixes, déjà connues lors de l'écriture du script (et qui ne pourront donc pas varier lors de l'exécution). Or, soit ces valeurs sont évaluées à true et l'instruction s'exécute, ce qui reviendrait à ne pas écrire la condition, soit ces valeurs sont évaluées à false et cela revient à ne pas écrire l'instruction complète. L'intérêt est relativement limité.

Cependant, vous vous doutez bien que je ne vous fait pas étudier tout cela pour le simple plaisir d'étaler mes quelques connaissances. Les conditions prennent tout leur intérêt lorsqu'on les utilise de manière dynamique, conjointement avec quelque chose qui bouge, qui varie. Vous l'aurez deviné, je parle bien entendu des variables que nous avons vues au chapitre précédent.

En effet, Ruby est parfaitement capable de traiter une variable dans le if puisque, nous l'avons vu, une variable est une expression. Une fois qu'une variable possède une valeur elle peut être traitée exactement de la même manière que cette valeur, il n'est donc pas étonnant qu'il en aille de même pour les conditions. Je peux donc faire ceci :
Code:
var = true
puts("Ce test est vrai") if var

Ainsi, dans ce cas, le test sera bien effectué puisque notre variable vaut true. L'intérêt ici c'est que la valeur de notre variable peut être modifiée durant notre script et donc que notre ligne réagit en fonction de cela. Un exemple très simple : mettons que nous ayons un booléen nommé « estVivant » qui vaut true si jamais notre héros est toujours vivant et passe à false dès qu'il meurt, alors nous pourrions écrire ceci :
Code:
puts("Vous êtes vivant !") if estVivant
puts("Vous êtes mort...") if !estVivant

Le point d'exclamation devant « estVivant » signifie que l'instruction s'exécutera si la variable est évaluée à false et non si elle est évaluée à true. C'est ce que l'on appelle un opérateur unaire parce qu'à une expres​sion(notre variable) il en associe une autre (sa valeur « opposée », que l'on appelle son complément). Cette opération est appelée « négation », souvent abrégé « NOT ».

L'intérêt de faire cela, c'est de pouvoir vérifier qu'une variable vaut false. Dans l'exemple ci-dessus, dans le cas où on utilise la négation, on veut vérifier que le héros est mort, ce qui revient à dire que le booléen estVivant vaut false. S'il vaut false, grâce à la négation il deviendra true et l'instruction ainsi conditionnée sera bien exécutée. Au contraire, s'il vaut true, la négation le transformera en false et l'instruction ne sera pas exécutée.

Nous pouvons donc utiliser nos conditions sur des variables ! Ces variables sont traitées exactement comme les expressions qu'elles contiennent : utilisées directement si elles sont booléennes, transtypées puis traitées si elles ne le sont pas. Cependant, dans l'état actuel de nos connaissances, des variables autres que des variables booléennes n'ont aucun intérêt dans la mesure où, si elles ne sont pas vides, elles seront systématiquement transtypées en true, quelle que soit leur valeur.

Eh bien bonne nouvelle, il est temps de changer cela. Nous avons vu l'opérateur « ! », mais il en existe d'autres, et c'est ce que nous allons voir.

Le premier opérateur que nous allons voir permet de tester l'égalité entre deux expressions. Vous vous dites certainement que si les concepteurs de Ruby ont eu deux sous de bon sens, cet opérateur doit être « = ». Eh bien, vous avez tout faux ! Tout d'abord, sachez que les concepteurs de Ruby (qui se sont inspirés de nombreux langages de programmation bien antérieurs) ont bien plus de deux sous de bon sens et que s'ils n'ont pas choisi un égal c'est qu'il y a une bonne raison : il est déjà pris ! Eh oui, souvenez-vous, le = est un opérateur d'affectation, or, dans notre condition, nous ne voulons pas faire une affection mais une comparaison. L'opérateur qu'ils ont choisi est « == ».

Non, je n'ai pas bogué sur ma touche égal, il y en a bien deux. Il ne faut surtout pas confondre les deux, le premier affecte l'expression de droite à la variable de gauche et le deuxième compare les deux expressions. Voici un exemple en image :

Ruby/RGSS ou la puissance cachée de RPG Maker 1390746359-irb4

La première chose que je fais est très simple : je mets l'entier 8 dans ma variable. Deuxième ligne, j'utilise une instruction conditionnée, l'instruction ne s'exécute que si la condition est vraie. Or, vous voyez bien que le contenu de ma variable (8 ) est différent de l'expression avec laquelle je la compare (4) et pourtant l'instruction s'exécute. C'est tout simplement parce que je n'ai pas utilisé le bon opérateur. C'est d'ailleurs ce que me dit Ruby avec son warning.

Deuxième instruction conditionnée, j'utilise cette fois-ce le bon opérateur... et pourtant l'instruction de s'exécute toujours pas... Pourquoi à votre avis ? Eh bien simplement parce que plus haut, au lieu d'utiliser == nous avons utilisé =, donc au lieu de comparer notre variable à 4, nous lui avons affecté 4. Notre variable n'est donc plus égale à 8, la condition est donc fausse. En revanche, dans la dernière instruction conditionnée, la condition est vérifiée, donc l'instruction s'exécute. Notez que l'opérateur renverra toujours false si vous lui passez un nombre et une chaîne de caractères, même si le contenu semble le même. Autrement dit, si vous lui passez 8 et "8", il vous renverra false.

Revenons sur un détail... qui n'en est pas vraiment un : la première condition. Je vous ai dit que l'opérateur = ne servait pas à faire des conditions, c'est pour cela que son comportement n'est pas adapté et ne fait pas ce qui est demandé. Mais si l'on y réfléchit quelques secondes, comment se fait-il que l'instruction s'exécute ? Comment se fait-il que cet opérateur d'affectation, dont le seul but est d'affecter une expression à une variable, renvoie quelque chose qui permette à la condition d'être vérifiée ? Eh bien, la vérité sur cet opérateur, c'est qu'il renvoie la valeur qu'on lui dit d'affecter. Exemple :
Code:
variable = 8

Avec cette ligne, non seulement on affecte un 8 à la variable, mais en plus, l'opérateur va retourner la valeur 8, comme si c'était une méthode (ça n'en est pas vraiment une). Cela signifie qu'il est possible d'affecter la valeur retournée à une autre variable, comme ici :
Code:
variable2 = variable = 8

On met la valeur retournée par l'opérateur = dans une autre variable... grâce à un deuxième opérateur égal. Au final, grâce à cette fonctionnalité, on dispose d'une écriture très naturelle qui permet d'affecter une même valeur à plusieurs variables en une ligne. Le plus beau c'est que le deuxième opérateur =, celui que l'on utilise pour affecter à notre deuxième variable la valeur retournée par le premier =, eh bien lui aussi retourne une valeur. La valeur qu'il a affecté, et cette valeur, c'est la valeur retournée par le premier =, donc 8 ! Cela signifie que l'on peut mettre une troisième égal qui affectera la valeur retournée par le deuxième et qui lui-même retournera une valeur que l'on pourra affecter grâce à un quatrième égal, etc. Impressionnant, n'est-ce pas ? C'est tout la philosophie de Ruby, le but du langage n'est pas foncièrement d'être simple à utiliser (même s'il l'est) mais de ressembler le plus possible au langage naturel (l'anglais), et c'est quelque chose qu'il fait particulièrement bien, nous aurons l'occasion d'en reparler.

Bien, revenons à nos moutons. Notre opérateur == a un joli petit nom : il fait partie des opérateurs binaires. Je vous ai déjà parlé de ! qui lui faisait partie des opérateurs unaires. Je vous ai aussi dit qu'on l'appelait comme ça parce qu'à une expres​sion(l'expression sur laquelle on l'applique) il en donné une autre (le complément de son transtypage en booléen). Eh bien un opérateur binaire, ça n'a rien à voir avec le « langage binaire ». Ils sont ainsi nommés parce que à deux expressions (celles qu'on leur passe en paramètre), il en associent une autre. Cette autre, c'est le résultat du test qu'on leur demande de faire, ce résultat peut être true si le test est vrai ou false si le test est faux. Ce résultat est donc un booléen qui peut ensuite directement être utilisé par le if. Regardez ce code :

Code:
variable = 8
puts("Hello world !") if variable == 8

En interne, l'opérateur == va faire son travail, vérifier que la condition est correcte, renvoyer true, if va voir qu'on lui donne true et donc autoriser l'instruction à s'exécuter. Tout ça, vous le savez parce que j'ai insisté sur le fonctionnement de cette mécanique (étant persuadé que ça peut vous aider à mieux comprendre et penser vos codes) mais, mettons que vous ne le sachiez pas. D'un œil extérieur, si on ne sait pas ce qu'il se passe en profondeur mais qu'on essaye de comprendre le code, on voit que l'on affichera du texte à l'écran si notre variable est égale à 8. Donc, sans avoir besoin de comprendre ou de se préoccuper de ce qu'il se passe vraiment, on est parfaitement capables de comprendre la syntaxe de Ruby qui montre une fois de plus à quel point elle est naturelle.

Mine de rien, nous avons pas mal avancé. Je vais vous présenter une nouvelle méthode. Celle-ci n'est jamais utilisée dans les scripts de RPG Maker parce qu'elle nécessite la console pour fonctionner, mais elle va nous permettre de comprendre facilement tout l'intérêt des opérateurs. Cette méthode s'appelle « gets », elle permet de récupérer du texte entré au clavier par l'utilisateur dans la console pour le stocker dans une variable et l'utiliser ensuite. Elle fonctionne de cette manière :

Code:
variable = gets()
#variable contient maintenant la chaîne de caractères tapée par l'utilisateur

Maintenant que vous savez cela, nous allons faire un petit exercice. Créer une variable contenant votre âge, puis demandez à l'utilisateur son âge. Si jamais celui-ci est le même que le vôtre, dites-le lui !

En réfléchissant un peu, vous devriez être capable de coder ce petit script sans problème. Voici une solution :
Code:
monAge = 19
puts("Quel est votre âge ?")
ageUser = gets().to_i()
puts("Nous avons le même âge !") if monAge == ageUser

Les deux premières lignes sont très simples : je crée une variable avec mon age puis j'affiche du texte pour demander le sien à l'utilisateur. La troisième ligne, c'est l'utilisation de gets() pour récupérer l'âge demandé, mais il y a une petit subtilité : le to_i(). En effet, je vous ai dit que gets() retournait une chaîne de caractères (et ce, même si l'utilisateur a tapé un chiffre), ce qui signifie qu'il faut la transtyper pour pouvoir la comparer car, comme je vous l'ai dit, on ne peut pas comparer un nombre et une chaîne de caractères. Puis, ensuite, à la dernière ligne, j'utilise une instruction conditionnée. Notez que j'aurais pas effectuer la transtypage directement dans la condition au lieu de le faire au moment de gets(). C'est à vous de choisir, mais, pour ma part, vu que ce que l'on récupère est un âge (et donc une donnée numérique), j'ai trouvé plus logique de la convertir en nombre dès le départ.

Bon, voilà un aperçu de la véritable puissance des conditions. Et, vous n'avez encore rien vu. Nous allons commencer par élargir vos possibilités en matière d'opérateur. Par exemple, il serait très intéressant, dans notre exemple précédent d'afficher un message au cas où l'utilisateur n'ait pas le même âge que vous. Si vous êtes un peu malin, vous devriez penser à ceci :
Code:
monAge = 19
puts("Quel est votre âge ?")
ageUser = gets().to_i()
puts("Nous avons le même âge !") if monAge == ageUser
puts("Nous n'avons pas le même âge. :(") if !(monAge == ageUser)

Les quatre premières lignes sont exactement les mêmes, comme vous pouvez le constater. La dernière, en revanche, est intéressante. À l'exception du texte, tout semble parfaitement identique à la précédente. Regardez-mieux. Oui, là ! Il y un point d'exclamation, ce point d'exclamation que vous connaissez déjà très bien et qui signifie négation. Or, si on fait une négation de l'opérateur d'égalité, on obtient un opérateur d'inégalité ! En effet, souvenez-vous que l'opérateur d'égalité retourne une expression booléenne et la négation va inverser cette expression. Ainsi, si l'égalité est vérifiée, le true retourné devient false et l'instruction ne s'exécute pas. En revanche, si l'égalité n'est pas vérifiée, le false retourné devient true et l'instruction s'exécute. Et c'est exactement le comportement que nous attendions.

Il existe cependant un moyen plus simple que ne nécessite pas de faire joujou avec les expressions booléennes : nous avons à disposition en ruby un opérateur d'inégalité et celui se note « != ». Si on l'utilisait dans la dernière ligne de notre script précédent, ça donnerait ceci :
Code:
puts("Nous n'avons pas le même âge. :(") if monAge != ageUser

Ceci aurait exactement le même comportement que la ligne telle qu'elle était avant, mais l'utilisation de cet opérateur rend la ligne plus claire.

Nous disposons également de quatre autres opérateurs, « > », « >= », « < », « <= », qui permettent de tester, respectivement :
- qu'une variable est strictement supérieure à une autre ;
- qu'une variable est supérieure ou égale à une autre ;
- qu'une variable est strictement inférieure à une autre ;
- qu'une variable est inférieure ou égale à une autre.

Modifions un peu notre script pour utiliser quelques-uns de ces opérateurs :
Code:
monAge = 19
puts("Quel est votre âge ?")
ageUser = gets().to_i()
puts("Nous avons le même âge !") if monAge == ageUser
puts("Vous êtes plus jeune que moi.") if monAge > ageUser
puts("Vous êtes plus vieux que moi.") if monAge < ageUser

Comme vous pouvez le constater, ils s'utilisent également de la même manière que l'opérateur d'égalité.

C'est à peu près tout ce que nous pouvions voir pour les opérateurs binaires de comparaison (en réalité, il en existe un autre qui est assez intéressant, c'est l'opérateur « <=> », il ressemble au signe mathématique de l'implication, mais ce n'est pas tout à fait cela ; son usage est assez spécifique, nous le reverrons plus tard). Cependant, il existe d'autres opérateurs binaires qui sont très utiles. Commençons par un exemple. Nous récupérons l'âge de notre utilisateur et le comparons au nôtre, très bien. Il pourrait être intéressant de faire de même avec son prénom. Si l'âge et le prénom sont les mêmes, c'est une sacrée coïncidence, si l'âge ou le prénom sont identiques, on a au moins une chose en commun, en revanche, si rien n'est pareil, on n'a rien en commun. On voit bien que l'on va devoir combiner des conditions : dans la première, on veut vérifier que l'âge ET le prénom sont identiques aux nôtres, dans la seconde que l'âge OU le prénom sont identiques aux nôtres et dans la dernière que l'âge ET le prénom sont différents des nôtres. Eh bien, ça tombe bien, il existe des opérateurs binaires qui permettent de combiner les conditions :
- l'opérateur qui permet de vérifier que deux conditions sont vraies est l'opérateur ET, en Ruby on le note && (pour info, le caractère « & » est souvent appelé « et commercial » mais son nom savant est  « esperluette ») ;
- l'opérateur qui permet de vérifier qu'au moins l'une des deux conditions est vraie est l'opérateur OU, en Ruby il se note || (sur les claviers français, Alt Gr + 6 deux fois).

Bien, codons tout cela !
Code:
monAge = 19
monPrenom = "Guillaume"
puts("Quel est vôtre âge ?")
ageUser = gets().to_i()
puts("Quel est votre prénom ?")
prenomUser = gets().chomp()
puts("Nous avons le même prénom et le même âge, quelle coïncidence !") if monAge == ageUser && monPrenom = prenomUser
puts("Nous avons au moins une chose en commun.") if monAge == ageUser || monPrenom = prenomUser
puts("Nous n'avons rien en commun...") if monAge != ageUser && monPrenom != prenomUser

Voilà un petit script qui commence à devenir intéressant !
Les cinq premières lignes, vous maîtrisez ! La sixième, vous devez pouvoir deviner ce qu'elle fait facilement, mais il est possible que vous ne connaissiez pas la méthode chomp(). Quand vous utilisez le méthode gets(), vous invitez l’utilisateur à saisir une chaîne de caractères et l'utilisateur valide la saisie de la chaîne par un appui sur la touche entrée. Or, la touche entrée produit un retour à la ligne, les concepteurs de Ruby ont donc décidé d'inclure un retour à la ligne à la fin de chaque chaîne de caractères saisie avec gets() afin de reproduire le comportement de la touche entrée. Le problème, c'est que dans la chaîne de caractères que nous avons remplie dans la script avec notre prénom, il n'y a pas de retour à la ligne, donc même si les deux prénoms sont les mêmes, les chaînes ne pourront jamais être égales. La méthode chomp(), comme vous l'aurez sans doute compris, permet de retirer le retour à la ligne à la fin de la chaîne de caractères que retourne gets(). Pour information, le caractère de retour à la ligne est « \n ». Bien sûr, il est composé de deux caractères usuels puisqu'on n'a pas sur le clavier de caractère spécifique pour le retour à la ligne.

Mais ce qui va vraiment nous intéresser, ce sont les trois dernières lignes. Dans la première, vous pouvez voir l'opérateur && en action : on veut vérifier que les deux conditions sont correctes. Dans la deuxième, c'est l'opérateur || qui est utilisé, on veut vérifier qu'au moins l'une des deux est correcte. Enfin, dans la dernière, on a une utilisation combinée de && et de !, parce que l'on veut vérifier que les deux sont faux. Notez que cette dernière ligne aurait également pu s'écrire de cette manière :
Code:
puts("Nous n'avons rien en commun...") if !(monAge == ageUser || monPrenom == prenomUser)

Ici, on vérifie simplement qu'il n'y pas au moins un des deux qui soit vrai, ce qui revient à dire que les deux sont faux. Pour passer de l'une à l'autre des deux formes, on utilise le théorème de De Morgan, un théorème fondamental de l'algèbre de Boole. Ne vous inquiétez pas cependant, la connaissance de ces outils est loin d'être essentielle pour du scripting RGSS, mais n'hésitez pas à vous renseigner si le domaine vous intéresse.

Si vous avez fait attention à ce que j'écris (et j'espère que c'est bien le cas !), vous avez dû remarquer que lorsque j'explique ce que fait l'opérateur ||, je dis qu'il va vérifier qu'au moins l'un des deux tests soit correct, mais jamais qu'il va vérifier que le premier test ou le second est correct. Il y a une raison à cela, et cette raison c'est qu'il y a un décalage entre le « ou » au sens mathématique strict et le « ou » tel que les profanes (c'est comme ça que j'appelle les hérétiques qui ne font pas de maths) l'utilisent. Le « ou » mathématique est basiquement un ou dit inclusif. C'est-à-dire qu'il est considéré comme vrai si l'une des deux expressions qu'il évalue est vraie ou bien si les deux sont vraies. C'est également le sens de l'opérateur || en Ruby et c'est pour cela que j'emploie l'expression « au moins un des deux » car ça peut être les deux en même temps. En revanche, dans le langage courant, quand on vous dit que vous pouvez prendre les pâtes ou la pizza, vous ne pouvez pas prendre les deux ! C'est ce que l'on appelle un ou exclusif : c'est l'un ou l'autre mais jamais les deux en même temps. En mathématiques, pour le ou exclusif, on dit « ou bien ». Donc si on veut éviter qu'un client fasse le malin, on lui dire qu'il peut prendre les pâtes ou bien la pizza.

Si vous avez testé la double égalité dans notre précédent script, vous avez dû vous apercevoir qu'il y a une incohérence assez ennuyeuse : l'instruction du milieu est également exécutée alors qu'on ne voulait pas que ce soit le cas. Ceci est lié à ce que je viens de vous raconter, le || de Ruby est un ou inclusif, c'est-à-dire que si les deux expressions testées sont vraies, il renverra true. Or, ce n'est pas ce que nous voulions, nous voulons un ou exclusif. La première solution est d'utiliser ce que nous connaissons déjà pour interdire le cas où les deux sont égaux :
Code:
puts("Nous avons au moins une chose en commun.") if (monAge == ageUser || monPrenom = prenomUser) && !(monAge == ageUser && monPrenom == prenomUser)

Les parenthèses servent à bien délimiter les blocs conditionnels : on effectue d'abord ce qu'il y a dans les parenthèses. Ici, on a repris la condition de la ligne au-dessus et on a mis un point d'exclamation devant pour signifier qu'on ne voulait pas que ce soit correct. Ceci dit, c'est un peu long et pénible à écrire. Ce qui serait vraiment génial, c'est qu'il existe un opérateur ou exclusif. Eh bien vous n'allez pas me croire... Oui ! Il existe ! C'est l'opérateur « ^ » (accent circonflexe). Sous Windows, vous devez appuyer deux fois sur la touche de l'accent circonflexe, puis pour une raison inconnue, il vous en met deux d'un coup, donc il faut en effacer un. Sous Linux, en revanche, il vous suffit d'appuyer deux fois sur la touche, et comme il est plus intelligemment conçu, il ne vous en mettra qu'un (non, ceci n'est pas un troll). On peut donc remplacer la ligne précédente par ceci :
Code:
puts("Nous avons au moins une chose en commun.") if (monAge == ageUser) ^ (monPrenom == prenomUser)

N'oubliez pas les parenthèses ce coup-ci sinon Ruby va lever une exception.

Il existe cependant une troisième solution encore plus pratique, mais vous ne pouvez pas la deviner car nous ne l'avons pas vue. C'est de dire, « si les âges et les prénoms sont les mêmes, faire ça, sinon si au moins l'un des deux test est vrai, faire ça, sinon, faire ça ». Ainsi, la deuxième et la troisième condition dépendent de la première, si la première est vérifiée, Ruby n'ira pas voir les deux autres. En revanche, si la première, n'est pas vérifiée, il va descendre à la deuxième. Là, il va vérifier qu'au moins l'un des deux tests est vrai, mais comme on sait déjà que les deux ne sont pas vrais en même temps (sinon on ne serait pas là), on ne rencontrera pas le problème précédent. Puis, dans le cas où les deux conditions sont fausses, on n'en fait pas de troisième (ce serait faire perdre son temps à Ruby) mais on affiche directement que rien ne correspond.

Ce type de montage conditionnel n'est pas compatible avec les conditions que nous avons vues. Les conditions que nous avons vues (le if en fin de ligne) sont appelées « conditions inline », c'est-à-dire qu'elles ne s'appliquent que sur une seule ligne. Les conditions que nous allons voir maintenant sont dites « conditions block » car elles s'appliquent sur un bloc de lignes. Le problème c'est de bien distinguer les lignes qui sont affectées par la condition et celles qui ne le sont pas ; mais vous allez voir que Ruby a tout prévu !

Pour utiliser une condition block, c'est comme ceci :
Code:
# Instructions avant la condition
if machin1 == machin2
 # Instructions qui s'exécutent si la condition est vraie
 # Là aussi
 # ...
 # Et là pareil
end # Fin de la condition
# Instruction après la condition

Si vous voulez écrire une instruction sur la même ligne que la condition, vous devez utiliser le mot-clé « then », comme ceci :
Code:
if true then puts("Eh oui, true est toujours vrai !") end

On peut également l'employer quand il y a un retour à la ligne, mais comme dans ce cas il est facultatif, je préfère m'en passer, je trouve que l'indentation (le fait de décaler les lignes à l'intérieur du bloc de conditions pour bien voir qu'elles en font partie) est tout aussi clair.

Ce qui est intéressant avec ce modèle de condition, c'est qu'il est possible de dire à Ruby d'exécuter des instructions si la condition est fausse :
Code:
if machin1 == machin2
 # instructions si la condition est vraie
else
 # Instructions si la condition est fausse
end

Pas besoin de remettre une condition après le else, Ruby a compris qu'il devait l'exécuter dès que la condition du if est fausse. Autant vous avertir tout de suite, il existe plusieurs manières de noter les conditions et vous êtes susceptibles de rencontrer les deux. La première, c'est un peu la méthode « à l'ancienne », héritée du C (c'est celle que j'utilise). La deuxième c'est celle-ci :

Code:
if machin1 == machin2
 then # Instructions si la condition est vraie
 else # Instructions si la condition est fausse
end

Certains auteurs (ceux qui ont écrit l'article de Wikipédia pour ne pas les citer) considèrent la deuxième façon de faire comme étant plus lisible... Ce n'est pas mon cas. À mes yeux, ils s'encombrent d'un « then » inutile et, surtout, ils indentent le « else » et le mettent au même niveau que le « then ». Je trouve que le fait de décaler ainsi le « else » par rapport au « if » donne la fausse impression que l'exécution du else est sujette à l'exécution du if alors que c'est tout l'inverse. Pour moi, comme en C, le else doit avoir le même niveau hiérarchique que le if. Ceci dit, vous êtes libre d'adopter la forme que vous préférez.

Enfin, il existe également un moyen d'utiliser des conditions intermédiaires, le fameux « sinon si ». Un « sinon si » s'exécutera si le test qui lui est associé est vrai et si tous les tests de toutes les conditions de son bloc conditionnel qui sont avant lui sont faux. En Ruby, « sinon si » se dit « elsif » et ça s'écrit comme ça :
Code:
if machin1 == machin2
 # Instructions si le premier test est vrai
elsif machin1 == machin3
 # Instructions si le deuxième test est vrai et que le premier est faux
elsif machin2 == machin3
 # Instruction si le troisième test est vrai et que les deux premiers sont faux
else
 # Instructions si tous les tests précédents sont faux
end

Notez que le « end » se situe systématiquement à la fin du bloc conditionnel, quel que soit son nombre d'éléments. Dans un bloc conditionnel, on a toujours un if, parfois un else (mais jamais plusieurs) et entre zéro et une infinité de elsif. On peut en mettre autant qu'on veut.

Si l'on devait réécrire notre exemple précédent avec ce que nous venons de voir, ça donnerait ceci :
Code:
monAge = 19
monPrenom = "Guillaume"
puts("Quel est vôtre âge ?")
ageUser = gets().to_i()
puts("Quel est votre prénom ?")
prenomUser = gets().chomp()

if (monAge == ageUser && monPrenom == prenomUser)
 puts("Nous avons le même âge et le même prénom, quelle coïncidence !")
elsif (monAge == ageUser || monPrenom == prenomUser)
 puts("Nous avons au moins une chose en commun")
else
 puts("Nous n'avons rien en commun")
end

Alors oui, c'est un peu plus long, mais c'est largement plus clair, vous ne trouvez pas ?

On notera également la présence du mot-clé « unless » (pour ma part, je ne l'utilise quasiment jamais, question d'habitude) pas mal utilisé dans les scripts de RPG Maker. C'est en quelque sorte l'inverse du if. Les instructions soumises à un if s'exécutent si la condition est vraie, les instructions soumises à un unless s'exécutent sauf si la condition est vraie. Exemple :
Code:
unless age >= 18
 pus("Tu n'es pas majeur.")
end
Il est également possible d'utiliser unless dans une condition inline.

Il nous reste une dernière chose à voir afin d'en avoir (enfin) fini avec ce chapitre. Il s'agit d'une forme assez particulière de condition (mais utile tout de même). Mettons que vous proposiez un questionnaire à vos joueurs, noté sur 20. À chaque note vous voulez associer un commentaire différent, vous devrez donc faire un if et dix-neuf elsif avec à chacun une condition du style
Code:
elsif note == x
 puts("Commentaire")

Ce serait relativement pénible, vous ne trouvez pas ? Heureusement, il existe un moyen de raccourcir tout cela : le case when ! (C'est l'équivalent du « switch case » dans des langages comme le C.) Il s'utilise de cette manière :
Code:
# On suppose que la variable note existe et qu'elle contient la note
case note
 when 0
 puts("Eh ben... T'as tout loupé !")
 
when 1
 puts("T'es pas totalement nul, mais pas loin.")

 when 2
 puts("Y'a de l'idée... Non j'rigole !")

 when 3
 puts("3 fautes ! Ah non... 3 points.")

 when 4
puts("T'es pas loin d'avoir la moitié d'une note à peine correcte.")

 when 5
 puts("T'as la moyenne... de la moyenne")

 # etc.

 when 20
 puts("Tout simplement parfait !")

 else
 puts("Tu as une note qui n'est pas entre 0 et 20... C'est pas commun pour un questionnaire noté sur 20.")
end

L'idée c'est que l'on donne au case le nom de la variable que l'on veut tester (note ici) puis ensuite, avec des when, on liste tous les cas possibles et on écrit une ou plusieurs instructions qui correspondent à ces cas. Enfin, on peut utiliser le else peut gérer tous les cas qu'on n'aurait pas écrits. Et on n'oublie pas le end !

Bien sûr, en pratique, pour associer une note avec son commentaire, on ne ferait pas du tout ça : ce n'est pas pratique, ce n'est pas bien pensé et ce n'est pas évolutif. Cependant, avant de savoir bien coder, il faut déjà apprendre à coder.

Ce sera tout pour ce chapitre. Dans le prochain, nous allons parler des boucles.
Korndor
Korndor
Staffeux retraité

Nombre de messages : 4959
Age : 110
Localisation : Erem Vehyx
Distinction : Champion de boxe et au lit ! :O [Wax]
Être Mythique [Mister]
Papi Korndor qui a l'ostéoporose [Skillo]
Soldat Ikéa [Coco']
Un bonhomme, un vrai ! [Neresis]
Vieillard acariâtre [Didier Gustin]
Date d'inscription : 16/12/2007
http://www.rpgmakervx-fr.com/

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 16:25
Excellent (et tres long) tutoriel, en plus tu mets des images d'Ubuntu, ca vaut bien quelques points de participation ! Wink

+5 points pour toi, jeune ami !

- Korndor
Spytje
Spytje
Administrateur

Nombre de messages : 5935
Localisation : La terre
Distinction : Spiraliste [Korn']
Forestia : Projet du mois juillet 2014
Papy Pulkigrat [Yama']
Date d'inscription : 16/03/2008

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 16:32
Wow de la lecture intéressante merci, vraiment merci !
Ewaldar
Ewaldar
Membre

Nombre de messages : 1386
Age : 30
Localisation : Suisse
Distinction : aucune
Date d'inscription : 29/12/2011
http://ewaldar.wixsite.com/les-ames-perdues

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 16:32
C'est plus digeste avec un peu de mise en page et quelques screen Wink

En tout cas, toujours au top, ça me donne envie de m'essayer à de la prog de niveau plus difficile !
SegFault
SegFault
Membre

Nombre de messages : 79
Age : 30
Localisation : Paris
Distinction : aucune
Date d'inscription : 26/04/2013

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 17:34
Oui Korndor, vive Ubuntu ! Personnellement, je suis plus habitué à FreeBSD, mais Ubuntu c'est quand même vachement joli Very Happy
velvetwizard
velvetwizard
Membre

Nombre de messages : 12
Age : 29
Localisation : quelque part entre la table et la chaise
Distinction : aucune
Date d'inscription : 28/12/2012

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Dim 26 Jan 2014 - 22:19
Merci pour le Tutoriel Ekron  Smile Il est super !!!!
Vivement la suite.
moh
moh
Membre

Nombre de messages : 28
Age : 31
Localisation : Roubaix
Distinction : aucune
Date d'inscription : 24/02/2014

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Ven 28 Fév 2014 - 2:13
Sérieusement meilleur tuto que j'ai eu. J'ai suivi des cours de ruby que je n'ai pas continué dû à ma compréhension un peu décourageante mais tu m'a redonné espoir !

En lisant chaque ligne j'en apprend plus, j'ai l'impression que tu m'apprends à voler à haute altitude tellement que pour moi c'était impossible de me faire comprendre ça.

J'ai hâte d'en apprendre plus, j'attend donc tes prochains chapitres.


Dernière édition par moh le Mer 5 Mar 2014 - 23:56, édité 2 fois
moh
moh
Membre

Nombre de messages : 28
Age : 31
Localisation : Roubaix
Distinction : aucune
Date d'inscription : 24/02/2014

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Mer 5 Mar 2014 - 23:54
Mais par contre il y a une chose que je voudrai savoir : étant donné qu'il faut la console pour utiliser la méthode gets, il y a t-il une autre méthode identique qui ne demande pas d'afficher la console ?
pingouinmutant
pingouinmutant
Membre

Nombre de messages : 204
Age : 24
Localisation : En Bordeciel
Distinction : aucune
Date d'inscription : 27/06/2012

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Ven 7 Mar 2014 - 22:33
Ce tuto est EXELLENT, j'ai enfin commencé à comprendre des ptits trucs, j'attends avec impatience la suite, et vraiment un grand merci à toi!
Heaven
Heaven
Staffeux retraité

Nombre de messages : 2441
Age : 23
Localisation : Alpes-Maritimes VIRILITÉ OLALA
Distinction : Aucune
Date d'inscription : 18/10/2012

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Sam 8 Mar 2014 - 15:03
Moh> fais gaffe aux doublepost ^^


Heav'n
vincent26
vincent26
Membre

Nombre de messages : 766
Age : 28
Localisation : baume de transit le village paumé
Distinction : aucune
Date d'inscription : 17/08/2010

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Lun 10 Mar 2014 - 5:10
Moh pour ce qui est d'afficher quelque chose sur l'écran du jeu c'est plus compliquer qu'une simple fonction il faut créer plein de chose Wink
Contenu sponsorisé

Ruby/RGSS ou la puissance cachée de RPG Maker Empty Re: Ruby/RGSS ou la puissance cachée de RPG Maker

Revenir en haut
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum