VNLEWIKICrie histórias. Conecte mundos.
Português (Brasil)
Manual do VNLE

MonoGame

← Integre o conteúdo ao seu jogo

MonoGame 3.8 · DesktopGL · C# / .NET

Comece exibindo uma frase. Este pequeno exemplo lê diretamente a exportação real do porto; ele ainda não é um sistema completo de diálogos. Depois, conecte os dados à interface do seu jogo.

1 · Prepare os arquivos e a cena

Comece com um projeto MonoGame DesktopGL. Coloque story.json em Content/ e copie-o como arquivo bruto para o diretório de saída (veja a configuração do projeto abaixo). Adicione ReadWelcome a Game1. No Content Pipeline Tool, crie um SpriteFont chamado DialogueFont, compile o conteúdo e carregue-o com Content.Load("DialogueFont").

story.json · Entenda os arquivos exportados

2 · Exiba o primeiro texto

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

Adicione os campos SpriteFont _dialogueFont; e string _dialogueLine = ""; a Game1. Em LoadContent, use _dialogueFont = Content.Load("DialogueFont"); _dialogueLine = ReadWelcome("en");. Em Draw, dentro do bloco SpriteBatch existente, use _spriteBatch.DrawString(_dialogueFont, _dialogueLine, new Vector2(24, 24), Color.White);. Se não houver SpriteBatch, crie um em LoadContent com new SpriteBatch(GraphicsDevice) e use Begin()/End() em 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();
}

Resultado esperado: “Welcome to the harbour. I am Mira.” Com locale = "de" ou o parâmetro de idioma de: “Willkommen im Hafen. Ich bin Mira.” Se o idioma não estiver disponível, será usado o texto original. Este exemplo aceita segmentos de texto e não descarta placeholders silenciosamente.

3 · De uma frase a uma conversa

O ID de texto fixo acima serve para o primeiro teste. No seu jogo, escolha flowRef/entryRef em story-index.json, leia execution.entries[entryRef].nodeRef e depois execution.nodes[nodeRef]. O diálogo atual fornece text.textRef e speakerRef. A continuação depende do tipo de nó.

Nome e diálogo: SpriteBatch.DrawString entre Begin/End. Cuide da quebra de linha e dos caracteres disponíveis na fonte para textos longos. As áreas de resposta e a entrada de mouse e teclado pertencem ao jogo; preserve os IDs em vez de usar o texto traduzido. End: desative desenho e entrada com dialogueOpen = false, não com Game.Exit().

  1. Continue e End: siga as conexões e feche a caixa de texto
  2. Escolhas: ID da resposta, ordem e continuação selecionada
  3. Condições e variáveis: dez ou duas moedas de ouro
  4. Idioma: mesmos IDs, conteúdo resolvido novamente
  5. Command: entregar um item ou abrir uma loja
  6. Call/Return: entrar em uma sub-história e voltar
Examine as respostas e a verificação de ouro nesta linguagem

Leia os dados de uma escolha

Insira este trecho onde story estiver disponível após o carregamento (no RPG Maker: const story = $gameTemp.vnleExample.story;). Ele exibe IDs para conferência. Substitua a saída pelos seus botões de resposta. O trecho cobre as duas respostas do porto e a verificação de ouro seguinte; não é um interpretador genérico.

// 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.

Com 10 moedas de ouro, next aponta para Pay five gold; com 2, para Not enough gold. No jogo, execute a verificação somente quando o caminho escolhido chegar a esse nó. Cada resposta tem sua própria continuação.

4 · Mapeie suas próprias imagens

Este trecho complementar espera um objeto de diálogo atual chamado node e os elementos de interface indicados nos comentários. Em C++ e MonoGame, speakerRef já foi lido como SpeakerId ou speakerId. A chave do mapeamento é o ID real da personagem Mira; o nome e a localização da imagem pertencem ao seu jogo. Insira as linhas nos locais indicados.

// 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);

Resolva o nome do personagem por content.characters[speakerRef].nameTextRef, como faz com o texto do diálogo. Se faltar um mapeamento, o jogo deve ocultar o retrato anterior ou mostrar uma imagem substituta. As imagens não são selecionadas pelo idioma.

Use as referências de imagem da exportação completa

5 · Distribua os arquivos com o jogo

Não use Content.Load para carregar o JSON neste exemplo. TitleContainer abre o arquivo bruto; o csproj o copia. Compile SpriteFont e texturas pelo Content Pipeline. Comece pelo DesktopGL e verifique as outras plataformas separadamente.

Confira o resultado

  1. As saudações em inglês e alemão devem aparecer corretamente; um idioma indisponível deve usar o inglês.
  2. Ao implementar o fluxo, teste as duas respostas, 10 e 2 moedas de ouro, a volta da sub-história e End.
  3. Execute o jogo compilado fora da pasta do projeto. JSON, fontes e retratos também devem estar disponíveis ali.

Documentação oficial

Referências de API e configuração usadas nesta abordagem: