Créez votre premier Visual Novel
Guide étape par étape pour créer un visual novel avec Pixi’VN, couvrant la configuration du projet, la narration, les ressources et l'interactivité.
Ce tutoriel vous guidera à travers le processus de création de votre premier Visual Novel.
À des fins de test, dans ce guide nous allons recréer le visual novel Breakdown en utilisant Pixi’VN. Breakdown est une courte histoire qui possède toutes les caractéristiques qu'un visual novel devrait avoir. Josh Powlison, le créateur de Breakdown, nous a donné la permission d'utiliser sa narration à des fins éducatives❤️.
Puisque Pixi’VN vous donne la possibilité d'écrire votre propre narration en choisissant un ou plusieurs langages narratifs disponibles, des exemples seront proposés pour chaque langage actuellement disponible à chaque étape de développement.
Créer un nouveau projet
Avant de commencer, assurez-vous d'avoir installé les prérequis.
La première étape consiste à créer un nouveau projet. Vous pouvez le faire en exécutant :
npm create pixi-vn@latestpuis en sélectionnant le modèle Visual Novel.
VS Code
Si vous ouvrez le projet avec VS Code, il vous sera demandé de consentir à l'exécution de certaines tâches d'espace de travail et d'installer les extensions recommandées pour le projet. Il est fortement conseillé d'accepter les deux.
Vous trouverez plus d'informations sur les modèles, les tâches et les extensions ici.
Création des personnages
Nous allons maintenant définir les personnages de cette histoire. Pour ce faire, nous définirons dans le fichier /content/characters.ts les personnages que nous utiliserons.
Pour plus d'informations sur la façon de créer et d'utiliser des personnages, vous pouvez consulter : Personnages
import Character from "@/models/Character";
import { RegisteredCharacters } from "@drincs/pixi-vn";
export const mc = new Character("mc", {
name: "Me",
});
export const james = new Character("james", {
name: "James",
color: "#0084ac",
});
export const steph = new Character("steph", {
name: "Steph",
color: "#ac5900",
});
export const sly = new Character("sly", {
name: "Sly",
color: "#6d00ac",
});
RegisteredCharacters.add([mc, james, steph, sly]);Premier brouillon de la narration
Markup
Tous les modèles prennent en charge Markdown et Tailwind CSS, nous allons donc les utiliser pour notre narration.
Nous pouvons maintenant commencer à écrire le « premier brouillon » de la narration du visual novel.
Nous allons créer le premier label appelé start, qui sera le début du jeu. Ensuite, nous pourrons écrire les dialogues qui suivront dans notre visual novel.
Voici l'exemple :
=== start ===
james: You're my roommate's replacement, huh?
james: Don't worry, you don't have much to live up to. Just don't use heroin like the last guy, and you' fine!
mc: ...
He thrusts out his hand.
james: James!
mc: ...Peter.
I take his hand and shake.
james: Ooh, Peter! Nice, firm handshake! The last quy always gave me the dead fish. I already think we'r gonna get along fine.
james: Come on in and...
james: ...
james: I know you're both watching, come on out already!
sly: I just wanted to see what the new guy was like. Hey, you, Peter- be nice to our little brother, or you'll have to deal with *us*.
mc: ...
james: Peter, this is Sly. Yes, that is her real name.
I put out my hand.
sly: I'm not shakin' your hand until I decide you're an all-right dude. Sorry, policy.
mc: Fair enough, I'm a pretty scary guy, or so l've been told.
james: The redhead behind her is Stephanie.
// Example of using Tailwind CSS
steph: <span class="inline-block motion-translate-y-loop-25">Hey</span>! Everyone calls me Steph. I'll shake your hand.
// ...
-> DONEDiviser la narration en labels
Il n'est pas recommandé de créer des labels très longs (même pour des visual novels linéaires), mais il est recommandé de créer plusieurs petits labels et de les « appeler » en cas de besoin avec les fonctionnalités de contrôle du flux narratif.
Pour cette raison, même si dans notre cas notre histoire est linéaire, elle sera divisée en deux labels, le premier étant celui que nous venons de créer (start), tandis que le second s'appellera second_part.
Voici l'exemple :
=== start ===
james: You're my roommate's replacement, huh?
james: Don't worry, you don't have much to live up to. Just don't use heroin like the last guy, and you' fine!
mc: ...
He thrusts out his hand.
james: James!
mc: ...Peter.
// ...
-> second_part
=== second_part ===
She enters my room before I'VE even had a chance to. \\n\\n...I could've just come back and gotten the platter later...
She sets it on a desk. I throw my two paper bags down beside the empty bed.
steph: They got you a new mattress, right? That last guy was a druggie, did James tell you that?
sly: *We're* the reason he got expelled!
steph: Sly! If word gets out about that... well, actually, it wouldn't matter, *he's* the one who shot himself up.
I'm fumbling for a new subject.
// ...
-> DONEMenus de choix
Nous allons maintenant demander au joueur s'il souhaite continuer avec la deuxième partie du visual novel.
To do this, we will set narration.choices to an array of choice options created with newChoiceOption (to jump or call a label) and newCloseChoiceOption (to close the choice menu without navigating anywhere).
Vous trouverez plus d'informations sur les menus de choix ici.
Voici l'exemple :
=== start ===
// ...
You want continue to the next part?
* Yes, I want to continue
-> second_part
* No, I want to stop here
-> END
=== second_part ===
// ...
-> DONEModifier les informations d'un personnage et les utiliser comme variable
Je vais maintenant donner au joueur la possibilité de changer le nom du mc.
Pour ce faire, je demanderai au joueur de remplir une boîte de saisie en utilisant les fonctionnalités de Pixi’VN.
Après avoir obtenu la valeur saisie, vous pouvez définir le nom du personnage en utilisant la valeur obtenue.
Dans ink, _input_value_ est une variable spéciale qui contient la valeur saisie par le joueur. Vous pouvez en savoir plus à ce sujet ici.
Voici l'exemple :
=== start ===
// ...
He thrusts out his hand.
# request input type string default Peter
What is your name?
# rename mc { _input_value_ }
// ...
-> DONENous pourrions maintenant utiliser les noms des personnages au sein des dialogues.
Dans ink, vous pouvez utiliser des crochets (par exemple [sly]) pour tirer parti du mécanisme de remplacement de texte : par défaut, les modèles vérifient si le texte entre les crochets correspond à un id de personnage, et si c'est le cas, le remplacent par le nom de ce personnage.
En JS/TS, vous pouvez obtenir le même résultat en utilisant les littéraux de gabarit avec ${} (par exemple `${sly.name}`).
Voici l'exemple :
VAR steph_fullname = "Stephanie"
=== start ===
// ...
sly: I just wanted to see what the new guy was like. Hey, you, [mc]- be nice to our little brother, or you'll have to deal with *us*.
mc: ...
james: [mc], this is [sly]. Yes, that is her real name.
I put out my hand.
sly: I'm not shakin' your hand until I decide you're an all-right dude. Sorry, policy.
mc: Fair enough, I'm a pretty scary guy, or so l've been told.
james: The redhead behind her is [steph_fullname].
steph: Hey! Everyone calls me [steph]. I'll shake your hand.
She puts out her hand, and I take it.
mc: Thanks, good to meet you, [steph_fullname].
steph: WOW, that is, like, the most perfect handshake I've ever had! Firm, but also gentle. [sly], you *gotta* shake his hand!
// ...
-> DONEDéfinir les ressources et les charger
Pour charger et manipuler des ressources (images, gifs, vidéos...) vous devrez utiliser Assets. Assets est une classe dotée de nombreuses fonctionnalités et provient de la bibliothèque PixiJS ; si vous souhaitez plus d'informations, lisez ici.
L'une des premières étapes consiste à choisir où enregistrer les ressources de votre visual novel : vous pouvez utiliser un service d'hébergement en ligne ou les enregistrer localement dans le projet. Vous trouverez plus d'informations sur ces deux options ici.
Si vous choisissez d'enregistrer les ressources localement, il vous suffit de les placer dans src/assets : le modèle utilise automatiquement AssetPack pour analyser les fichiers et les définir dans src/assets/manifest.gen.json. Si à la place vous choisissez de les conserver en ligne, vous devrez modifier manuellement assets/index.ts pour les enregistrer.
Dans les deux cas, chaque ressource se voit attribuer un ou plusieurs alias, que vous pourrez ensuite utiliser dans votre code pour référencer cette ressource.
{
"bundles": [
{
"name": "images",
"assets": [
{
"alias": [
"images_icon",
"icon"
],
"src": [
"images/[email protected]",
"images/icon-VA-NtA.webp",
"images/[email protected]",
"images/icon-E_ZC2g.png"
],
"data": {
"tags": {}
}
}
]
}
]
}Ajouter des images d'arrière-plan et de personnages
Il est maintenant temps de penser également à la partie visuelle. Nous allons ajouter les images d'arrière-plan et de personnages au canvas du visual novel.
Dans notre cas, chaque personnage est composé de 3 sprites : le corps, les yeux et la bouche. Nous utilisons ImageContainer, un Container qui regroupe des enfants Sprite, pour les regrouper et composer le personnage. Vous trouverez plus d'informations sur la façon d'ajouter des composants de canvas dans cette documentation.
Voici l'exemple :
=== start ===
# show image bg bg01-hallway
# show imagecontainer james [m01-body m01-eyes-smile m01-mouth-neutral01] xAlign 0.5 yAlign 1
james: You're my roommate's replacement, huh?
# show imagecontainer james [m01-body m01-eyes-grin m01-mouth-smile01]
james: Don't worry, you don't have much to live up to. Just don't use heroin like the last guy, and you'll be fine!
# show imagecontainer james [m01-body m01-eyes-smile m01-mouth-grin00]
mc: ...
// ...
-> DONESons et musique
Pour ajouter des sons et de la musique à votre visual novel, vous pouvez utiliser l'utilitaire sound.
Vous pouvez définir des canaux sonores pour gérer différents types de sons (par exemple, BGM, SFX) et contrôler leur volume, les mettre en pause, les reprendre, etc. Il est recommandé de définir les canaux au début du jeu, par exemple dans le callback then de la fonction Game.init.
Dans cet exemple, je définis deux canaux : un pour la musique de fond (BGM) et un pour les effets sonores (SFX). Je définis également defaultChannelAlias sur le canal SFX, de sorte que si je ne spécifie pas de canal lors de la lecture d'un son, il sera joué par défaut dans le canal SFX. Pour définir le canal de fond, je définis la propriété background sur true, de sorte que, contrairement aux autres canaux, les sons ne seront pas arrêtés à la fin de chaque step narratif, mais continueront jusqu'à ce qu'ils soient mis en pause ou arrêtés.
import { Game, sound } from "@drincs/pixi-vn";
import { BGM_CHANNEL_NAME, SFX_CHANNEL_NAME } from "@/constans";
Game.init(body, {
// ...
}).then(() => {
sound.channels.add(BGM_CHANNEL_NAME, { background: true });
sound.channels.add(SFX_CHANNEL_NAME);
sound.defaultChannelAlias = SFX_CHANNEL_NAME;
});Enfin, vous pouvez jouer les sons et la musique dans les labels en utilisant la fonction sound.play. Vous pouvez également utiliser des canaux pour gérer différents types de sons (par exemple, BGM, SFX) et contrôler leur volume, les mettre en pause, les reprendre, etc.
Vous trouverez plus d'informations sur la façon de l'utiliser ici.
=== start ===
# show image bg bg01-hallway
# play sound sfx_whoosh delay 0.1
# show imagecontainer james [m01-body m01-eyes-smile m01-mouth-neutral01] xAlign 0.5 yAlign 1 with movein direction right ease circInOut type spring
james: You're my roommate's replacement, huh?
# play sound sfx_whoosh channel bgm loop true
# show imagecontainer james [m01-body m01-eyes-grin m01-mouth-smile01]
james: Don't worry, you don't have much to live up to. Just don't use heroin like the last guy, and you'll be fine!
# show imagecontainer james [m01-body m01-eyes-smile m01-mouth-grin00]
mc: ...
// ...
# pause all sounds
# show imagecontainer steph [fm02-body fm02-eyes-smile fm02-mouth-smile00]
# play sound sfx_whoosh delay 0.1
# remove image james with moveout direction right ease circInOut type spring duration 0.5 delay 0.05
# remove image sly with moveout direction right ease anticipate duration 0.5
# remove image steph with moveout direction left ease easeInOut duration 0.5 delay 0.1
You want continue to the next part?<># continue
* Yes, I want to continue
-> second_part
* No, I want to stop here
-> END
=== second_part ===
# show text bg "(A few minutes later...)" style { fontFamily: "Arial", dropShadow: { alpha: 0.8, angle: 2.1, blur: 4, color: "0x111111", distance: 10, }, fill: "\#ffffff", stroke: { color: "\#004620", width: 12, join: "round" }, fontSize: 60, fontWeight: "lighter" } with fade
# edit text bg align 0.5
# pause
# resume all sounds
# show image bg bg02-dorm align 0 with fade
# play sound sfx_whoosh delay 0.4
// ...
She enters my room before I'VE even had a chance to.
// ...
-> DONE
Conclusion
Eh bien, vous savez maintenant comment créer un visual novel avec Pixi’VN. Un grand pouvoir implique de grandes responsabilités, alors utilisez-le judicieusement et créez une grande histoire ! 🚀