Aller au contenu

Interfaces 2D

Libretto ne livre ni document, ni téléphone, ni popup. Il livre des helpers de lecture qui permettent à n'importe quelle UI de votre cru de parcourir un Dialogue, et rien n'impose à quoi cette UI ressemble. Les recettes ci-dessous sont des exemples dont vous inspirer : chacune traite un cas courant, d'une manière parmi d'autres, avec les vues d'exemple du showcase. Les interfaces de votre jeu ne ressembleront probablement à aucune d'elles, ou en mélangeront plusieurs : prenez le motif qui vous convient, et laissez le reste.

Ce qui vient des exemples

Les flags enfants (Interface2D.Document, .Messaging, .Voicemail, .Popup, .Lock), les actions typées Interface2D, les vues et le device appartiennent tous au showcase. Seuls Staging.Interface2D et les helpers de lecture font partie du produit. Renommez, remplacez ou supprimez le reste.

Je veux afficher un dialogue dans une UI au lieu de le jouer

Cochez Staging.Interface2D sur les sous-dialogues, et lisez-les depuis votre widget avec les helpers de lecture (ULBRDialogueReadingLibrary). Vous gardez tout ce que Libretto apporte à un dialogue écrit (écriture, conditions, GPVars, correcteur orthographique, localisation, voix) et votre UI décide de son apparence. Le showcase livre un exemple complet : un lecteur 2D, cinq vues et un device, sur la station « 2D Interfaces » de la map tutoriel.

  1. Cochez Libretto.Flags.Subdialogue.Staging.Interface2D sur chaque sous-dialogue que votre UI lit, ou l'un de vos propres flags enfants (Interface2D.Document, Interface2D.Messaging…). La génération ne construit alors ni séquence ni stage pour lui, et génère toujours ses voix.
  2. Dans votre widget, choisissez le sous-dialogue avec FindFirstPlayableSubdialogue (ou listez-les avec GetPlayableSubdialogues), puis parcourez-le : GetSubdialogueEntry, puis GetNextStep après chaque ligne, GetValidReplies sur un choice, RecordReplyChosen et ApplyLineEffects quand le joueur répond.
  3. Appelez MarkSubdialogueDone quand votre UI considère la page lue ou le fil terminé : rien n'est marqué terminé pour vous.
  4. Ou partez de l'exemple : un ALBRI2DDevice avec un Dialogue et une View Class ouvre la vue sur la touche Interact.

Piège

Vous ne générez pas de séquences et n'appelez pas StartDialogueInstance pour ces sous-dialogues : une Dialogue Instance n'entre jamais dans un sous-dialogue Interface2D, et un saut Sequencer vers l'un d'eux termine le dialogue joué. Les voix font exception : générez les assets si l'interface joue de l'audio.

Voir aussi : Lire des dialogues dans des interfaces 2D · La boucle de lecture

Je veux un document ou une lettre de plusieurs pages

Une manière : un sous-dialogue par page, flaggé Interface2D.Document, et une condition sur une page pour la masquer jusqu'à ce que la situation soit remplie. La vue document d'exemple liste les pages qui passent leur condition sous forme de table des matières, et affiche une page d'un coup.

La vue document d'exemple

  1. Créez un sous-dialogue par page, flaggez-le Interface2D.Document, et donnez-lui une ligne flaggée Interface2D.Title : cette ligne est le titre dans la table des matières.
  2. Écrivez le corps en lignes Text. Utilisez un If / Else dans une page pour un texte qui dépend de l'état du jeu, et une condition sur le sous-dialogue pour une page qui n'apparaît que plus tard.
  3. Pour une image, ajoutez une action Interface2D Image à la ligne : la vue l'affiche avec le texte.
  4. Ouvrez-le avec un device dont la View Class est ULBRI2DDocumentView. D_I2D_Document montre tout ce qui précède.

Piège

La table des matières est construite à partir de GetPlayableSubdialogues : une page apparaît donc dès que sa condition passe, même document fermé. Si une page ne doit apparaître qu'une fois que le joueur rouvre le document, décidez-le dans votre vue, pas dans la condition.

Voir aussi : Interfaces 2D — les vues d'exemple

Je veux un fil de messagerie sur un téléphone qui garde son historique

Une manière : un sous-dialogue par fil, flaggé Interface2D.Messaging, et Reconstruct à chaque ouverture du fil. Libretto ne garde aucune transcription : les replies choisis sont déjà dans les GPVars, si bien que le fil est reconstruit à partir d'eux et reprend en direct au premier choice sans réponse.

Un fil de messagerie

  1. Écrivez chaque fil comme un sous-dialogue flaggé Interface2D.Messaging : les lignes du contact, puis un Choice dont les replies sont les messages du joueur.
  2. Pour qu'un fil apparaisse plus tard, donnez une condition à son sous-dialogue (dans D_I2D_Phone, le second fil attend que la messagerie vocale ait été écoutée).
  3. Quand la vue ouvre un fil, appelez Reconstruct au lieu de Start : les lignes déjà lues reviennent avec bReplay levé, aucun effet n'est appliqué une seconde fois, et la lecture reprend là où le joueur l'a laissée.
  4. Rythmez les lignes en direct dans votre vue (« en train d'écrire… », un délai par caractère) ; la vue de messagerie d'exemple le fait avec une file de timers.

Piège : deux règles pour un fil qui se reconstruit

  • Ne faites pas passer un fil deux fois par le même choice. Au second passage, la reconstruction s'arrête et le joueur répond à nouveau.
  • Mettez en cache les conditions qui décident de ce qu'un fil a déjà dit (bCacheSuccess / bCacheFailure). Elles sont réévaluées pendant la reconstruction, et un résultat qui a changé envoie le fil reconstruit dans une autre branche.

Voir aussi : Reconstruction · Conditions — cache

Je veux une messagerie vocale : une transcription, et la vraie voix à la demande

Une manière : la transcription dans un sous-dialogue Interface2D.Voicemail, la voix dans un sous-dialogue Audio2D du même Dialogue, et une action Interface2D Play Audio Subdialogue pour les relier. La vue d'exemple affiche le texte tout de suite et joue l'audio quand le joueur appuie sur Play.

La vue messagerie vocale

  1. Écrivez le message dans un sous-dialogue flaggé Interface2D.Voicemail.
  2. Écrivez les mêmes lignes, parlées, dans un second sous-dialogue flaggé Staging.Audio2D, et cochez NoSubtitle sur ses lignes pour que des sous-titres ne doublent pas la transcription.
  3. Sur la transcription, ajoutez une action Interface2D Play Audio Subdialogue qui désigne le sous-dialogue Audio2D.
  4. Générez les assets et les séquences du Dialogue (le sous-dialogue Audio2D a besoin de sa séquence). La vue le joue avec StartGenericDialogue et marque la messagerie vocale comme terminée à la fin de l'audio.

Piège

Le sous-dialogue audio se joue comme un dialogue générique, qu'aucune map ne référence : dans un jeu packagé, il est muet tant que son dossier n'est pas dans Additional Asset Directories to Cook. La vue journalise un warning et termine la lecture au lieu de planter.

Voir aussi : Je veux jouer un dialogue sans instance placée · Personnages intangibles

Je veux une popup avec un choix minuté, qui se souvient de ce que le joueur a fait

Une manière : un sous-dialogue flaggé Interface2D.Popup avec un Choice minuté et un reply par défaut, sous la condition « pas encore terminé », suivi d'un sous-dialogue « bon retour ». Le premier sous-dialogue jouable l'emporte : une fois la première visite terminée, la popup passe au second.

La vue popup

  1. Écrivez la première visite dans un sous-dialogue flaggé Interface2D.Popup, avec la condition « ce sous-dialogue n'est pas encore terminé ».
  2. Donnez un temps à son Choice (TimeChoice) et cochez Default Reply sur le reply pris quand le temps s'écoule. Votre vue appelle TimeOut sur le lecteur à la fin de son compte à rebours.
  3. Ajoutez un second sous-dialogue, après lui et sans condition, pour les visites suivantes. Faites-en bifurquer le texte avec un If sur le reply choisi auparavant : une condition GPCounter sur le chemin du reply, au moins 1.
  4. La vue popup d'exemple marque terminés les sous-dialogues qu'elle a lus, à la fin de la lecture. D_I2D_Popup montre le motif complet.

Piège

Le reply par défaut garde bDoOnceReply coché par défaut. Pour une popup qui peut revenir avec le même choix, décochez-le, sinon le deuxième dépassement de temps ne trouve aucun reply à prendre.

Voir aussi : Saisie et reply par défaut

Je veux un écran de verrouillage, un mot de passe ou une énigme

Une manière : un Choice dont les replies sont les réponses acceptées, plus un reply par défaut pour une mauvaise réponse, et une vue qui envoie ce que le joueur a tapé à SubmitInput. La correspondance ignore la casse et les espaces autour, et compare dans la langue jouée.

L'écran de verrouillage

  1. Créez un sous-dialogue flaggé Interface2D.Lock, avec la condition « ce sous-dialogue n'est pas encore terminé » : une fois ouvert, le téléphone le saute.
  2. Ajoutez un Choice. Chaque réponse acceptée est un Reply dont le texte est la réponse (1987). Ajoutez un Reply de plus, cochez Default Reply, et décochez DoOnce dessus : c'est la branche de la mauvaise réponse.
  3. Dans la branche de la mauvaise réponse, écrivez le retour et faites un Goto vers le Choice pour redemander. Pour un indice après quelques échecs, enveloppez-le dans un If dont la condition vérifie le compteur du reply (au moins 3 fois dans D_I2D_Phone).
  4. Dans votre vue, passez le texte saisi à SubmitInput, ou appelez vous-même FindReplyMatchingInput. Une bonne réponse marque le sous-dialogue du verrou comme terminé.

Piège

  • Les accents comptent : café n'est pas cafe. La casse et les espaces autour, non.
  • Un reply traduit est un mot de passe traduit : le joueur le tape dans la langue jouée.
  • Laissé en DoOnce, le reply par défaut n'est pris qu'une fois : le deuxième code faux n'obtient aucune réponse.

Voir aussi : Saisie et reply par défaut · Je veux un jet de compétence qui dépense une ressource quand il réussit

Je veux une pastille « non lu » sur une conversation

Une manière : un fil est non lu tant qu'il est jouable et pas encore terminé. Marquez-le terminé quand le joueur l'a lu jusqu'au bout, et testez les deux depuis l'écran d'accueil. Libretto stocke déjà ce dont la pastille a besoin : le compteur « done » de chaque sous-dialogue.

  1. Quand un fil se termine (le lecteur envoie Finished), appelez MarkSubdialogueDone dessus. La vue de messagerie d'exemple fait exactement cela.
  2. Sur l'écran d'accueil, listez les fils avec GetPlayableSubdialogues(Dialogue, Interface2D.Messaging) : un fil dont la condition ne passe pas encore n'est pas listé du tout.
  3. Pour chaque fil, lisez GetGPCounter(Subdialogue ▸ GetSubdialogueDoneGPTagPath). 0 signifie que le joueur ne l'a jamais lu jusqu'au bout : affichez la pastille.
  4. Pour un fil qui reçoit de nouveaux messages après avoir été lu (un Goto vers une partie ultérieure, une nouvelle branche qui s'ouvre), tenez votre propre GPCounter de lignes vues par fil : incrémentez-le dans ShowText quand bReplay est faux, et affichez la pastille quand une nouvelle partie du fil devient jouable.

Piège

Ne comptez pas les lignes pendant une reconstruction : les lignes avec bReplay levé ont déjà été vues. Et une condition qui fait apparaître un fil est évaluée quand l'écran d'accueil le liste : mettez-la en cache si le fil doit rester une fois apparu.

Voir aussi : GPVars · Je veux tester « ce dialogue a-t-il déjà été joué »