Accueil > Bienvenue > Journal de bord > Un Visual Novel sous forme de graphe ?
Un Visual Novel sous forme de graphe ?
dimanche 15 octobre 2023, par
Toutes les versions de cet article : [Deutsch] [English] [français]
Je n’ai pas abandonné le projet Neuf Soleils. J’ai commencé à l’écrire en utilisant l’environnement de développement RenPy et j’ai un petit peu avancé.
Quand le code colle trop à l’histoire
Cependant, je bute régulièrement sur une limitation de RenPy, mais qui je crois est une limitation plus générale des outils de développement basés sur du texte : le fait d’écrire une histoire avec un outil textuel, incite fortement à écrire une histoire linéaire. C’est la nature du médium texte qui veut cela. Le texte se lit de haut en bas et de gauche à droite, paragraphe par paragraphe. Quand on écrit une histoire, il y a un début et une fin, et des développements. Les apartés ou les flashbacks se font au moment où l’auteur souhaite les voir apparaître. Le récit, qu’il soit choral ou chaotique, progresse page par page vers la conclusion.
Le jeu vidéo s’affranchit facilement de cette contrainte. Le programmeur peut présenter des éléments de narration au joueur et lui laisser le choix de l’ordre dans lequel il va les parcourir, voire lui laisser le choix d’en sauter certains. Il va rajouter ensuite des contraintes qui vont déterminer l’ordre dans lequel le joueur est censé faire les actions - par exemple, pour ouvrir une porte, le joueur devra d’abord trouver une clé, et tant qu’il ne l’a pas trouvée, la porte (et l’histoire qu’il y a derrière) resteront fermées. Tout l’art du créateur de jeu consiste à contraindre sans en avoir l’air.
Ceci peut avoir lieu car il y a une distance importante entre le code et l’histoire. Dans le jeu standard, le code définit la logique du jeu (on appelle cela le moteur), et l’histoire est codée à côté, sous diverses formes. Ceci n’est pas le cas dans le cadre du Visual Novel (VN ci-après). Quand on écrit un VN, le travail d’écriture, même si c’est du code informatique, suit de très près l’histoire telle qu’elle se déroule. On divise son histoire en scènes, avec des liens entre les scènes, et les choix du joueur sont généralement très contraints : les choix que fait le joueur mènent vite à des culs-de-sac (game over) ou à avancer dans l’intrigue principale là où l’auteur veut le voir aller. Ceci pose un problème de rejouabilité : quand le joueur a parcouru le VN une première fois, il n’a pas beaucoup d’intérêt à y retourner.
Pour améliorer la rejouabilité, les développeurs imaginent souvent différentes fins possibles, auxquelles le joueur peut accéder en faisant différents choix en cours de partie. On peut donc dire que, d’un point de vue organisationnel, un VN ressemble généralement à un arbre avec quelques grosses branches. Utiliser un langage de programmation textuel se prête bien à faire un arbre avec peu de branches.
Une structure non linéaire
Dans le cas de Neuf Soleils, une caractéristique est que le jeu suit une structure cyclique et non linéaire. Le cycle principal est celui de la semaine (Lun -> Mar -> Mer... -> Dim -> Lun...) à partir duquel se détachent des micro-histoires, qui sont déclenchées par le début de chaque journée. Chaque micro-histoire dépend également d’événements déclenchés dans d’autes micro-histoires (par exemple, le joueur va rencontrer une vieille dame le samedi, mais il ne peut lui parler que s’il l’a soutenue dans une altercation routière qui a lieu les matins de semaine), ou dans des itérations précédentes de la micro-histoire elle-même.
Dans ce jeu, le plus important c’est le temps qui passe, mais j’aurais pu aussi imaginer une structure où le joueur a la liberté de se déplacer dans différents lieux, et de vivre les micro-histoires à partir de ces lieux (ce qui serait plus proche d’un jeu d’aventure en déplacement libre, du genre de Dans Mon Quartier, le jeu développé par Nils).
Cela rend l’écriture via RenPy complexe. Non seulement la "narration" d’ensemble n’est pas linéaire, mais en plus dans les micro-narrations interviennent des éléments d’autres micro-narrations ! Ceci rend le suivi du projet complexe : comment stocker les informations, comment visualiser les boucles...
Ce qui aurait pu être un arbre ressemble en fait beaucoup à un graphe, avec des retours en arrière.
Un exemple en version texte
Voici un petit exemple. Dans le code ci-dessous, le narrateur (joueur) et un personnage dénommé Eileen (c’est le nom du personnage du tutoriel de RenPy) se baladent dans un parc et discutent des événements. Eileen demande au narrateur ce qu’il pense de ceux-ci, le narrateur n’a pas envie de répondre, mais Eileen insiste. Si le narrateur tarde trop à répondre, Eileen n’est pas contente et les deux personnages se brouillent, sinon Eileen est contente et prend le narrateur dans ses bras.
Le code RenPy fait 90 lignes, contient une boucle sur le menu, et ressemble à ceci :
init python:
import random
define Eileen = Character('Eileen', color="#c8ffc8")
define m = Character('Me', color="#c8c8ff")
label start:
scene park
show eileen happy
$ eileen_love = 0
$ label1_num = 0
$ label2_num = 0
"Eileen and I walk in the park."
"We are discussing the latest events."
Eileen "What do you think of the latest events?"
label .label1:
$label1_num += 1
"What should I answer?"
menu:
"I don't know" if label1_num == 1:
jump .label2
"I really don't know" if label1_num == 2:
jump .label2
"I have no idea, honest" if label1_num > 2:
jump .label2
"I think the events brought us closer" if label1_num > 1:
jump .label3
label .label2:
$ eileen_love -= 1
show eileen angry
$ label2_num += 1
if label2_num == 1:
"Eileen frowns at me. Maybe I should find a better answer..."
if label2_num == 2:
"Eileen looks angry. Come on."
if label2_num > 2:
$ randval = random.randint(0,3)
if randval == 0:
"Eileen sighs."
elif randval == 1:
"Eileen raises her eyes."
else:
"Eileen looks really pissed."
jump .label1
label .label3:
$ eileen_love += 2
if eileen_love > 0:
show eileen happy
"Eileen gives me a hug."
else:
Eileen "Yeah, right."
return
Ce qui saute aux yeux tout de suite, c’est la difficulté de suivre les différents embranchements du programme, en particulier le menu principal. L’astuce qui consiste à avoir une variable "eileen_love" qui est décrémentée de 1 à chaque fois que le joueur hésite, et incrémentée de 2 quand il finit par répondre, ce qui le fait "gagner" s’il répond dès le 2e tour ou "perdre" s’il attend un tour de plus, n’est pas évidente à comprendre.
De plus, pour que le personnage d’Eileen ait un dialogue plus réaliste dans le cas où le personnage principal insiste pour ne pas répondre, une dose d’aléatoire est introduite dans un de ses réponses, mais la syntaxe RenPy est peu maniable, obligeant à introduire une variable.
On note également que la programmation d’éléments de narration qui dépendent des itérations dans les boucles (par exemple, quand on passe pour la première fois à tel endroit de la narration, on peut choisir telle réponse, puis si on passe une deuxième fois, on peut choisir telle autre réponse...) nécessite d’introduire manuellement des compteurs, ce qui est peu pratique.
Une idée : le représenter sous forme de graphe...
Voici à présent le même programme représenté sous la forme d’un diagramme de flot de données :
N’est-ce pas beaucoup plus simple à interpréter ?
Dans le détail : proposition d’une syntaxe visuelle
Des raccourcis de syntaxe permettent de gérer les éléments de dialogue devant apparaître à différentes itérations d’une boucle :

Un autre raccourci est proposé pour générer un élément de dialogue "aléatoire" (le programme choisit aléatoirement un des éléments entre parenthèses) :

Des éléments standard de diagrammes de flot de données sont utilisés pour présenter les différents éléments du jeu :
- La narration (monologue intérieur du narrateur)

- Les dialogues (entre les personnages et éventuellement le narrateur, ceci reste à préciser pour mieux visualiser quel personnage parle : utilisation de couleur ? De logo représentant le personnage ?)

- Les menus (choix manuels du joueur)

- Les embranchements automatiques

- Le stockage ou la mise à jour de variables

- L’affichage des graphismes

Les séquences, sauts et boucles sont représentés par les flèches, qui peuvent être agrémentées de texte qui sera interprété comme du code (dans le cas d’un embranchement automatisé) ou d’une réponse possible du narrateur (dans le cas d’un menu).
On pourra aussi utiliser les éléments standard des diagrammes de flots de données pour faire des sauts entre scènes, etc.
Ce protocole reste à affiner.
Quel logiciel utiliser ?
Etant entendu que je n’ai pas les capacités (temps, essentiellement) de développer mon propre logiciel de création de graphe (même si en théorie je pourrais le faire, par exemple avec Processing), pour "écrire" (peut-être que le terme "dessiner" serait plus approprié ?) ce programme j’ai utilisé un logiciel libre appelé Dia. J’ai hésité avec Yed, un logiciel propriétaire très ergonomique.
Ces deux logiciels génèrent des vrais graphes, c’est à dire qu’il est possible d’utiliser les fichiers produits (au format interéchangeable XML) comme entrée d’un "traducteur" qui fera la conversion en code RenPy (ou en tout autre chose : pourquoi pas directement en code Neo Geo Pocket ?). Dia est assez ancien, il est un peu moins ergonomique que Yed (en particulier pour ajouter du texte aux liens entre deux éléments de graphes), mais il a deux avantages : d’une part, c’est un logiciel libre, et d’autre part, son ancienneté fait que son format de fichier est très stable, donc si je développe un traducteur pour Dia, il marchera encore dans 10 ans.
J’aime bien cette idée et je pense que je vais travailler dessus !