RPG tactique : Client MJ & Interface Joueur personnalisée

Contexte du TP

Dans ce TP, vous n’êtes pas en train de coder le jeu lui-même :
le Maître du Jeu (MJ) tourne déjà sur la machine de l’enseignant et gère toute la logique (cartes, monstres, tours, déplacements…).

Votre mission est de créer votre propre interface de joueur, en personnalisant le client fourni (client.js + page HTML générée), pour qu’elle tourne autour de votre personnage inspiré de la mythologie corse.

Exemples :

Vous devrez également intégrer des éléments audio (Text-To-Speech, voire Speech-To-Text) pour rendre les échanges avec le MJ plus vivants.


Objectifs pédagogiques

À la fin de ce TP, vous serez capable de :


1. Architecture générale du système

Deux programmes Node.js sont fournis :

1.1. Le Maître du Jeu (MJ)

Vous ne modifiez pas ce fichier.

1.2. Le client joueur

MJ_BASE_URL=http://ADRESSE_DU_MJ:4000 
PLAYER_ID=p1 
CLIENT_PORT=4101 
node client.js

Dans ce TP, vous allez modifier la partie HTML / CSS / JavaScript du client (dans la réponse HTML de la route app.get('/', ...) de client.js).


2. Les données accessibles côté client

Quand votre page reçoit l’événement :

es.addEventListener('state', ev => {
  snapshot = JSON.parse(ev.data);
  draw();
});

La variable snapshot ressemble à ceci (simplifié) :

{
  started: true,
  turnOrder: ["p1","p2","p3"],
  active: "p2",               // id du joueur dont c'est le tour
  config: { maxStep: 1 },

  players: [
    {
      id: "p1",
      name: "Slot 1",
      cls: "Classe",
      hp: 35,
      sp: 20,
      atk: 3,
      x: 1,
      y: 1,
      mapId: "map1",
      inv: ["Arbousier", "Épée courte"],
      joined: true
    },
    ...
  ],

  maps: [
    {
      id: "map1",
      name: "Le debut du sentier",
      background: "/assets/level1.png",
      grid: [ [".",".","#",...], ... ],         // 20x20
      decor: [ { x:5, y:8, type:"wall", blocking:true }, ... ],
      items: [
        { id:"it1", name:"Arbousier", icon:"/assets/items/arbousier.png", x:14, y:2 },
        ...
      ],
      monsters: [
        { id:"m1", name:"U Bufonu", hp:8, icon:"/assets/monsters/bufonu.png", x:6, y:9 },
        ...
      ],
      exits: [ { x:19, y:11, to:"map2" } ],
      requireAllMonstersDead: true
    },
    ...
  ]
}

2.1. Vos informations de joueur

Depuis snapshot, vous pouvez récupérer votre joueur avec :

const me = snapshot.players.find(p => p.id === PLAYER_ID);

Vous avez accès à :

2.2. Les autres joueurs

Vous pouvez récupérer les autres joueurs sur la même carte :

const friends = snapshot.players.filter(p =>
  p.joined &&
  p.mapId === me.mapId &&
  p.id !== PLAYER_ID
);

Vous pourrez ainsi afficher leur position sur la grille et dans votre UI.


3. Mise en place du TP

3.1. Récupération des fichiers

L’enseignant vous fournit :

Le MJ est lancé par l’enseignant.
Vous, vous lancez votre client sur votre propre machine.

3.2. Lancer votre client

Installez les dépendances :

npm install

Puis lancez votre client en adaptant l’adresse du MJ et votre ID joueur :

MJ_BASE_URL=http://ADRESSE_DU_MJ:4000 
PLAYER_ID=p1 
CLIENT_PORT=4101 
node client.js

Ensuite, ouvrez votre navigateur sur :
http://localhost:4101/


4. Partie 1 — Fiche personnage et thème graphique

4.1. Choisir votre créature / personnage

Choisissez un monstre / créature issu de la mythologie corse ou inspiré de celle-ci.
Par exemple :

Créez :

4.2. Thème graphique

Modifiez le HTML/CSS généré dans client.js pour que toute l’interface tourne autour de votre personnage :

Vous pouvez par exemple :

Consigne :
Le thème doit être cohérent et lisible (contraste suffisant).


5. Partie 2 — Fiche de personnage dynamique

Dans la partie <script> de la page HTML (générée par client.js), vous avez déjà un code similaire à :

function draw() {
  if (!snapshot) return;

  const me = snapshot.players.find(p => p.id === PLAYER_ID);
  stats.innerHTML = me
    ? `<b>${me.name}</b> [${me.cls}] — HP:${me.hp} SP:${me.sp} — Pos (${me.x},${me.y})`
    : 'Non rejoint';

  // ...
}

5.1. Affichage joli des PV / SP / ATK

Transformez cette ligne en une vraie fiche :

Par exemple :

5.2. Afficher pseudo, classe et position

Affichez dans votre fiche :


6. Partie 3 — Inventaire du joueur

Vous avez déjà côté client :

me.inv  // ex: ["Arbousier", "Épée courte"]

6.1. Affichage basique

Créez dans votre HTML un bloc “Inventaire” et affichez :

6.2. Affichage amélioré (recommandé)

(Vous ne modifiez pas la logique de jeu : c’est le MJ qui décide des effets.)


7. Partie 4 — Position sur la grille et amis

Le code fourni affiche déjà une grille 20x20 et montre :

7.1. Mettre en avant votre personnage

Modifiez le CSS/JS pour que votre personnage soit :

Vous pouvez par exemple :

7.2. Afficher vos amis

Utilisez :

const friends = snapshot.players.filter(p =>
  p.joined &&
  p.mapId === me.mapId &&
  p.id !== PLAYER_ID
);

Sur la grille, mettez une icône différente pour ces amis (couleur ou petit symbole), et éventuellement listez-les dans un encadré “Alliés proches”.


8. Partie 5 — Text-To-Speech (TTS) pour la voix du MJ

Nous allons utiliser l’API SpeechSynthesis disponible dans la plupart des navigateurs modernes.

8.1. Principe

Quand un événement chat arrive :

es.addEventListener('chat', ev => {
  const msg = JSON.parse(ev.data);
  logChat(msg);
});

La fonction logChat reçoit un objet de la forme :

{
  from: "p1",
  text: "Je frappe le monstre",
  narrative: "Tu abats ton arme sur la créature qui vacille.",
  decision: { ... },
  ts: 1730000000000
}

Vous pouvez utiliser narrative pour faire parler le MJ.

8.2. Implémentation simple

Dans votre <script>, ajoutez une fonction :

function speak(text) {
  if (!('speechSynthesis' in window)) return; // pas supporté
  const utterance = new SpeechSynthesisUtterance(text);
  utterance.lang = 'fr-FR';
  window.speechSynthesis.speak(utterance);
}

Puis modifiez logChat pour que seulement les messages du MJ soient lus à voix haute.
Ici, on considère que tout narrative est la voix du MJ :

function logChat(m) {
  const who = m.from === PLAYER_ID ? 'Vous' : m.from;
  const cls = m.from === PLAYER_ID ? 'mine' : 'other';
  const line = document.createElement('div');
  line.innerHTML =
    '<span class="' + cls + '"><b>' + who + '</b>:</span> ' +
    (m.text || '') +
    (m.narrative ? '<br><small>' + m.narrative + '</small>' : '');
  chat.appendChild(line);
  chat.scrollTop = chat.scrollHeight;

  if (m.narrative) {
    speak(m.narrative);
  }
}

(Vous pouvez affiner en ne lisant que quand c’est un autre joueur ou le MJ, etc.)


9. Partie 6 — Text-To-Speech pour votre personnage

Vous pouvez également faire parler votre propre personnage quand vous envoyez un message.

9.1. Lecture à l’envoi

Dans le gestionnaire du formulaire :

form.onsubmit = async (e) => {
  e.preventDefault();
  const text = msg.value.trim();
  if (!text) return;
  msg.value = '';

  // Faire parler votre personnage
  speak(text);

  const r = await fetch('/say', {
    method: 'POST',
    headers: { 'Content-Type':'application/json' },
    body: JSON.stringify({ text })
  });
  if (!r.ok) alert(await r.text());
};

Vous pouvez utiliser une voix différente (si le navigateur en propose plusieurs) pour distinguer :


10. Bonus — Speech-To-Text (optionnel)

Pour aller plus loin, vous pouvez essayer d’utiliser SpeechRecognition (API Web Speech) pour permettre :

Attention : cette API est expérimentale et mieux supportée sur certains navigateurs (Chrome, versions Desktop, etc.).

Idée de démarche :

  1. Ajouter un bouton “🎙 Parler”.
  2. Au clic, lancer la reconnaissance vocale.
  3. Quand un résultat est reçu, l’afficher dans msg.value.
  4. Laisser l’utilisateur corriger ou envoyer.

11. Récapitulatif des exigences

Obligatoire :

  1. Connexion au MJ via votre client (client.js) et affichage d’une interface web.
  2. Choix d’un personnage inspiré de la mythologie corse :
    • nom,
    • image affichée dans l’interface.
  3. Thème graphique cohérent avec ce personnage (couleurs, ambiance).
  4. Affichage clair de :
    • pseudo,
    • classe,
    • PV, SP, ATK,
    • position (x, y).
  5. Affichage de l’inventaire du joueur (me.inv).
  6. Mise en avant de la position de votre personnage sur la grille.
  7. Affichage des amis (autres joueurs) sur la carte.
  8. Text-To-Speech pour lire au moins la narration du MJ.

Fortement recommandé :

Bonus possibles :


12. Questions / pistes de réflexion

Lorsque vous aurez terminé, préparez une courte démonstration :
montrez votre interface, expliquez votre personnage et justifiez vos choix graphiques / techniques.