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

Phaser

← Integre o conteúdo ao seu jogo

Phaser 3.90 · JavaScript

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

Crie index.html, first-text.js e story/story.json no mesmo projeto web. Inclua Phaser 3.90 antes de first-text.js usando tags script. Você pode usar o arquivo existente examples/phaser/phaser.min.js. Abra o projeto por um servidor web local, não com um clique duplo no HTML.

story.json · Entenda os arquivos exportados

2 · Exiba o primeiro texto

<!doctype html>
<html lang="en"><meta charset="utf-8"><title>First VNLE text</title>
<script src="phaser.min.js"></script>
<script src="first-text.js"></script></html>

Phaser 3.90 · Licença do Phaser

class FirstText extends Phaser.Scene {
  preload() {
    this.load.json('story', 'story/story.json');
    this.load.on('loaderror', file => console.error('Cannot load', file.src));
  }
  create() {
    const story = this.cache.json.get('story');
    if (!story) { this.add.text(24, 24, 'Cannot load story.json'); return; }
    const locale = 'en';
    const id = 'fd7b61a3-8233-4ba7-8f77-b88b119a91bf';
    const record = story.content.texts[id];
    const translation = story.content.translations[locale]?.[id];
    const message = translation ? translation.message : record.sourceMessage;
    const text = message.segments.map(segment => {
      if (segment.kind !== 'text') throw new Error('Text-only example');
      return segment.text;
    }).join('');
    this.add.text(24, 24, text, {fontSize: '24px', wordWrap: {width: 720}});
  }
}
new Phaser.Game({type: Phaser.AUTO, width: 800, height: 300, scene: FirstText});

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: Text.setText(). Respostas: Text.setInteractive() e pointerdown, cada opção preservando seu ID. End: oculte os objetos de diálogo com setVisible(false) e desative sua entrada; mantenha a cena do jogo em execução.

  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.

// story is already loaded. Keep each optionId on its answer button.
const choice = story.execution.nodes['42edfff8-b8fe-46bf-ae0d-9e2347b6e726'];
for (const optionId of choice.optionOrder) {
  const option = choice.options[optionId];
  console.log(optionId, option.text.textRef); // Resolve text, then create your button.
}
// Inspect the actual purchase check. This particular node is Gold >= 5.
const branch = story.execution.nodes['c1c3c372-0a73-4cd0-851d-ede59d5709bb'];
const gold = 10; // Repeat with 2, using your current game value.
const next = gold >= branch.condition.right.value.value ? branch.whenTrue : branch.whenFalse;
console.log(next.nodeRef);

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.

// preload(): the key is a real VNLE character ID; the file is yours.
this.load.image('807b2957-7bab-4a28-83a4-1f3d1589bbc2', 'assets/portraits/mira.png');
// create(): keep one image for the dialogue bar.
this.portrait = this.add.image(100, 180, '807b2957-7bab-4a28-83a4-1f3d1589bbc2').setVisible(false);
// When showing a dialogue; node is your current dialogue object:
const key = node.speakerRef;
this.portrait.setVisible(Boolean(key && this.textures.exists(key)));
if (key && this.textures.exists(key)) this.portrait.setTexture(key);

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

Mantenha JSON e imagens na pasta web publicada. Os caminhos são relativos à página HTML, a menos que o carregador tenha um caminho configurado. Use os dados em create; preload coloca as solicitações na fila. Confira possíveis falhas de carregamento.

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: