/ p5.js / 15 / Narration non linéaire

 

Construire une narration non-linéaire avec p5.js

« Je vais dans le jardin, je vois voir maman ou je vais manger des cerises (dans ce cas il faut que je prenne l’échelle), je mange des cerises, je vais faire la sieste… »

Voici la structure de l’histoire.
Pour rendre l’histoire plus intéressante une condition d’accès au cerisier est requise (il faut prendre l’échelle).
Si le mot (en rose) est saisi dans le champ, le lecteur passe à l’étape suivante…

Télécharger les images et les fichiers de bases

Étape 1

D’abord les variables pour les images et une variable pour l’état initial (attention à écrire etat et non état).

var sortir;
var jardin;
var mere;
var cerisier;
var manger;
var sieste;

var etat = 0;

Ensuite, une fonction preload() est créée pour le chargement des images.

function preload(){
  sortir = loadImage("images/0-sortir.jpg");
  jardin = loadImage("images/1-jardin.jpg");
  mere = loadImage("images/2-mere.jpg");
  cerisier = loadImage("images/3-cerisier.jpg");
  manger = loadImage("images/4-manger.jpg");
  sieste= loadImage("images/5-sieste.jpg");
}

Dans setup() créer le canvas :

function setup() {
 createCanvas(1280, 800);
}

Dans la fonction draw() créer les conditions d’affichage :

 if (etat == 0){
    image(sortir, 0,0); 
 }else if (etat == 1) {
    image(jardin, 0,0);
 }
...

Si la variable etat est égale à 0 alors l’image sortir s’affiche, si la variable état est égale à 1 c’est l’image jardin qui s’affiche… et ainsi de suite pour toutes les états de la variable.
Afin de tester le chargement des images, il faut créer une fonction keyTaped() pour afficher les images à l’aide d’une touche du clavier :

if(key == '0'){
    etat = 0;
  }else if (key == '1'){
        etat = 1;
    }

Si la touche 0 est utilisée l’état = 0 (c’est-à-dire que l’image « sortir » s’affiche (rappelons que c’est la valeur par défaut))
Si la touche 1 est utilisée l’état = 1 (c’est-à-dire que l’image « jardin » s’affiche)
et ainsi de suite….  Attention l’etat3 et l’etat4 appelle la même image (le texte différera par la suite) !

Code étape 1

var sortir;
var jardin;
var mere;
var cerisier;
var manger;
var sieste;

var etat = 0;


function preload(){
 sortir = loadImage("images/0-sortir.jpg");
 jardin = loadImage("images/1-jardin.jpg");
 mere = loadImage("images/2-mere.jpg");
 cerisier = loadImage("images/3-cerisier.jpg");
 manger = loadImage("images/4-manger.jpg");
 sieste= loadImage("images/5-sieste.jpg");
}


function setup() {
 createCanvas(1280, 800);
}

function draw() {
 background(255);
 textSize(20);
 if (etat == 0){
 image(sortir, 0,0);
 }else if (etat == 1) {
 image(jardin, 0,0);
 }else if (etat == 2) {
 image(mere, 0,0);
 }else if (etat == 3) {
 image(cerisier, 0,0);
 }else if (etat == 4) {
 image(cerisier, 0,0);
 }else if (etat == 5) {
 image(manger, 0,0);
 }else if (etat == 6) {
 image(sieste, 0,0);
 }
 }

function keyTyped(){
 if(key == '0'){
 etat = 0;
 }else if (key == '1'){
 etat = 1;
 }else if (key == '2'){
 etat = 2;
 }else if (key == '3'){
 etat = 3;
 }else if (key == '4'){
 etat = 4;
 }else if (key == '5'){
 etat = 5;
 }else if (key == '6'){
 etat = 6;
 }
}

Tout ça permet de tester l’affichage de nos images et le bon fonctionnement de nos états.

 

Étape 2

Configurer le texte (voir ici, si vous avez oublié)…

function setup() { 
createCanvas(1280, 800); 
textFont("Helvetica"); 
textSize(24); 
textAlign(LEFT); 
}

Ajouter un texte pour chaque état.
Un bloc de texte est créé : text (“le texte”, position en X, position en Y, largeur de la boîte, hauteur de la boîte);

function draw() {
 background(255);
 textSize(20);
 if (etat == 0){
 image(sortir, 0,0);
 text("Tu veux sortir ?", 820, 200,450,100);
 }else if (etat == 1) {
 image(jardin, 0,0);
 text("Je cherche maman dans le jardin ou je vais manger des cerises ? Pense à prendre l'échelle pour monter au cerisier.", 820, 50,450,200);
 }else if (etat == 2) {
 image(mere, 0,0);
 text("Elle a l'air super occupée, je vais aller manger des cerises...", 820, 50,450,200);
 }else if (etat == 3) {
 image(cerisier, 0,0);
 text("Zut ! T'as oublié l'échelle.", 820, 50,400,200);
 }else if (etat == 4) {
 image(cerisier, 0,0);
 text("Super t'a pris l'échelle, tu peux manger plein de cerises.", 820, 50,450,200);
 }else if (etat == 5) {
 image(manger, 0,0);
 text("Ventre plein, je vais faire une sieste.", 820, 50,450,200);
 }else if (etat == 6) {
 image(sieste, 0,0);
 text("Fin provisoire.", 820, 50,400,200);
 }
 }

Afin que le lecteur puisse progresser dans l’histoire en écrivant un mot dans un champ de saisie, à l’aide du clavier, il faut créer le champ de saisie et un bouton de validation :

Ajouter d’abord ces 3 variables au début du code.

var input, bouton, annotation;

Puis compléter la fonction setup()

function setup() {
 createCanvas(1280, 800);
 textFont("Helvetica");
 textSize(20);
 textAlign(LEFT);
 
 input = createInput();
 input.position(820, 740);
 input.changed(saisieTexte); 
 
 bouton = createButton('Cliquez');
 bouton.position(1030, 740);
 bouton.mousePressed(saisieTexte);
 annotation = createElement('annotation', 'Écrire ici');
 annotation.position(820, 710);
}

Créer une fonction pour la saisie de texte.

function saisieTexte(){

}

Elle permet de spécifier toutes les interactions nécessaires :
Créer une variable qui récupère la saisie du texte var text = input.value();
L’état par défaut est 0 (var etat = 0;)
Commencer par la fin !!
Si l’usager écrit début dans le champ de saisie l’histoire retourne à l’etat0 et le champ de saisie s’efface.

var text = input.value();
if (text == "début"){
 etat = 0;
 input.value('');
 }

Attention car le code est sensible à la casse et aux caractères accentués. Si l’usager écrit Début ou debut cela ne fonctionnera pas. Si vous voulez que l’usager puisse écrire Début  ou debut il faudra le spécifier dans le code.
Rappel : && pour et || pour ou

if (text == "début" || text == "Début" || text == "debut"){
 etat = 0;
 input.value('');
 }

Autre rappel, en programmation égal s’écrit ==

Ensuite, il suffit de commencer la narration.
Si je suis à l’etat0 et si j’écris sortir,  je passe à l’etat1
Si je suis à l’etat1 et si j’écris maman je passe à l’etat2
Si je suis à l’etat1 et si j’écris échelle je passe à l’etat4
Si je suis à l’etat1 
et si j’écris cerises je passe à l’etat3
… (utiliser le schéma structurel du début)

 if (text == "début"){
 etat = 0;
 input.value('');
 }else if (etat == 0 && text == "sortir"){
 etat = 1;
 input.value('');
 }

En définitive on obtient le code suivant :

function saisieTexte(){
 var text = input.value();
 if (text == "début"){
 etat = 0;
 input.value('');
 }else if (etat === 0 && text == "sortir"){
 etat = 1;
 input.value('');
 }else if (etat == 1 && text == "maman"){
 etat = 2;
 input.value('');
 }else if ((etat == 1 && text == "échelle") ||(etat == 2 && text == "échelle") ||(etat == 3 && text == "échelle")){
 input.value('');
 etat = 4;
 }else if ((etat == 1 && text == "cerises") || (etat == 2 && text == "cerises") || (etat == 3 && text == "cerises" )) {
 input.value('');
 etat = 3;
 }else if (etat == 4 && text == "manger"){
 input.value('');
 etat = 5;
 }else if (etat == 5 && text == "sieste"){
 input.value('début');
 etat = 6;
 }
}

Code étape 2

var sortir;
var jardin;
var mere;
var cerisier;
var manger;
var sieste;

var etat = 0;
var input, bouton, annotation;

function preload(){
 sortir = loadImage("images/0-sortir.jpg");
 jardin = loadImage("images/1-jardin.jpg");
 mere = loadImage("images/2-mere.jpg");
 cerisier = loadImage("images/3-cerisier.jpg");
 manger = loadImage("images/4-manger.jpg");
 sieste= loadImage("images/5-sieste.jpg");
}

function setup() {
 createCanvas(1280, 800);
 textFont("Helvetica");
 textSize(20);
 textAlign(LEFT);
 
 input = createInput();
 input.position(820, 740);
 input.changed(saisieTexte); 
 
 bouton = createButton('Cliquez');
 bouton.position(1030, 740);
 bouton.mousePressed(saisieTexte);
 annotation = createElement('annotation', 'Écrire ici');
 annotation.position(820, 710);
 }

function draw() {
 background(255);
 textSize(20);
 if (etat === 0){
 image(sortir, 0,0);
 text('Tu veux sortir ?', 820, 200,450,100);
 }else if (etat == 1) {
 image(jardin, 0,0);
 text("Je cherche maman dans le jardin ou je vais manger des cerises ? Pense à prendre l'échelle pour monter au cerisier.", 820, 50,450,200);
 }else if (etat == 2) {
 image(mere, 0,0);
 text("Elle a l'air super occupée, je vais aller manger des cerises...", 820, 50,450,200);
 }else if (etat == 3) {
 image(cerisier, 0,0);
 text("Zut ! T'as oublié l'échelle.", 820, 50,400,200);
 }else if (etat == 4) {
 image(cerisier, 0,0);
 text("Super t'a pris l'échelle, tu peux manger plein de cerises.", 820, 50,450,200);
 }else if (etat == 5) {
 image(manger, 0,0);
 text("Ventre plein, je vais faire une sieste.", 820, 50,450,200);
 }else if (etat == 6) {
 image(sieste, 0,0);
 text("Fin provisoire.", 820, 50,400,200);
 }
}

function saisieTexte(){
 var text = input.value();
 if (text == "début"){
 etat = 0;
 input.value('');
 }else if (etat == 0 && text == "sortir"){
 etat = 1;
 input.value('');
 }else if (etat == 1 && text == "maman"){
 etat = 2;
 input.value('');
 }else if ((etat == 1 && text == "échelle") ||(etat == 2 && text == "échelle") ||(etat == 3 && text == "échelle")){
 input.value('');
 etat = 4;
 }else if ((etat == 1 && text == "cerises") || (etat == 2 && text == "cerises") || (etat == 3 && text == "cerises" )) {
 input.value('');
 etat = 3;
 }else if (etat == 4 && text == "manger"){
 input.value('');
 etat = 5;
 }else if (etat == 5 && text == "sieste"){
 input.value('début');
 etat = 6;
 }
}

 Étape 3

Pour faire figurer les consignes à l’etat0, il faut ajouter le texte et le mettre en forme.
Pour l’instant les textes sont tous formater  dans le setup();

 textFont("Helvetica");
 textSize(20);
 textAlign(LEFT);

Mettons les consignes en Cambria, taille 20.
Afin que le texte « Tu veux sortir » soit en Helvetica il est nécessaire de le repréciser, de plus nous changeons la couleur du texte fill(13, 108,147)

if (etat === 0){
 image(sortir, 0,0);
 textFont("Cambria");
 fill(100);
 text("Pour avancer dans l'histoire il faut écrire au clavier le bon mot. Il est toujours contenu dans la phrase.", 820, 50,450,100);
 textFont("Helvetica");
 fill(13,108,147);
 text("Tu veux sortir ?", 820, 200,450,100);
 }

Ajoutons à la fin de draw les références des images.

textSize(10);
 text("'Au jardin', Katy Couprie Antonin Louchard, Éditions Thierry Magnier, 2003", 820, 780, 450, 50);

Le formatage du champ de saisie, de sa légende et du bouton est réalisé en CSS dans le fichier index.html

 <style> 
 body {
 padding: 0; 
 margin: 0;
 } 
 
 canvas {
 vertical-align: top;
 } 
 
 annotation{
 font-family: helvetica;
 color:rgb(13,108,147);
 }
 
 input {
 width:200px;
 }
 
 button {
 background-color: rgb(13,108,147);
 border: none;
 color: white;
 padding: 2px 10px;
 text-align: center;
 text-decoration: none;
 display: inline-block;
 font-size: 14px;
 }
 
 button:hover {
 background-color: rgb(13,108,147);
 color: #ccc;
 box-shadow: 0 2px 6px 0 rgba(0,0,0,0.24), 0 7px 5px 0 rgba(0,0,0,0.19);
 }
 </style>

Enfin pour que le texte s’efface automatiquement quand le mauvais mot est saisi dans le champ il faut ajouter la ligne :

else if (text != "sortir" || text != "maman" || text != "échelle"|| text != "cerises" || text != "manger" || text != "sieste" || text != "début"){
 input.value('');
 }

à la fin de la fonction saisieTexte()

Code étape 3

sketch.js

var sortir;
var jardin;
var mere;
var cerisier;
var manger;
var sieste;

var etat = 0;
var input, bouton, annotation;

function preload(){
 sortir = loadImage("images/0-sortir.jpg");
 jardin = loadImage("images/1-jardin.jpg");
 mere = loadImage("images/2-mere.jpg");
 cerisier = loadImage("images/3-cerisier.jpg");
 manger = loadImage("images/4-manger.jpg");
 sieste= loadImage("images/5-sieste.jpg");
}

function setup() {
 createCanvas(1280, 800);
 textFont("Helvetica");
 textSize(20);
 textAlign(LEFT);
 
 input = createInput();
 input.position(820, 740);
 input.changed(saisieTexte); 
 
 bouton = createButton('Cliquez');
 bouton.position(1030, 740);
 bouton.mousePressed(saisieTexte);
 annotation = createElement('annotation', 'Écrire ici');
 annotation.position(820, 710);
}

function draw() {
 background(255);
 textSize(20);
 if (etat === 0){
 image(sortir, 0,0);
 textFont("Cambria");
 fill(100);
 text("Pour avancer dans l'histoire il faut écrire au clavier le bon mot. Il est toujours contenu dans la phrase.", 820, 50,450,100);
 textFont("Helvetica");
 fill(13,108,147);
 text('Tu veux sortir ?', 820, 200,450,100);
 }else if (etat == 1) {
 image(jardin, 0,0);
 text("Je cherche maman dans le jardin ou je vais manger des cerises ? Pense à prendre l'échelle pour monter au cerisier.", 820, 50,450,200);
 }else if (etat == 2) {
 image(mere, 0,0);
 text("Elle a l'air super occupée, je vais aller manger des cerises...", 820, 50,450,200);
 }else if (etat == 3) {
 image(cerisier, 0,0);
 text("Zut ! T'as oublié l'échelle.", 820, 50,400,200);
 }else if (etat == 4) {
 image(cerisier, 0,0);
 text("Super t'a pris l'échelle, tu peux manger plein de cerises.", 820, 50,450,200);
 }else if (etat == 5) {
 image(manger, 0,0);
 text("Ventre plein, je vais faire une sieste.", 820, 50,450,200);
 }else if (etat == 6) {
 image(sieste, 0,0);
 text("Fin provisoire.", 820, 50,400,200);
 }
 textSize(10);
 text("'Au jardin', Katy Couprie Antonin Louchard, Éditions Thierry Magnier, 2003", 820, 780, 450, 50);
 }

function saisieTexte(){
 var text = input.value();
 if (text == "début"){
 etat = 0;
 input.value('');
 }else if (etat == 0 && text == "sortir"){
 etat = 1;
 input.value('');
 }else if (etat == 1 && text == "maman"){
 etat = 2;
 input.value('');
 }else if ((etat == 1 && text == "échelle") ||(etat == 2 && text == "échelle") ||(etat == 3 && text == "échelle")){
 input.value('');
 etat = 4;
 }else if ((etat == 1 && text == "cerises") || (etat == 2 && text == "cerises") || (etat == 3 && text == "cerises" )) {
 input.value('');
 etat = 3;
 }else if (etat == 4 && text == "manger"){
 input.value('');
 etat = 5;
 }else if (etat == 5 && text == "sieste"){
 input.value('début');
 etat = 6;
 }else if (text != "sortir" || text != "maman" || text != "échelle"|| text != "cerises" || text != "manger" || text != "sieste" || text != "début"){
 input.value('');
 }
}

index.html

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>construction</title>
 <script src="libraries/p5.js" type="text/javascript"></script>
 <script src="libraries/p5.dom.js" type="text/javascript"></script>
 <script src="libraries/p5.sound.js" type="text/javascript"></script>
 <script src="sketch.js" type="text/javascript"></script>

<style> 
 body {
 padding: 0; 
 margin: 0;
 } 
 
 canvas {
 vertical-align: top;
 } 
 
 annotation{
 font-family: helvetica;
 color:rgb(13,108,147);
 }
 
 input {
 width:200px;
 }
 
 button {
 background-color: rgb(13,108,147);
 border: none;
 color: white;
 padding: 2px 10px;
 text-align: center;
 text-decoration: none;
 display: inline-block;
 font-size: 14px;
 }
 
 button:hover {
 background-color: rgb(13,108,147);
 color: #ccc;
 box-shadow: 0 2px 6px 0 rgba(0,0,0,0.24), 0 7px 5px 0 rgba(0,0,0,0.19);
 }
 </style>
 </head>
 <body>
 </body>
</html>