Créer une interface sous PSDK LiteRGSS

  • 2 Réponses
  • 155 Vues
Créer une interface sous PSDK LiteRGSS
« le: 01 mai 2018, 14:24:18 »
Salut à tous, aujourd’hui, je vais vous présenter comment réaliser correctement une interface sous PSDK (à partir de Alpha 23.0).

Comme vous pouvez vous en douter, beaucoup de choses ont changé, surtout au niveau du dessin de texte, il est désormais plus possible de dessiner du texte dans un Bitmap. A la place de la vieille méthode bancale du RGSS il y a un type d’objet dédié à l’affichage de Text : la classe Text ! (Qui a plusieurs variantes).

1 – Principe de fonctionnement d’une interface sous PSDK

Sous PSDK, une interface est souvent codé dans le module GamePlay, ceci pour une raison assez simple, il existe une classe de base nommé « Base » qui intègre les fonctions de base vous permettant de ne pas avoir à faire une grande partie du boulot et réduisant considérablement la taille des scripts. Dans ce tutoriel nous allons suivre les étapes de programmation du script « QuestBookMenu » qui affiche le menu principal du journal des quêtes.

Script de base :
module GamePlay
  # Menu to choose which list of quest to show
  class QuestBookMenu < Base
    include UI #Add the UI functions to the current interface
    # Create a new QuestBookMenu
    def initialize
      super() # Call the Base initialize method ignoring the argument of the current initialize
      @viewport = Viewport.create(:main, 1000) # Viewport that holds the sprites of the interface
    end
   
    # Updates the interface
    def update
      return unless super # The update method from base tells if the update can continue or not (message display)
     
    end
   
    # Dispose the viewports of the interface
    def dispose
      super # Call the dispose from Base to dispose the messagebox
      @viewport.dispose #Under LiteRGSS Viewport#dispose disposes all the sprite it holds
    end
  end
end
Pour développer votre interface, je vous conseille d’utiliser un module dédié de Pokémon SDK : Tester ! Ce module vous permet de déposer des scripts Ruby dans le dossier « Tests » et de les tester au fur et à mesure à l’aide de l’option --test=NomDuFichierSansLextension de Game.exe.

Bien entendu pour que ce module fonctionne, vous devez lui signaler quoi tester :

La ligne « Tester.start(GamePlay::QuestBookMenu) » indique au module Tester de démarrer l’interface GamePlay::QuestBookMenu, ceci vous permettra de développer votre script au fur et à mesure sans avoir à forcément redémarrer le jeu ou faire plein de trucs chiants comme passer l’écran titre (ça affiche directement l’interface désiré).

2 – Explication du script de base

Avant d’aller plus loin je vais expliquer le script de base au fur et à mesure, certaines choses sont importantes à comprendre.
Ligne 1 : « module GamePlay » Cette ligne indique que vous travaillez dans le module GamePlay, ceci vous permet d’accéder à toutes les composantes de ce menu (notamment la classe Base).
Ligne 3 : « class QuestBookMenu < Base » Cette ligne vous permet de définir votre classe « QuestBookMenu » et de charger les fonctions de la classe « Base ».
Ligne 4 : « include UI » Cette ligne n’est pas vraiment obligatoire mais sachez que si vous avez besoin d’éléments définis dans le module UI (comme SpriteStack ou PokemonIconSprite) il peut être utile d’ajouter cette ligne, ça ajoute toute les classes définies dans le module UI à votre classe.
Ligne 6 : « def initialize » Cette ligne vous permet de définir la fonction qui crée votre objet d’interface, il ne faut jamais l’oublier car c’est après cette ligne que vous définirez tous les éléments à afficher dans votre interface.
Ligne 7 : « super() » Cette ligne appelle la méthode initialize de la classe Base, ça permet entre autre d’avoir une boite de message sur demande. Si vous ne désirez pas explicitement de boite de message, tapez « super(true) » à la place.
Ligne 8 : « @viewport = Viewport.create(:main, 1000) » Cette ligne crée le viewport principal de votre interface (vous en aurez besoin pour les textes et sprites). Le viewport sera à la coordonnée z = 1000.
Ligne 9 : « end » Cette ligne indique à Ruby que vous avez terminé de définir la méthode initialize de votre classe.
Ligne 12 : « def update » Cette ligne définit la méthode appelée à chaque frame, c’est destiné aux interactions avec l’utilisateur (actuellement nous ne faisons rien).
Ligne 13 : « return unless super » Cette ligne appelle la méthode update de « Base » et sort de la méthode update si quelque chose comme l’affichage d’un message doit empêcher au joueur d’interagir avec l’interface. (Si vous oubliez cette ligne, vos messages ne fonctionneront pas).
Ligne 15 : « end » Cette ligne indique à Ruby que vous avez terminé de définir la méthode update.
Ligne 18 : « def dispose » Cette ligne indique que vous commencez à définir la méthode d’effacement des sprites / texte et autres entités de votre interface (lorsque son travail est terminé).
Ligne 19 : « super » Cette ligne permet d’appeler la méthode dispose de la classe « Base », le but est d’effacer la boite de message si elle a été créée.
Ligne 20 : « @viewport.dispose » Cette ligne permet d’efface le viewport principal ainsi que tous les sprites et textes qui sont affiché dedans. De ce fait, vous n’avez pas besoin d’effacer séparément les sprites et textes qui sont affichés dedans. (Attention, c’est valable que depuis Alpha 23.0 et pour les sprites/textes réellement affichés dans le viewport désigné !)
Ligne 21 à 23 : Ces lignes disent à Ruby que vous avez terminé de définir la méthode « dispose », la classe QuestBookMenu et que vous quittez le module GamePlay.

3 – Test du script de base

Pour le test, j’ai enregistré le script dans Tests/Quest.rb, la commande que je dois donc entrer pour le tester est « Game.exe --test=Quest »


Comme vous pouvez le voir, ça affiche une fenêtre noir qui tourne à 60FPS, c’est normal nous n’avons pas défini de choses à afficher.
Si la fenêtre ne s’affiche pas, lisez la console, il se peut qu’il y ait une erreur de syntaxe ou une autre erreur. La plupart du temps en cas d’erreur, vous pouvez relancer le script en écrivant « reload and restart » dans la console. Si cela ne fonctionne pas ou que le jeu se freeze complètement (on sait jamais) appuyez sur CTRL+C dans la console et relancez le test avec la ligne présenté avant l’image.

4 – Ajoutons un fond

Pour ajouter le fond, j’ai placé deux lignes dans la méthode initialize :
  • « @is_showing_failed = isf = $quests.failed_quests.size > 0 » Cette ligne permet de détecter si l’interface doit afficher l’option des quêtes échouée. (C’est purement informatif).
  • « Sprite.new(@viewport).set_bitmap(isf ? "quest/quest_bg_1" : "quest/quest_bg_1_2", :interface) » Cette ligne affiche le fond, nous allons la détailler après l’image qui montre comment j’ai placé ces lignes.


La ligne de création du fond est composée de deux parties :
  • La création du sprite à afficher dans le viewport principal « Sprite.new(@viewport) »
  • Le chargement de l’image à afficher depuis le cache d’interface : « set_bitmap(isf ? "quest/quest_bg_1" : "quest/quest_bg_1_2", :interface) »

Comme nous avons deux fonds différents en fonction de si on affiche l’option des quêtes échouées on utilise la variable définie quelques lignes plus haut dans une condition ternaire. Sachez que la plupart des fonctions en .set_qqch de Sprite peuvent se chaîner.
Notez par ailleurs que le sprite n’a pas été stocké dans une variable, c’est normal puis-ce que nous n’agirons jamais dessus et que le viewport se charge de conserver le sprite jusqu’à son effacement.

5 – Ajouter du texte

Maintenant nous allons ajouter du texte sur l’interface, mais avant cela, je vais vous présenter une fonctionnalité qui pourrait vous intéresser. Lorsque vous testez une interface, la touche F9 vous donne les coordonnées de la souris sur l’écran. Nous nous en servirons pour positionner nos textes.


Nous utilisons une interface basique (sans SpriteStack) du coup nous devons demander les fonctionnalités d’affichage de texte.
  • Après « include UI » nous ajoutons « include Text::Util » ceci charge les fonctionnalités d’affichage de texte pour les interfaces.
  • Après « @viewport = Viewport.create(:main, 1000) » on ajoute « init_text(0, @viewport) » ceci permet d’indiquer aux texte d’utiliser la Font 0 (défaut) et d’afficher les textes dans le viewport (nous permettant de ne pas avoir à les effacer à la main).

Une fois ces lignes ajoutées nous ajoutons les lignes qui permettent de définir les textes que l’interface affiche


Les choses à savoir : add_text permet d’ajouter un texte, il faut donc appeler cette méthode dans initialize (sauf cas particulier), cette méthode fonctionne exactement comme bitmap.draw_text (qui a été supprimé). La seule variation qu’il y a avec cette fonction c’est qu’elle retourne l’objet Text que vous pouvez stocker ou utiliser par exemple pour définir la couleur de celui-ci. (.set_color(id))
La liste des couleurs est la même que celle des couleurs des messages, en effet la boite des messages utilise également add_text pour afficher les mots du message.

Maintenant je vais attirer votre attention sur la ligne suivante :
« add_text(0, 129, 320, 23, "Quêtes échouées", 1, 1).load_color(9) if isf »
Cette ligne affiche le texte « Quêtes échouées » si et seulement si l’interface doit les afficher. Notez par ailleurs qu’à cause d’une fonction dans update nous allons déplacer cette ligne avant la précédente. (Les coordonnées y sont ajustées en fonction d’isf pour les autres textes).

6 – Ajouter un sélecteur

Maintenant que nous avons placé les textes, nous devons placer le sélecteur, il permettra au joueur de savoir quel menu il ouvre. Comme le sélecteur est un objet qui se déplace, nous devons l’enregistrer dans une variable d’instance « @selector »


Comme vous le voyez, j’ai créé le sprite, positionné et affiché l’image de celui-ci en trois lignes sans rappeler la variable d’instance. Ceci mérite explication.
En Ruby, le point-virgule des langages comme C/C++ est optionnel, cela-dit il peut être utilisé et ça a un sens particulier. Si une ligne termine par point-virgule, alors l’instruction est terminée, sinon, Ruby interprète selon ses propres règles. Dans le cas présent, la ligne suivante commence par un point, de ce fait pour Ruby c’est comme si vous n’aviez pas sauté de ligne (rappelez-vous les .load_color(9)). Ca voudra aussi dire que tant que vous continuez à chainer des appels de fonction sur l’objet crée, la variable d’instance @selector ne contient pas l’objet c’est pourquoi vous devez bien faire attention à ce que les méthodes que vous chaînez renvoient l’objet que vous voulez enregistrer.

Maintenant détaillons un peu les trois lignes :
  • « @selector = Sprite.new(@viewport) » nous créons un sprite dans le viewport principal, le résultat final sera stocké dans la variable d’instance @selector.
  • « .set_position(0, @texts[@index].y + FOY) » nous positionnons le sprite à la coordonnée 0, coordonnée du texte @index plus un petit offset dû aux fonctions de positionnement des textes sur l’écran. Notez qu’avec Text::Util les textes sont tous enregistré dans @texts dans l’ordre où les add_text ont été exécutés. C’est pourquoi sur le screenshot j’ai déplacé le texte des quêtes échouées. (On s’en servira pour le positionnement du sélecteur).
  • « .set_bitmap("quest/quest_selector", :interface) » on charge l’image quest_selector dans le dossier quest du cache d’interface.
7 – Actions du joueur sur le sélecteur

Après avoir créé le sélecteur nous allons gérer les interactions du joueur dessus, son déplacement entre autre. Pour cela, la classe Base défini une méthode très utile « index_changed » que nous appellerons dans la méthode update.
La méthode index_changed est définie ainsi : index_changed(varname, sub_key, add_key, max, min = 0)
  • varname correspond au symbole de la variable d’instance affecté par la méthode ( :@index pour nous)
  • sub_key correspond au symbole de la touche qui soustraira 1 à l’index, ici :UP
  • add_key correspond au symbole de la touche qui ajoutera 1 à l’index, ici :DOWN
  • max correspond à la valeur maximale que l’index peut prendre (2 ou 3 selon si on affiche le choix échoué ou pas).
  • min correspond à la valeur minimale que l’index peut prendre (on le spécifiera pas car pour nous c’est 0)
Notez que cette fonction est rotative, si vous arrivez en bas de la liste, ça retourne en haut, pour ne pas avoir cet effet, utilisez « index_changed! » à la place.


Quand l’index change, nous changeons évidemment la position du sélecteur.

8 – Choix de l’utilisateur

Une fois que l’utilisateur a positionné le sélecteur au bon endroit, il voudrait surement ouvrir le menu qui correspond (ou quitter). Pour cela il appuiera sur la touche virtuelle « A » qui est en fait la touche « C » ou « Entrée » du clavier. Pour gérer la fermeture du menu, nous allons devoir enregistrer l’index maximal dans une variable et comparer l’index à l’index maximal, si la comparaison est valide, on arrête l’interface à l’aide de la variable d’instance « @running » qui pour toute les interfaces de GamePlay indique si l’interface tourne toujours ou pas.


Pour détecter un appui de touche nous utilisons Input.trigger?(symbol) où symbol est le symbole de la touche virtuelle. Par exemple pour quitter en toute circonstances on appuie sur « B » (X sur le clavier).

9 – Test final

Une fois que tout est codé, on peut faire un test final de l’interface. Vous pouvez entrer des lignes de code, sur le screen suivant je vais entrer « $quests.failed_quests[0] = {} », ça aura pour effet d’activer les quêtes échouées, si on entre ensuite « restart » l’interface va s’afficher avec l’option d’affichage de l’échec des quêtes et lorsqu’on appuiera sur Entrée ça devrait ouvrir le menu désiré (là ça l’affiche à l’écran car pas encore codé).


Bonus – Démarrer une autre interface.

Pour démarrer une autre interface, il existe une fonction spécifique « call_scene(Nom, *args) ». Cette fonction crée un objet en appelant « Nom.new(*args) », rend le viewport principal de la scene actuelle invisible redonne la priorité à votre interface une fois que la scene « Nom » a terminé son boulot. Attention, il se peut que votre scene soit automatiquement arrêté si par exemple la scène Nom décide de retourner sur la carte ou alors qu’elle appelle la fonction « return_to_scene(AutreNom) » (vous pouvez aussi le faire).
Pour vous rendre compte de call_scene, regarde les scripts dans PSDK, c’est la version Alpha 23.0 du système de quêtes (ouvrez Data/__.rxdata pour lire le script).
« Modifié: 01 mai 2018, 14:27:09 par Nuri Yuri »
ln(yo) = <3
 
Utilisateurs ayant remercié ce post : Aerun, Splifingald, Vulvoch, Bentoxx, yyyyj

*

Hors ligne Aerun

Créer une interface sous PSDK LiteRGSS
« Réponse #1 le: 01 mai 2018, 16:43:02 »
Merci pour ce tuto, ça va nous permettre de construire nos interfaces plus facilement ! :D
Bientôt un éditeur d'interface à la Ruby Host ? :ahde:
 
Utilisateurs ayant remercié ce post : yyyyj

Créer une interface sous PSDK LiteRGSS
« Réponse #2 le: 01 mai 2018, 16:48:02 »
Malheureusement non ^^'
C'est beaucoup trop compliqué d'abstraire une interface avec des boutons, le texte sera toujours supérieur aux interfaces graphiques (comme sous Windows, tu as plus de marge de manœuvre avec cmd qu'avec l'interface d'Explorer).
ln(yo) = <3
 
Utilisateurs ayant remercié ce post : yyyyj