Introduction à Loreline
Loreline est un langage de script open-source pour écrire de la fiction interactive. Il gère les dialogues à embranchements, les choix de la personne qui joue, les personnages et l'état de l'histoire dans une syntaxe conçue pour être lisible par les autrices et auteurs tout en offrant de vrais outils de programmation (variables, conditions, fonctions) quand l'histoire en a besoin.
Vous pouvez l'intégrer partout : moteurs de jeu, applications web ou projets autonomes. Il s'adapte à vos outils, les histoires que vous écrivez restent portables.
À quoi ça ressemble
Voici un script Loreline minimal :
Une bonne odeur de café flotte dans la salle.
barista: Salut ! Comment tu vas aujourd'hui ?
choice
Je passe une excellente journée
barista: Formidable ! Le café va la rendre encore meilleure.
Besoin de caféine...
barista: N'en dis pas plus ! Laisse-moi m'en occuper.
Tu t'appelles Alex, non ?
barista.name = "Alex"
barista: Oh, je ne m'attendais pas à ce que tu t'en souviennes !
- Le texte seul est de la narration.
barista: ...est un dialogue prononcé par un personnage.choiceprésente des options, et l'indentation détermine ce qui se passe après chaque choix.
C'est le schéma de base. Le Guide d'écriture aborde cela en détail.
Simple mais explicite par design
Loreline réduit la ponctuation au strict minimum. Le texte narratif et les dialogues s'écrivent tels quels, sans aucun délimiteur particulier. Passer à une autre section, c'est une simple flèche ->. Assigner une variable, c'est juste =. Les conditions n'ont pas besoin d'un mot-clé de fermeture, l'indentation suffit. Un choix peut inclure un if en fin de ligne pour n'apparaître que si la condition est remplie.
D'un autre côté, les principaux éléments structurels (beat, choice, character, state, if, else) sont des mots-clés en anglais courant plutôt que des symboles. Ils se comprennent d'un coup d'œil, sans avoir besoin d'apprendre ce que signifie chaque caractère spécial. C'est un choix délibéré : des mots lisibles plutôt que de la ponctuation cryptique.
D'autres outils s'appuient davantage sur les symboles ou les délimiteurs : Yarn Spinner utilise <<if>>...<<endif>> et <<set>> ; Ink dispose de ses propres marqueurs pour les choix, les knots et les diverts. Loreline essaie de rester au plus proche du texte brut, et l'éditeur est suffisamment intelligent pour appliquer une coloration syntaxique correcte avec aussi peu d'indices :
Le café est calme ce matin.
choice
Commander un café
cafesCommandes += 1
if cafesCommandes > 3
barista: <concerned> Ça fait quand même beaucoup de café aujourd'hui...
else
barista: Un de plus, c'est parti !
Commander un déca if cafesCommandes > 2
barista: Bonne idée. Je t'en fais un bon.
Pour les autrices et auteurs, le résultat est un script qui se lit presque comme du langage naturel, avec moins de bruit visuel entre l'histoire et sa structure.
Structure de l'histoire
Une histoire est organisée en beats, des sections nommées qui fonctionnent comme des scènes ou des chapitres. On passe de l'une à l'autre avec ->, ou on en appelle une avec BeatName() pour faire un détour qui ramène à l'endroit de l'appel une fois terminé :
beat EnterCafe
Le soleil du matin traverse les fenêtres du café.
barista: Bienvenue ! Je ne crois pas t'avoir déjà vu.
TakeOrder()
barista: Bon café !
-> EndScene
beat TakeOrder
barista: Alors, qu'est-ce que je te prépare ?
Les personnages sont des éléments de premier plan : on les déclare avec des champs qui peuvent être lus et modifiés tout au long de l'histoire :
character barista
name: Alex
mood: friendly
friendship: 0
Les données persistantes vivent dans un bloc state. Les conditions (if, else if, else) permettent à l'histoire de réagir aux décisions prises, et les choix peuvent porter des conditions en ligne pour afficher ou masquer des options dynamiquement.
if barista.friendship > 2
barista: Ah ! Je suis content de te voir :)
Autres fonctionnalités
Au-delà de la syntaxe de base, Loreline propose aussi :
- Tags de texte : attacher des métadonnées comme
<friendly>ou<whisper>à n'importe quelle ligne de dialogue, ou utiliser des tags pour formatter le texte, que le moteur de jeu peut interpréter comme il le souhaite.
barista: <friendly> Je suis content de te voir !
sarah: Ça sera un <strong>café très fort</strong> pour moi, aujourd'hui.
- Texte dynamique : insérer des variables avec
$et${}, et la pluralisation automatique avec$count pièce|pièces.
sarah: Tu savais que c'est $barista.name qui gère le café à côté ?
james: Ah super, allons-y, il faut que je termine ma lecture de ${james.currentBooks[0]}.
barista: Tu as pris $cafesCommandes boisson|boissons aujourd'hui.
- Alternatives : varier le texte au fil des visites grâce à cinq modes de sélection (
sequence,cycle,once,pick,shuffle).
pick
Un air de jazz s'échappe doucement d'une enceinte sur l'étagère.
--
La machine à espresso siffle et crépite.
--
Des rires fusent d'une table près de la fenêtre.
- Fonctions : plus de 60 fonctions intégrées pour les mathématiques, la manipulation de texte, les tableaux et les maps. On peut aussi définir ses propres fonctions, directement dans un script Loreline ou les exposer depuis le moteur hôte.
barista: Ta commande sera prête dans $random(2, 5) minutes !
// Affichera un nombre aléatoire entre 2 et 5
- Imports : répartir une histoire sur plusieurs fichiers
.lorpour organiser les gros projets.
import inventaires
import personnages
// Histoire qui utilise les inventaires (inventaires.lor)
// et les personnages (personnages.lor)...
- Sauvegarde et restauration : sérialiser l'état complet de l'histoire à tout moment et le restaurer plus tard, incluant la position d'exécution, les variables, les champs des personnages et la progression générale.
// Sauvegarder l'état (par exemple à un point de contrôle)
const saveData = interpreter.save();
localStorage.setItem('save', JSON.stringify(saveData));
// Plus tard, restaurer et reprendre
const saved = JSON.parse(localStorage.getItem('save'));
interpreter = Loreline.resume(script, onDialogue, onChoice, onFinish, saved);
- Localisation : une fonctionnalité de premier plan du langage : étiqueter les lignes avec des
#clesdans le script, fournir des fichiers de traduction.lorpar langue, et l'interpréteur les substitue à l'exécution. Pour en savoir plus, consultez le guide de localisation.
Plateformes et intégration
Loreline est compatible avec n'importe quel moteur C# (y compris Unity), C++, Javascript, Typescript, Python, Lua ou encore JVM. Il s'utilise de la même manière partout : charger un script Loreline, puis le jouer en fournissant des callbacks pour les dialogues, les choix et la fin de l'exécution.
Toutes ces cibles partagent une base de code commune écrite en Haxe, ce qui garantit un comportement cohérent d'un langage à l'autre et permet de livrer les mises à jour partout simultanément sans différence majeure de fonctionnalité. Une batterie de plus de 160 fichiers de tests couvre le runtime et contribue à sa fiabilité au fil de l'évolution du langage.
import { Loreline } from 'loreline';
const script = Loreline.parse(source);
Loreline.play(script,
// Appelé pour afficher un dialogue
(interp, character, text, tags, callback) => {
if (character) {
const name = interp.getCharacterField(character, 'name');
console.log((name || character) + ': ' + text);
} else {
console.log(text);
}
callback();
},
// Appelé pour afficher un choix
(interp, options, callback) => {
options.forEach((opt, i) => {
if (opt.enabled) console.log(' [' + (i + 1) + '] ' + opt.text);
});
callback(0);
},
// Appelé en fin d'exécution
(interp) => {
console.log('--- The End ---');
}
);
| Plateforme | Notes |
|---|---|
| JavaScript / TypeScript | Fonctionne dans Node.js et le navigateur. Disponible en tant que package npm. |
| C# / .NET | S'intègre avec Unity, Godot (.NET) et tout projet .NET. |
| C++ | Bibliothèque autonome sans dépendances externes. |
| Python | Fonctionne avec Python 3.8+, sans dépendances externes. |
| Java / JVM | Fonctionne avec Java 8+ (et Kotlin). Un seul JAR sans dépendances externes. |
| Lua | Fonctionne avec Lua 5.1+, sans dépendances externes. |
| Haxe | Disponible en tant que package haxelib avec accès à l'API complète. |
Jetez un œil aux guides d'intégration pour les instructions de configuration dans chaque langage.
Outillage
- Extension VS Code : coloration syntaxique et panneau de prévisualisation en direct pour les fichiers
.lor. - Atelier en ligne : écrivez et exécutez des scripts Loreline directement dans le navigateur.
- CLI : un outil en ligne de commande pour exécuter les fichiers
.lor, disponible pour macOS, Linux et Windows.
Comparaison avec Ink et Yarn Spinner
Ink et Yarn Spinner sont les deux autres outils couramment utilisés pour le récit interactif. Chacun adopte une approche différente de la syntaxe et de la structure.
Cette comparaison ne prétend en aucun cas qu'un outil est meilleur ou moins bon qu'un autre. Ink et Yarn Spinner sont matures, bien documentés et ont été utilisés dans des jeux publiés depuis des années. Loreline est plus récent et adopte une approche différente. Le meilleur choix dépend de la familiarité de l'équipe, du moteur cible et du style de script qui correspond le mieux à la façon dont on veut écrire.
Voici le même script écrit dans les trois langages :
state
cafesCommandes: 0
character barista
name: Alex
beat Cafeteria
Une bonne odeur de café flotte dans la salle.
barista: Salut ! Qu'est-ce que je te sers ?
choice
Un café normal
barista: C'est parti !
Un déca if cafesCommandes > 2
barista: Tu passes au déca ? Sage décision.
cafesCommandes += 1
if cafesCommandes > 3
barista: Ça fait quand même beaucoup de café aujourd'hui...
VAR cafesCommandes = 0
=== Cafeteria ===
Une bonne odeur de café flotte dans la salle.
Alex: Salut ! Qu'est-ce que je te sers ?
+ Un café normal
Alex: C'est parti !
+ {cafesCommandes > 2} Un déca
Alex: Tu passes au déca ? Sage décision.
-
~ cafesCommandes = cafesCommandes + 1
{cafesCommandes > 3:
Alex: Ça fait quand même beaucoup de café aujourd'hui...
}
-> DONE
title: Cafeteria
---
<<declare $cafesCommandes = 0>>
Une bonne odeur de café flotte dans la salle.
Alex: Salut ! Qu'est-ce que je te sers ?
-> Un café normal
Alex: C'est parti !
-> Un déca <<if $cafesCommandes > 2>>
Alex: Tu passes au déca ? Sage décision.
<<set $cafesCommandes = $cafesCommandes + 1>>
<<if $cafesCommandes > 3>>
Alex: Ça fait quand même beaucoup de café aujourd'hui...
<<endif>>
===
Les trois scripts racontent la même histoire avec une longueur comparable mais des conventions différentes. Pour un comparatif détaillé fonctionnalité par fonctionnalité, consultez la comparaison détaillée.
Essayer Loreline
Le moyen le plus rapide de commencer est l'Atelier, où vous pouvez écrire et exécuter des scripts Loreline directement dans le navigateur, sans rien installer. Pour aller plus loin, le Guide d'écriture couvre le langage complet pas à pas.