Compare commits

...

4 Commits

Author SHA1 Message Date
84cd04a4cf fix: ajout de protection anti-mauvais chargement de voix 2026-08-09 02:29:37 +02:00
dab95812cc Merge branch 'main' into dev
recuperation de la version valide du projet
2026-08-04 10:20:45 +02:00
ab4372c57c add: ajout des modifications manquantes pour la fonction d'instruction vocale 2026-08-03 22:54:51 +02:00
d36c025cf2 add: ajout de la fonction d'instruction vocale 2026-08-03 22:51:26 +02:00
4 changed files with 106 additions and 0 deletions

69
client/js/guideVoice.js Normal file
View File

@@ -0,0 +1,69 @@
/*
guideVoice.js
Vocalise les instructions recues du serveur via la synthese vocale du navigateur
*/
let currentUtterance = null;
let voixChoisie = null;
let voixPretes = false;
let texteEnAttente = null;
const NOM_VOIX_PREFERE = "French (France)+female1";
function resoudreVoix() {
if (voixPretes) return; // deja fait, evite le travail en double
const voix = speechSynthesis.getVoices();
if (voix.length === 0) return; // toujours pas chargees
voixChoisie =
voix.find(v => v.name === NOM_VOIX_PREFERE) ||
voix.find(v => v.lang.startsWith("fr")) ||
voix[0];
voixPretes = true;
console.log("Voix sélectionnée:", voixChoisie?.name);
if (texteEnAttente) {
const texte = texteEnAttente;
texteEnAttente = null;
jouer(texte);
}
}
// Piste 1 : l'event, au cas ou il se declenche sur d'autres navigateurs
speechSynthesis.onvoiceschanged = resoudreVoix;
// Piste 2 : sondage en secours, car onvoiceschanged n'est pas fiable sur Firefox/LibreWolf
const intervalleSondage = setInterval(() => {
resoudreVoix();
if (voixPretes) clearInterval(intervalleSondage);
}, 200);
resoudreVoix(); // au cas ou les voix sont deja dispo au chargement du module
function jouer(texte) {
if (speechSynthesis.speaking) {
speechSynthesis.cancel();
}
currentUtterance = new SpeechSynthesisUtterance(texte);
currentUtterance.voice = voixChoisie;
currentUtterance.lang = "fr-FR";
currentUtterance.onstart = () => console.log("Lecture démarrée");
currentUtterance.onend = () => console.log("Lecture terminée");
currentUtterance.onerror = (e) => console.error("Erreur synthèse:", e.error, e);
speechSynthesis.speak(currentUtterance);
}
export function speakInstruction(texte) {
if (!voixPretes) {
console.log("Voix pas encore prêtes, mise en attente:", texte);
texteEnAttente = texte;
return;
}
jouer(texte);
}

View File

@@ -9,6 +9,7 @@ import { roleState } from "./role.js";
import { render, drawBlind } from "./canvas.js";
import { setupMovement } from "./movement.js";
import { showGameOver, showVictory, updateTimerDisplay } from "./ui.js";
import { speakInstruction} from "./guideVoice.js";
setupMovement();
@@ -48,3 +49,8 @@ socket.on("victory", () => {
socket.on("timer", (timeLeft) => {
updateTimerDisplay(timeLeft);
});
socket.on("instruction", (data) => {
console.log("Payload recu", data);
speakInstruction(data.texte);
})

View File

@@ -0,0 +1,27 @@
/*
guideInstruction.js
sert a envoyer au client guide les instructions
*/
const INSTRUCTION_GUIDE = "instruction";
const INSTRUCTION_INTERVAL_MS = 5000;
function startInstructionLoop(wSS, socket, partnerSocket, pairState, getInstructionText) {
const interval = setInterval(() => {
if (pairState.gameOver) {
clearInterval(interval);
return;
}
const guideSocket = socket.data.role === "guide" ? socket : partnerSocket;
const texte = getInstructionText();
guideSocket.emit(INSTRUCTION_GUIDE, { texte });
}, INSTRUCTION_INTERVAL_MS);
return () => clearInterval(interval);
}
module.exports = { startInstructionLoop };

View File

@@ -8,6 +8,7 @@ const gameState = require("./gameState");
const { GAME_DURATION } = require("./config");
const { handleDoorReached } = require("./doorLogic");
const { startTimer } = require("./timer");
const { startInstructionLoop } = require("./guideInstruction");
function registerSocketHandlers(wSS, socket) {
console.log(`Un client s'est connecté : ${socket.id}`);
@@ -38,6 +39,9 @@ function registerSocketHandlers(wSS, socket) {
partner.emit("status", "Partie prête !");
startTimer(socket, partner, pairState);
startInstructionLoop(wSS, socket , partner, pairState, () => {
return "Descendre de quatre cases, aller a droite de une case, descendre de 1 case";
});
}
socket.on("door_reached", (position) => handleDoorReached(wSS, socket, position));