JeuWeb - Crée ton jeu par navigateur

Version complète : Modélisation Dialogues & prérequis
Vous consultez actuellement la version basse qualité d’un document. Voir la version complète avec le bon formatage.
Pages : 1 2
Bonsoir,

je viens vers vous pour parler de modélisation. Je suis en train d'ajouter les dialogues sur mes PNJs, problème: comment modéliser proprement et surtout de manière générique (pour assurer une maintenance et une extension facile) les dialogues?

C'est à dire qui parle en premier? qui dit quoi? comment on sait où on en est dans le dialogue? Comment gérer les Prérequis à des dialogues spécifique?

Ce qui entraîne les questions de la modélisation de Prérequis en général: finalement que se soit pour une quête ou un dialogue sur un PNJ, on a parfois envi de bloqué certains de ces éléments par des conditions (avoir débloqué tel chose, être niveau tant, ou posséder tel objet en n quantité, par exemple).

La réflexion est double, puisqu'il faut pouvoir gérer ça coté serveur et transmettre tout ça (notamment les prérequis) au JS pour l'interface, coté client.


Donc pour ce qui est des dialogues, on peut pensé a faire une liste d'objet coté JS, avec le text, le prérequis éventuel, dont l'indice serait "l'étape" du dialogue. On stock dans une variable lié a l'action en cours l'étape du dialogue, facile.
Par contre comment on définit quel protagoniste parle le premier?

Ensuite coté serveur, j'ai encore du mal a voir comment modéliser (en ruby en l’occurrence) les différents prérequis et a pouvoir faire des combinaisons de ET et de OU entre eux, de manière générique, pour ensuite les transmettre au JS (de quel manière?)

Si vous avez des idées, ou que vous avez déjà étudier la question, ça pourrait être bien de confronter différente méthode et d'en tirer le meilleur partie de chaque.

merci.
La meilleur représentation d'un dialogue pour moi est un arbre décisionnel

exemple :
la base de l'arbre est l'entré de la discussion, généralement dans les RPG, c'est une question du PNJ (que me voulez vous? que désirez vous acheter? etc...)

Ensuite tu as autant de branches que de réponse possible et tu ajoutes les prérequis sur les branches.

Pour modéliser ça je ferais :
- le tronc : une table discussion avec les éléments génériques de la discussion : le PNJ, le pré requis de base par exemple et l'id du premier élément de discussion
- les noeuds : une table discussion_element avec le libellé de la discussion
- les branches : une table discussion_response avec l'id de l’élément "précédent", le libellé, l'id de l'élément "suivant"
- une table discussion_prerequis avec l'id de la réponse et le préquis.

De cette façon, devant un PNJ tu recherches la discussion via son id, tu récupères l'élément attaché et les réponses associés en fonction des prérequis.
Pour les prérequis, il faut déjà avoir une idée de ce que ça peut être : un lieu déjà visité,un objet dans l'inventaire, une quête achevée. Pour représenter ensuite en base, je créerais une colonne par type de prérequis

j'espère avoir été un minimum clair et que ça te donne des pistes pour débuter...
Salut,

le fait de faire un arbre me semble assez pertinent, je partais aussi naturellement là dessus, par contre, je peux avoir une réplique dans le dialogue qui est découpé en plusieurs "étapes" sans pour autant changer de locuteur.
Exemple:

"toto : Je suis un peu fatiguer mais je pense bientôt me reposer, vous devriez en faire de même."
"toto : Vous pouvez dormir ici, cela ne me gène pas, faites comme chez vous."
"Moi : Merci pour votre aide."

Donc d'une part, il n'y a pas un coup sur deux le joueur qui parle, d'autres part il n'y a pas forcement des choix de réponses à chaque fois que le joueur parle.


Après mon gros soucis c'est la modélisation des prérequis et "l’emboîtement" logique (ET/OU) entre eux, le tout de manière dynamique pour que via une interface admin il soit facilement possible d'ajouter/supprimer des prérequis dans l'ordre que je souhaite.
Fais un arbre avec a chaque noeud une structure du type

Auteur : du coup deux noeuds de suite avec le meme auteur permettent de realiser ta demande

Conditions : qui sera un tableau de structures qui représentera tes OU : chaque entrée du tableau si elle est réalisée valide le OU. La structure est aussi un tableau de conditions unitaires qui représentera tes ET. Il faut que toutes les conditions unitaires soient réalisées pour validée la condition (on pourrait faire une modélisation plus subtile combinant et / ou mais est ce pertinent ?)

Choix : qui sera un tableau de structures : chaque structure porte le texte et le noeud fils (si pas de choix et bien une seule entrée dans le tableau)

Voila je sais pas si ça couvre tout
le problème c'est comment faire une classe unique de prérequis qui sache donc les gérer, avec des conditions aussi différente que posséder un objet et "être allé parlé à Tartampion" au moins une fois?

Ensuite, y a le problème de la transmission au client JS. inutile de dire que devoir faire une requête ajax a chaque fois qu'un joueur appuis sur la touche action pour passer au dialogue suivant pour vérifier de potentiel prérequis n'est pas du tout une bonne idée!
Ça voudrais dire qu'il faudrait passer d'une manière ou d'une autres les prérequis et les vérifier en JS!?

Enfin, le fait de pouvoir combiner des ET et des OU me semble pourtant intéressant au niveau des possibilités.
Salut (et oui je suis de retour avec mes questions ^^)

Pour tes dialogues, tu veux qu'il y ait un minimum basique pour chacun des pnj que tu rencontreras ou pour certains en particulier?

Pour ma part, je n'ai pas vraiment de conseil de programmation à te donner, mais plutôt dans "l'esthétique" de la chose. Genre ta question "savoir qui parle". Tu peux probablement faire intervenir une bulle de dialogue, ou le basique texte avec le nom de celui qui parle, non?

Après, je comprends le principe de l'arbre et du raisonnement générique, mais si tu veux une évolution ou une adaptation personnalisée, ça va être tendu du string (passé moi l'expression qui pourtant convient bien). Tu peux toujours faire les basiques "objets/textes" (je ne connais pas le bon vocabulaire pour ça), concernant des marchands, aubergistes, pnj useless (avec des phrases aléatoires du genre "il fait beau"), mais tu vas vite atteindre tes limites je pense.

Bien sûr, je reste dans mon expérience de RPG maker, mais ce ne serait pas, certes plus long, mais finalement plus pratique d'avoir un texte évolutif accroché à un perso?
Justement, le but est que j'ai un arbre de dialogue possible pour chaque pnj, du coup c'est très permissif, surtout si j'arrive a faire les prérequis comme je le veux, je pourrais avoir des dialogues pour un même pnj qui varie en fonction de condition que je définis Wink

Sinon, bien que je suis pas très design, c'est moins la partie "esthétique" le problème, c'est plutôt la modélisation du code. C'est comme essayé de recoder rpg maker (en mieux :p)
xD

Je vois, en fait, j'avais mal compris le truc, je pensais que tu voulais généraliser pour essayer de réécrire le moins de dialogue possible ^^"

Mais du coup, à partir de ton arbre de base, pour tous les pnj, est-ce que tu ne peux pas intégrer des évènements qui justement te feront passer d'une branche de dialogue à une autre? Une sorte de condition commune à tous? (Je sais, une noob parlant de programmation, c'est comme un aveugle décrivant un feu d'artifice, ça peut faire rêver mais ça sert à rien ^^' )
(L'aveugle peut décrire les sons du feu d'artifices!)
Puisque tu pars d'un arbre, pourquoi ne pas modéliser cela en XML? Chaque noeud serait alors un dialogue (<dialog>) comprenant un sous-noeud avec les prérequis (<requires><require{1,n}></requires>), un autre sous-noeud avec le texte du dialogue (<text>Salutations joueur. J'ai perdu mon unique marteau. Je l'ai laissé en plein milieu du volcan, peux-tu aller le chercher?</text>) et enfin, un dernier noeud avec les évènements débloqués (<unlocks><unlock{0,n}></unlock>).

Ainsi, tu pourras utiliser Xpath pour récupérer tous les noeuds "dialog" dont les prérequis sont remplis. Ensuite, charge à toi de trouver comment ordonner ces noeuds (aléatoire, ou prépondérance de certains prérequis face à d'autres), puis tu choisis un seul de ces noeuds. Tu lis le texte (ou l'affiche à l'écran), et une fois le texte affiché, les "unlock" du "unlocks" sont débloqués, donc de nouveaux prérequis seront activés.

Pour les noeuds require/unlock, tu peux utiliser un modèle du genre <require name="rencontrer-le-joueur"/> et <unlock name="rencontrer-le-joueur"/>. Ainsi, le "dialog" qui contient le "require" ci-dessus ne pourras pas être lu si un "unlock" contenant le même nom n'a pas été rencontré avant (donc, au départ, tu ne pourras lire que les noeuds "dialog" qui n'ont aucun "require").


Vois-tu l'idée? Pour la mise en oeuvre, XSLT (j'suis ch**t avec XML/XSLT hein? :p) devrait t'aider. Il existe, je pense mais je n'en suis pas sûr, des interpréteurs javascript du XSLT. Sinon, tu peux très bien utiliser directement XMLHttpRequest pour récupérer le XML du dialogue, puis récupérer la XMLResponse pour traiter le XML comme un DOM document dans ton javascript (et avoir accès aux habituels children[...], getAttribute et getElementsBy...).


Enfin, pour complexifier, tu peux:
  • Ajouter un noeud "speakers", contenant des sous-noeuds "speaker". Chaque "speaker" possède un attribut (name) qui indique le nom du PNJ qui peut lire ce dialogue (c'est un genre de pré-requis spécial: le prérequis pour lire le dialogue, c'est que la personne qui parle doit être tel ou tel PNJ). Idem pour les dialogues que le joueur peut utiliser: "speaker" peut voir son "name" définit à "player" si le joueur a le droit de lire ce dialogue (note que, pour le joueur, tu vas récupérer une liste de dialogues possibles sur la abse des <requires>, et laisser le joueur faire son choix dans cette liste de dialogues: ce n'est pas à toi de choisir pour le joueur, contrairement au PNJ où tu DOIS choisir; enfin, si le joueur n'a aucun "dialogue", tu peux passer directement son tour, tu n'auras donc pas une alternance forcée entre PNJ et joueur)

  • Ajouter un noeud "date", qui te permet de mettre en place un système d'expiration du dialogue: si le dialogue entre les deux joueurs a duré plus de X secondes ou minutes (ou s'il y a eu plus de X échanges c'est à dire plus de X <dialog> lus, alors ce <dialog> possédant un <date> ne pourra plus être lu, ou à l'inverse, il ne pourra être lu qu'après ces X échanges ou X secondes). <date> serait alors une sorte de prérequis basé sur le temps, et non sur les évènements.

Avec cela, je pense que tu auras un système de dialogues assez robustes, facile à entretenir et à utiliser, qui pourra également se dérouler hors-ligne (une fois le XMl téléchargé, aucun appel au serveur n'est fait, sauf si tu le demandes explicitement). Enfin, tu pourras même traduire le jeu dans d'autres langues en traduisant les <text> de ton XML.

Note importante qui me vient à l'esprit:
Dans ce schéma, utilisant "<require>" et "<unlock>", la structure du XML serait:

<root>
<dialog><!-- 1 .. n -->
<requires>
<require name=""/><!-- 0 .. n -->
<text>blabla</text>
<unlocks>
<unlock name=""/><!-- 0 .. n -->
</unlocks>
</requires>
</dialog>
</root>

Donc, on n'exploite pas le coté "arbre" du XML (à cause du <dialog{1..n}>). En d'autres mots, tu peux avoir des plusiques <dialog> qui seront débloqués (ils sont "enfants") après un autre <dialog>, mais de la même façon, un "<dialog>" possède plusieurs prérequis indépendants (plusieurs "parents"): ce n'est donc pas un arbre, mais un graph.

La structure "arbre pur" serait plutôt:

<root>
<dialog author="PNJ">
<text>Salut joueur!</text>
<dialogs>

<dialog author="PNJ">
<text>Comment vas-tu?</text>
<dialogs>...1</dialogs>
</dialog>

<dialog author="J">
<text>Salut PNJ qui a perdu son marteau</text>
<dialogs>...2</dialogs>
</dialog>

</dialogs>
</dialog>
</root>
Dans ce schéma-arbre (qui me semble beaaaaucoup moins prétique et moins souple), seuls les <dialog> directement enfants de <root> sont accessibles au début. Une fois qu'un <dialog> est lu, seuls les dialogues contenus dans le <dialogs> peuvent être lus.
Ainsi, au début, seule la phrase "Salut joueur" peut être lue. Le jeu va donc la lire. Une fois lue, cela débloque 2 dialogues: "Comment vas-tu" et "Salut PNJ qui a perdu son marteau". L'un de ces deux dialogues est alors lu (au hasard?). Si le 1er est lu, cela débloque le contenue de "...1", si c'est le 2nd, cela débloque le contenu de "...2" etc.
Ce deuxième système est, à mon avis:
  • Plus facile à mettre en place grâce au coté "arbre"
  • Moins sympatique à entretenir (pas de possibilité de faire rejoindre deux branches de l'arbre)
  • Moins sympatique à utiliser en tant que joueur (si on choisit un dialogue donné, on sait qu'on ne pourra plus tomber sur certaines autres phrases)

Toutefois, il évite d'avoir des risques de "bouclage" (une séquence de dialogue répétée à l'infinie). Dans le cas du graphe, si un dialogue A requière l'évènement B (qui a déjà eu lieu), que le joueur choisit C, et que C ne débloque aucun évènement, alors le dialogue A pourrait être re-lu.
Pour éviter cela, il te faudrait faire une "liste" des dialogues déjà lus, pour interdire leur re-lecture.

A mon avis, tu as matière à travailler maintenant :p Bonne chance.
(Qui osera me répondre tl;dr? O.O)
En fait j'ai appris cette année le xsl/xstl/xpath, ce n'est pas le problème, le truc c'est juste que le XML c'est pompeux pour rien, et du coup sur le réseau, c'est bcp de ko à faire télécharger pour rien. Je pense rester en JSON Wink

Après le fait que le joueur puisse trifouiller pour trouver des dialogues et les afficher à la limite je m'en fiche puisque les actions importantes comme la validation de quête ou le fait d'ajouter une quête sera vérifié par le serveur.

Du coup j'ai juste à lié une réponse du joueur au dialogue suivant, ce qui me permet d'imbriquer/boucler comme je veux sans être forcement coincé dans un arbre comme tu le faisais remarquer.

Le fait de pouvoir relire des dialogues me gène pas au contraire. Si on regarde Mass Effect, cela ne gène absolument pas de pouvoir relire les même dialogue, au contraire ça permet au joueur de chercher une information ou de revoir un truc qu'il n'a pas compris/entendu.

Mais c'est sur qu'il y a du taf, je fini de modéliser là et après on passe à l'implémentation^^

J'ai hate que ça soit fait, ça fera un gros morceau en moins Smile
Pages : 1 2