FDJ.fr

Affichage des messages

Dans la section précédente, nous avons établi toute la logique de notre application, donc elle fonctionne ! Maintenant, il faudrait que notre système affiche des messages de victoire ou de défaite. Nous allons créer une fenêtre qui s’affichera au bon moment.

Une fenêtre simple

Nous utiliserons Window_Base, la représentation la plus simple d’une fenêtre. L’objectif de ce type de fenêtre est simplement d’afficher des informations. Dans le code de Window_Base, on peut voir que son constructeur prend 4 arguments : la position en X et en Y, puis la taille en largeur et en hauteur.

Je vous invite à créer une méthode create_window_message dont le rôle sera de dessiner une fenêtre simple dans un attribut nommé message. Je souhaite lui donner les dimensions (280, 80) et la placer au centre de l’écran. Le point d’origine d’une fenêtre étant son coin haut gauche, nous devons effectuer quelques calculs pour la positionner au centre :

  • Centrer en X : (Ecran de jeu / 2) − Largeur fenêtre / 2
  • Centrer en Y : (Ecran de jeu / 2) − Hauteur fenêtre / 2

La résolution d’un jeu RPG Maker VX Ace étant 544×416 par défaut, le résultat final est le suivant :

  • En X : (544 / 2) − (280 / 2) = 132
  • En Y : (416 / 2) − (80 / 2) = 168

C’est une petite ruse pour positionner correctement la fenêtre. On écrit create_window_message de cette manière :

def create_window_message
  @message = Window_Base.new(132, 168, 280, 80)
end

N’oubliez pas d’appeler create_window_message dans la méthode start. Vous pouvez tester la scène pour voir notre fenêtre bien placée. L’idéal serait qu’elle s’affiche uniquement au besoin. Nous allons modifier notre méthode pour que la fenêtre soit invisible au départ.

def create_window_message
  @message = Window_Base.new(132, 168, 280, 80)
  @message.hide
end

Ecrire du texte dans la fenêtre

Une fenêtre vide, c’est pas génial, donc nous allons essayer d’y écrire du texte. Une fois de plus, le RGSS met à notre disposition une méthode qui fait précisément cela : draw_text.

draw_text(x, y, width, height, text, [align=0])

Concrètement, on va préparer un rectangle invisible dans la fenêtre, qui accueillera le texte. Ce rectangle est défini par une position et une taille. Le dernier argument donne l’alignement du texte. Il est facultatif, car il vaut 0 par défaut, pour signifier un alignement à gauche. 1 = alignement au centre, et 2 = alignement à droite.

Essayons d’écrire un texte dans la méthode create_window_message, en supprimant temporairement la commande qui masque la fenêtre afin de voir ce que l’on fait.

def create_window_message
  @message = Window_Base.new(132, 168, 280, 80)
  # @message.hide
  @message.draw_text(0, 0, 280, 38, "Vous avez choisi la pierre.")
end

Je vous parlais de la création d’un rectangle, dans lequel sera placé le texte. Voici la représentation de ce rectangle :

Représentation du rectangle de draw_text.

Vou pouvez voir que le contenu d’une fenêtre possède des marges de 12 pixels, définies par la méthode standard_padding de Window_Base.

Nous allons écrire une petite fonction pour afficher les différents résultats possibles. La méthode aura deux arguments. Le premier sera un texte tel que « Vous avez choisi pierre et l’ordinateur papier ». Le deuxième argument pourra prendre 3 valeurs : 0, 1, ou 2. Dans le cas où le nombre vaut 0, on affiche « Match nul », si le nombre vaut 1, « Vous perdez » et sinon, « Vous gagnez ».

def display_message(text, number)
  @message.draw_text(0, 0, 280, 38, text)
  message = "Vous gagnez !"
  if number == 0
    message = "Match nul."
  elsif number == 1
    message = "Vous perdez !"
  end
  @message.draw_text(0, 20, 280, 38, message)
  @message.show
end

Pour éviter de réécrire la seconde méthode draw_text qui est assez lourde, j’utilise une variable message. Remarquez comment je me suis passé du else à la fin de la branche conditionnelle, en initialisant la variable avec une valeur par défaut.

Il est maintenant temps d’utiliser notre nouvelle méthode !

Utilisation de display_message

Cette partie est très facile, parce que nous avons déjà conçu nos outils. Dans les méthodes pierre, feuille et ciseaux, substituez les utilisations de la méthode p par la méthode que nous venons de créer. Par exemple, au lieu d’écrire :

p "Vous avez choisi pierre et l'ordinateur ciseaux, vous gagnez !"

Faites plutôt :

display_message("Vous avez choisi pierre et l'ordinateur ciseaux.", 2)

Problème : le message ne s’affiche jamais ! Ou plutôt, la fenêtre va bien s’afficher, mais de suite après, un changement de scène est appelé. Il serait préférable d’attendre l’appui de la touche action avant de changer de scène.

Attendre l’appui d’une touche

Nous allons modifier la méthode pre_terminate de la classe Window_Base. Nous savons que grâce à l’héritage, il n’est pas nécessaire d’écrire certaines méthodes. La méthode pre_terminate est appelée juste avant la suppression automatique des éléments de la scène. Pour éviter que notre message soit effacé car la scène est terminée, nous allons ajouter une attente dans la méthode pre_terminate, jusqu’à ce que la touche C, correspondant à la touche Action, soit pressée.

def pre_terminate
  super
  loop do
    Graphics.update
    Input.update
    break if Input.trigger?(:C)
  end
end

Le mot super permet d’appeler la méthode pre_terminate de Window_Base, qui est normalement vide, mais sait-on jamais ! Un script personnalisé pourrait l’avoir améliorée.

Le code compris entre loop do et end sera répété à l’infini. Cette boucle va durer plusieurs frames, il faut donc rafraichir l’affichage et la détection des touches : c’est le rôle de Graphics.update et de Input.update.

break permet de sortir de la boucle. La dernière ligne indique donc que l’on sort de la boucle si la touche C est pressée. Cette écriture en une ligne est identique à :

if Input.trigger?(:C)
  break
end

Quand on n’a qu’une seule commande à exécuter, on peut synthétiser une condition comme dans la première forme.

Concrètement, une fois que le message est affiché, nous indiquons que nous souhaitons changer de scène. Notre scène va appeler la méthode pre_terminate, juste avant terminate. On rentre dans la boucle et on en sort dès que la touche Action est pressée. S’en suit la méthode terminate qui supprime les éléments et renvoie vers la scène demandée !

Voici un rappel du code terminé :

# Scène de jeu principale
class Scene_Chifoumi < Scene_Base
 # Lancement de la scène
 def start
   super
   create_title
   create_commands
   generate_choice
   create_window_message
 end
 # Création de la fenêtre de titre
 def create_title
   @title = Window_Help.new(1)
   @title.set_text("CHI FOU MI !")
 end
 # Création de la fenêtre de sélection
 def create_commands
   @window_selection = Window_Chifoumi.new(0, 48)
   @window_selection.set_handler(:pierre, method(:pierre))
   @window_selection.set_handler(:papier, method(:papier))
   @window_selection.set_handler(:ciseaux, method(:ciseaux))
 end
 # Génère le choix de l'ordinateur
 def generate_choice
   list_signs = [:pierre, :papier, :ciseaux]
   @computer_choice = list_signs.sample
 end
 def create_window_message
   @message = Window_Base.new(132, 168, 280, 80)
   @message.hide
 end
 # Affiche un message
 def display_message(text, number)
   @message.draw_text(0, 0, 280, 38, text)
   message = "Vous gagnez !"
   if number == 0
     message = "Match nul."
   elsif number == 1
     message = "Vous perdez !"
   end
   @message.draw_text(0, 20, 280, 38, message)
   @message.show
 end
 # Cas de sélection de Pierre
 def pierre
   if @computer_choice == :pierre
     display_message("Vous : Pierre, Ordi : Pierre", 0)
     SceneManager.call(Scene_Chifoumi)
   elsif @computer_choice == :papier
     display_message("Vous : Pierre, Ordi : Papier", 1)
     SceneManager.call(Scene_Map)
   else
     display_message("Vous : Pierre, Ordi : Ciseaux", 2)
     SceneManager.call(Scene_Map)
   end
 end
 # Cas de sélection de Papier
 def papier
   if @computer_choice == :papier
     display_message("Vous : Papier, Ordi : Papier", 0)
     SceneManager.call(Scene_Chifoumi)
   elsif @computer_choice == :ciseaux
     display_message("Vous : Papier, Ordi : Ciseaux", 1)
     SceneManager.call(Scene_Map)
   else
     display_message("Vous : Papier, Ordi : Pierre", 2)
     SceneManager.call(Scene_Map)
   end
 end
 # Cas de sélection de Ciseaux
 def ciseaux
   if @computer_choice == :ciseaux
     display_message("Vous : Ciseaux, Ordi : Ciseaux", 0)
     SceneManager.call(Scene_Chifoumi)
   elsif @computer_choice == :pierre
     display_message("Vous : Ciseaux, Ordi : Pierre", 1)
     SceneManager.call(Scene_Map)
   else
     display_message("Vous : Ciseaux, Ordi : Papier", 2)
     SceneManager.call(Scene_Map)
   end
 end
 # Attente de la pression du bouton C
 def pre_terminate
   super
   loop do
     Graphics.update
     Input.update
     break if Input.trigger?(:C)
   end
 end
end

# Fenêtre de sélection de coup
class Window_Chifoumi < Window_Command
 # Création de la liste de sélection
 def make_command_list
   add_command("Pierre", :pierre)
   add_command("Papier", :papier)
   add_command("Ciseaux", :ciseaux)
 end
end
Le résultat final.

Enfin ! Nous avons créé un script complet qui, malgré son aspect très simple, fut l’occasion d’aborder de nombreux concepts. Ce guide n’aura pas été d’une rigueur exemplaire afin d’être plus facile à suivre. Pour aller plus loin, je vous recommande cet ouvrage très complet sur le Ruby. Bonne continuation dans la suite de votre formation !