Como posso implementar árvores de diálogo no meu jogo?

51

Qual é a melhor maneira de implementar um sistema de árvore de diálogo no meu jogo? Eu quero que um NPC dê ao jogador diferentes conjuntos de respostas, algumas que só podem aparecer quando o Jogador tiver um item ou um evento anterior.

Bryan Denny
fonte
2
O BOUNTY é especialmente para boas idéias sobre como lidar com traduções de frases de gatilho e texto de NPC. Para que o NPC possa entender e falar idiomas diferentes, dependendo do jogador que iniciou a conversa. Mesmo com a abordagem de blocos de construção em gamedev.stackexchange.com/questions/31/… , não parece uma boa idéia ter lógica dentro dos repositórios de texto. Mas dividi-los torna muito mais difícil entender o código.
Hendrik Brummermann

Respostas:

17

As árvores de diálogo devem ser feitas usando XML. Você armazena as condições para as respostas e a resposta em árvores aninhadas com uma referência a um arquivo de script se precisar fazer algo mais complexo.

Você deve manter os scripts e o diálogo separados, especialmente se estiver montando um RPG com uma tonelada métrica de conversas. Você pode usar uma biblioteca como simpleXML para ler o arquivo XML.

Há uma pergunta semelhante no SO com um exemplo: https://stackoverflow.com/questions/372915/game-logic-in-xml-files

Raposa
fonte
+1 para XML. Muito melhor do que incorporar no próprio código, permite alterações sem recompilar o código e é um formato padrão que pode ser lido por alguns editores avançados.
precisa
34
XML é apenas um formato (e, na IMO, um formato ruim). Realmente, o que esta resposta diz é: "Crie uma linguagem de domínio pequeno que contenha lógica e fluxos básicos, mas que consista principalmente no seu diálogo e analise-o". Dessa maneira geral, eu concordo com esta resposta.
Ipsquiggle
5
Exatamente, XML é apenas o contêiner, você também pode (e definitivamente mais legível por humanos e editável por humanos) implementar isso usando Lua ou outras linguagens de script.
LearnCocos2D
4
O XML é caro para analisar e ocupa muita memória. É bom usá-lo como um formato de armazenamento, mas eu escreveria um utilitário que converte as árvores de diálogo em um formato binário usado em tempo de execução. Se você estiver em um PC e não se importar com o uso de memória, pode ser bom, mas em qualquer outra plataforma, o custo da memória será suficiente.
BigSandwich 19/09/10
11
-1 para XML. Concordo com @Ipsquiggle e @BigSandwich
o0 '.
20

Eu procuraria incorporar uma linguagem de script como lua ou ruby ​​e interações de diálogo de codificação nisso.

Assim, um script de diálogo pode se parecer com:

switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!"
    case 1:
        showDialog "And stay gone!"
    case 2:
        if playerHasObject "dog"
            showDialog "Thank you!"
        else
            showDialog "Liar!"

Isso também funciona bem para codificar a IA e outras coisas simples que são úteis para ajustar durante o tempo de execução. Você pode até adicionar um editor incorporado ao seu aplicativo que possa ser chamado durante a execução de depuração (ou como um ovo de Páscoa).

BarrettJ
fonte
11
Eu prefiro isso ao XML direto, pois você pode adicionar lógica. Mas eu diria que o texto em si provavelmente deveria estar em XML e não no código. (mais fácil de editar, localizar para outros idiomas etc).
Iain
se você precisar de localização / edição mais fácil, poderá agrupar o texto em uma função que grava o texto em anexo em um arquivo separado, como a função / macro tr (QString) no Qt. pepper.troll.no/s60prereleases/doc/linguist-hellotr.html
Dispositivo de pregagem de
o que impede você de usar atributos ou tags extras no xml para simular a lógica aqui?
lathomas64
16

No jogo Stendhal, usamos uma máquina de estados finitos para implementar NPCs.

O diagrama a seguir mostra um pequeno exemplo do tutorial de como escrever missões .

FSM com os estados IDLE, ATTENDING e QUEST_OFFERED

No início, o NPC está em um estado ocioso e pode estar andando por aí. Um jogador pode iniciar uma conversa dizendo "oi" e o NPC passará ao estado ATENDO. Nesse estado, ele responde a perguntas sobre o seu "trabalho" e oferece algum jogo "ajuda". O jogador pode pedir uma missão e o NPC irá declarar QUEST_OFFERED esperando que o jogador aceite ("sim") ou recuse ("não").

Definimos um conjunto de condições que podem ser anexadas às transições. Por exemplo, concluir uma missão pode ser possível apenas se uma condição PlayerHasItemWithHimCondition for atendida.

Após a execução da transição, o NPC pode dizer algum texto e / ou executar uma ação. Semelhante às condições, definimos um conjunto reutilizável de ações como EquipItemAction, que é usado para recompensar a missão de um jogador.

É possível combinar várias condições usando AndCondition , OrCondition e NotCondition . Geralmente, existem várias ações a serem executadas na conclusão da missão, portanto há também uma classe MultipleActions .

Embora a implementação real em Stendhal sofra por não ser traduzível em outras línguas (humanas) facilmente, acho que o conceito geral é bom.

Hendrik Brummermann
fonte
5

Você pode dar uma olhada na ferramenta Dlgedit do mecanismo de RPG de código aberto Adonthell . É muito avançado e deve conter tudo o que você precisa (incluindo fontes;))

Koonsolo
fonte
5

Penso que, para adicionar traduções, você ainda pode usar XML para a lógica, conforme declarado acima . Ao entrar nesse tipo de complexidade, escreva sua própria ferramenta de diálogo. O texto do seu diálogo seria armazenado como uma chave para um banco de dados que você poderia trocar dependendo do idioma que deseja exibir.

Por exemplo, você poderia ter:

<dialogue id="101" condition="!npc.carsFixed">
  <message>Localize.FixMyCar</message>
  <choices>
    <choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure">
      <command>hero.carFixingSkills += 1</command>
      <command>npc.carFixed = true</command>
      <command>hero.playSmokeAnimation()</command>
      <command>nextDialogue = 104</command>
    </choice>
    <choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix">
      <command>nextDialogue = 105</command>
    </choice>
    <choice id="Localize.FixYourself">
      <command>npc.likesHero -= 1</command>
    </choice>
  </choices>
</dialogue>

Em seguida, o representante de texto da missão substitui "Localize.FixMyCar" pelo texto traduzido adequadamente.

Sua ferramenta exibia o que o player veria em um idioma selecionável ao lado do XML bruto editável.

Da mesma forma, você pode usar algo como isso no exemplo que você referenciou :

npc.add(ConversationStates.ATTENDING,
        ConversationPhrases.QUEST_MESSAGES, 
        null,
        ConversationStates.QUEST_OFFERED, 
        Localization[ "BringMeABeer" ],
        null);

Se suas chaves forem descritivas o suficiente, não ter o texto completo não deve ser um problema.

Algo assim também pode ser útil:

Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];
toddw
fonte
4

Os dados direcionam seus caracteres com scripts LUA ou mesmo arquivos XML. Ao interagir com um NPC, pegue o arquivo que está anexado a ele, leia-o, ajuste-o para quaisquer variáveis ​​do jogo que possam ter sido acionadas e produza a resposta válida.

O maior ganho ao fazê-lo dessa maneira é que você pode facilmente entrar e manipular a caixa de diálogo, adicionar novos caracteres etc. Você também evita estragar sua base de código com uma lógica especial ao lidar com todos os casos.

David McGraw
fonte
11
É Lua, não LUA. :)
RCIX 16/09
2
Eu fiz isso só por você, cara. ;)
David McGraw
4

Se você usa XML, certifique-se de criar uma pequena ferramenta para editar o arquivo XML. Caso contrário, você ficará louco.

zooropa
fonte
Se já não existe uma ferramenta para editá-lo, não faz sentido usá-lo em primeiro lugar: crie seu próprio formato também!
o0 '.
3

Se você possui um conjunto bastante profundo de árvores de diálogo, use o ChatMapper . Eles têm uma versão gratuita com todos os recursos e a ferramenta permite exportar suas árvores de diálogo para XML. Eu o uso e é uma excelente maneira de visualizar e organizar árvores de diálogo complexas.


fonte
1

Se suas caixas de diálogo tiverem alguma complexidade, o mais importante para a implementação da caixa de diálogo é uma maneira de entender a complexidade de sua interação. Eu recomendo um editor de nó de algum tipo para visualizar isso, embora eu não tenha bons sistemas abertos para recomendar.

Aaron Brady
fonte
1

Eu acho que você usa sua própria linguagem de script para direcionar esse tipo de jogo (se não, você deveria). Em seguida, expanda seu script para manipulação de diálogos também.
Você pode trabalhar com outras variáveis ​​do jogo durante a criação da lógica dos diálogos. Motores de jogos são como Lego. Você programou apenas tijolos e o script os utiliza. Não importa se você cria algum interpretador ou compilador de script. Mas o script é sempre útil.

samboush
fonte
0

Autômato simples pode fazer:

(dialogueline_id, condition) -> (next_id, response)

Pode ser algo como isto:

(1, troll is hungry?) -> (2, say "troll be hungry")
(2, player has bananas?) -> (3, say "hey, you have bananas!")
(3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll))
(2, player does not have bananas?) -> (-1, say "go away!!!")

No jogo, você encontra o id e tenta combinar o id e a condição.

Você precisa modelar as condições e ações. Por objetos, ponteiros de função, XML ...

Um bom editor de diálogo também será útil.

user712092
fonte