VNLEWIKICréez des histoires. Reliez des mondes.
Français
Manuel VNLE

MonoGame

← Intégrer le contenu à votre jeu

MonoGame 3.8 · DesktopGL · C# / .NET

Commencez par afficher une seule phrase. Ce petit exemple lit directement les données exportées de La clé du port ; il ne constitue pas un système de dialogue complet. Reliez ensuite ces données à l’interface de votre jeu.

1 · Préparer les fichiers et la scène

Commencez avec un projet MonoGame DesktopGL. Placez story.json dans Content/ et copiez-le comme fichier brut dans le dossier de sortie (voir la configuration du projet ci-dessous). Ajoutez ReadWelcome à Game1. Dans Content Pipeline Tool, créez un SpriteFont nommé DialogueFont, compilez le contenu et chargez-le avec Content.Load("DialogueFont").

story.json · Comprendre les fichiers exportés

2 · Afficher le premier texte

<ItemGroup>
  <None Update="Content/story.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Ajoutez les champs SpriteFont _dialogueFont; et string _dialogueLine = ""; à Game1. Dans LoadContent, utilisez _dialogueFont = Content.Load("DialogueFont"); _dialogueLine = ReadWelcome("en");. Dans Draw, au sein de votre bloc SpriteBatch existant, utilisez _spriteBatch.DrawString(_dialogueFont, _dialogueLine, new Vector2(24, 24), Color.White);. Sans SpriteBatch existant, créez-en un dans LoadContent avec new SpriteBatch(GraphicsDevice), puis utilisez Begin()/End() dans Draw.

// Game1.cs: add using System.IO; using System.Text.Json; using System.Text;
// Place this method inside the existing Game1 class.
private string ReadWelcome(string locale)
{
    using var stream = TitleContainer.OpenStream("Content/story.json");
    using var document = JsonDocument.Parse(stream);
    var content = document.RootElement.GetProperty("content");
    const string id = "fd7b61a3-8233-4ba7-8f77-b88b119a91bf";
    var message = content.GetProperty("texts").GetProperty(id).GetProperty("sourceMessage");
    if (content.GetProperty("translations").TryGetProperty(locale, out var table)
        && table.TryGetProperty(id, out var translation))
        message = translation.GetProperty("message");
    var line = new StringBuilder();
    foreach (var segment in message.GetProperty("segments").EnumerateArray())
    {
        if (segment.GetProperty("kind").GetString() != "text")
            throw new InvalidDataException("Text-only example");
        line.Append(segment.GetProperty("text").GetString());
    }
    return line.ToString();
}

Résultat attendu : « Welcome to the harbour. I am Mira. » Avec locale = "de" ou le paramètre de langue de : « Willkommen im Hafen. Ich bin Mira. » Une langue absente utilise le texte source. Cet exemple prend en charge les segments de texte ; il ne supprime pas silencieusement les paramètres de substitution.

3 · D'une phrase à une conversation

L’identifiant de texte fixe ci-dessus sert au premier test. Dans votre jeu, choisissez flowRef/entryRef dans story-index.json, puis lisez execution.entries[entryRef].nodeRef et execution.nodes[nodeRef]. Le dialogue courant fournit text.textRef et speakerRef. La suite dépend du champ kind du nœud.

Nom et dialogue : SpriteBatch.DrawString entre Begin/End. Gérez les retours à la ligne et les caractères couverts par la police pour les textes longs. Le jeu gère les zones de réponse et les entrées souris/clavier ; conservez les identifiants, pas les textes traduits. End : désactivez l’affichage et les entrées avec dialogueOpen = false, sans appeler Game.Exit().

  1. Continue et End : suivre les connexions et fermer la boîte de dialogue
  2. Choix : identifiant, ordre et suite de la réponse sélectionnée
  3. Conditions et variables : dix ou deux pièces d’or
  4. Langue : mêmes identifiants, contenu relu dans la langue choisie
  5. Command : donner un objet ou ouvrir une boutique
  6. Call/Return : appeler une sous-histoire puis revenir
Examiner les réponses et la vérification de l’or dans ce langage

Lire les données pour un choix

Insérez cet extrait là où story est disponible après le chargement. Pour RPG Maker, utilisez const story = $gameTemp.vnleExample.story;. Il affiche les identifiants pour vérification ; remplacez cet affichage par vos boutons de réponse. Il couvre les deux réponses du port et la vérification de l’or qui suit, pas l’ensemble des types de nœuds.

// Inside ReadWelcome while document is alive; inspect data before returning.
var nodes = document.RootElement.GetProperty("execution").GetProperty("nodes");
var choice = nodes.GetProperty("42edfff8-b8fe-46bf-ae0d-9e2347b6e726");
foreach (var idToken in choice.GetProperty("optionOrder").EnumerateArray())
{
    string optionId = idToken.GetString();
    var option = choice.GetProperty("options").GetProperty(optionId);
    System.Console.WriteLine(optionId + " " + option.GetProperty("text").GetProperty("textRef").GetString());
}
var branch = nodes.GetProperty("c1c3c372-0a73-4cd0-851d-ede59d5709bb");
int gold = 10; // Repeat with 2.
int minimum = branch.GetProperty("condition").GetProperty("right").GetProperty("value").GetProperty("value").GetInt32();
var next = branch.GetProperty(gold >= minimum ? "whenTrue" : "whenFalse");
System.Console.WriteLine(next.GetProperty("nodeRef").GetString());
// Copy strings/values you need later before disposing JsonDocument.

Avec 10 pièces d’or, next désigne Pay five gold ; avec 2, Not enough gold. Dans le jeu, effectuez cette vérification uniquement lorsque le parcours choisi atteint ce nœud. Chaque réponse possède sa propre suite.

4 · Associer vos propres images

Cet extrait complémentaire suppose que le dialogue courant se trouve dans un objet nommé node et que les éléments d’interface cités en commentaire existent. En C++ et MonoGame, speakerRef a déjà été lu dans SpeakerId ou speakerId. La clé est le véritable identifiant de Mira ; le nom et l’emplacement de l’image dépendent de votre jeu. Insérez les lignes aux endroits indiqués.

// Game1 class field, so both LoadContent and Draw can access it:
private readonly System.Collections.Generic.Dictionary<string, Texture2D> portraits = new();
// Inside LoadContent(): import/build mira.png as portraits/mira.
portraits["807b2957-7bab-4a28-83a4-1f3d1589bbc2"] = Content.Load<Texture2D>("portraits/mira");
// Inside a SpriteBatch Begin/End in Draw; speakerId comes from speakerRef:
if (portraits.TryGetValue(speakerId, out var portrait))
    _spriteBatch.Draw(portrait, new Vector2(24, 120), Color.White);

Retrouvez le nom du personnage avec content.characters[speakerRef].nameTextRef, comme pour un texte de dialogue. Si aucune image n’est associée, masquez l’ancien portrait ou affichez une image de remplacement. Les images ne sont pas choisies selon la langue.

Utiliser les références d'image de l'exportation complète

5 · Inclure les fichiers dans le jeu distribué

Dans cet exemple, ne chargez pas le JSON avec Content.Load. TitleContainer ouvre le fichier brut, copié par le csproj. Compilez SpriteFont et les textures avec Content Pipeline. Commencez par DesktopGL et vérifiez les autres plateformes séparément.

Vérifiez votre résultat

  1. Les salutations en anglais et en allemand s'affichent correctement; une langue non disponible revient à l'anglais.
  2. Après avoir ajouté la progression, testez les deux réponses, 10 puis 2 pièces d’or, le retour de la sous-histoire et End.
  3. Lancez le jeu compilé en dehors du dossier du projet. Les fichiers JSON, les polices et les portraits doivent y être accessibles aussi.

Documentation officielle

Documentation des API et de la configuration utilisées :