feat: add: boucle principale de jeu fonctionnelle

This commit is contained in:
2026-08-01 01:58:38 +02:00
parent 75253d0693
commit fedd606f15
5 changed files with 136 additions and 13 deletions

View File

@@ -15,6 +15,12 @@
const socket = io();
let myRole = null;
console.log("Connecte au serveur, id :", socket.id);
socket.on("new_round", (startPos) => {
player.x = startPos.x;
player.y = startPos.y;
});
socket.on("role", (role) => {
console.log("Mon role :", role);
myRole = role;
@@ -87,6 +93,12 @@
drawPlayer();
}
function showGameOver(message){
document.getElementById("gameOverMessage").textContent = message;
document.getElementById("gameOverScreen").style.display = "block";
myRole = null;
}
document.addEventListener("keydown", (e) => {
if (myRole !== "explorateur") return;
@@ -114,9 +126,13 @@
if (result.correct){
console.log("Bonne porte ! Victoire (pour cette manche).");
} else {
console.log("Mauvaise porte. Partie terminee.");
showGameOver("Mauvaise porte. Vous avez perdu.");
}
})
</script>
<div id="gameOverScreen" style="display: none;">
<h2>Partie terminee</h2>
<p id="gameOverMessage"></p>
</div>
</body>
</html>

79
echoes.md Normal file
View File

@@ -0,0 +1,79 @@
# **Echoes**
### *Jeu coopératif à deux joueurs*
---
# Pitch
**Echoes** est un jeu de coopération en ligne où deux joueurs doivent communiquer efficacement pour survivre.
Chaque manche, les rôles sont répartis entre un **Guide** et un **Explorateur**.
Le **Guide** est plongé dans l'obscurité. Il ne peut pas se déplacer, mais il est le seul à recevoir les instructions d'un mystérieux système de guidage. Il doit interpréter ces informations et les transmettre à son partenaire.
L'**Explorateur**, quant à lui, voit le labyrinthe et peut s'y déplacer librement. Cependant, il ne reçoit aucune indication sur la bonne direction et dépend entièrement des informations fournies par le Guide.
Ensemble, les deux joueurs doivent retrouver la bonne porte avant la fin du temps imparti.
À chaque porte franchie avec succès, les rôles s'inversent : le Guide devient l'Explorateur, et inversement. Les joueurs devront alterner entre observation, communication et exploration jusqu'à atteindre le nombre de portes nécessaires pour remporter la partie.
Le moindre mauvais choix est fatal : ouvrir une mauvaise porte met immédiatement fin à la partie.
---
# Gameplay
* Coopération à **2 joueurs**.
* Un joueur est **Guide**.
* Un joueur est **Explorateur**.
* Le Guide reçoit les indications mais ne peut pas se déplacer.
* L'Explorateur peut se déplacer mais ne connaît pas le chemin.
* Les joueurs doivent communiquer pour atteindre la bonne porte.
* Les rôles s'inversent après chaque porte correcte.
* Un chronomètre limite la durée de la partie.
---
# Conditions de victoire
* Trouver le nombre de portes demandé avant la fin du chronomètre.
# Conditions de défaite
* Ouvrir une mauvaise porte.
* Laisser le chronomètre atteindre zéro.
---
# Objectifs du projet
* Créer une expérience coopérative simple et accessible.
* Mettre la communication entre les joueurs au cœur du gameplay.
* Développer un prototype jouable rapidement, avec la possibilité d'ajouter de nouvelles fonctionnalités par la suite.
---
# Évolutions possibles
* Instructions vocales plutôt que textuelles.
* Dégradation progressive de la qualité des transmissions.
* Nouveaux labyrinthes.
* Pièges et fausses indications.
* Difficulté croissante.
* Classement basé sur le temps restant.
---
# Technologies envisagées
* **Frontend :** HTML, CSS, JavaScript
* **Backend :** Node.js + Socket.IO
* **Hébergement :** Serveur personnel
* **Plateforme :** Navigateur Web
---
# Slogan
**« Entendre ne suffit pas. Il faut aussi savoir se faire comprendre. »**

View File

@@ -102,6 +102,7 @@
"version": "13.0.2",
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.2.tgz",
"integrity": "sha512-jW6oufeDhXZaiX9Lw5A+oerVClx4iFrI6uDj1zu7SqUAjak9vbJvA0NEcKLNxHiQHb6kYCoFzzXYV0YOauhV3g==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"node-addon-api": "^8.0.0"

View File

@@ -27,19 +27,25 @@ io.on("connection", (socket) => {
waitingPlayer = null;
const socketIsGuide = Math.random() < 0.5;
socket.emit("role", socketIsGuide ? "guide" : "explorateur");
partner.emit("role", socketIsGuide ? "explorateur" : "guide");
const socketRole = socketIsGuide ? "guide" : "explorateur";
const partnerRole = socketIsGuide ? "explorateur" : "guide";
socket.data.partnerId = partner.id;
partner.data.partnerId = socket.id;
socket.emit("status", "Partie prete !");
partner.emit("status", "Partie prete !");
socket.data.role = socketRole;
partner.data.role = partnerRole;
const pairState = { gameOver: false};
socket.data.pairState = pairState;
partner.data.pairState = pairState;
socket.emit("status", "Partie prete !");
partner.emit("status", "Partie prete !");
}
socket.emit("role", socketRole);
partner.emit("role", partnerRole);
}
socket.on("message", (data) => {
const partnerId = socket.data.partnerId;
@@ -53,15 +59,36 @@ io.on("connection", (socket) => {
if (!pairState || pairState.gameOver) return;
const partnerId = socket.data.partnerId;
const partnerSocket = io.sockets.sockets.get(partnerId);
const isCorrect = position.x === correctDoor.x && position.y === correctDoor.y;
if (!isCorrect){
pairState.gameOver = true;
const result = { correct: false};
socket.emit("door_result", result);
if (partnerSocket) partnerSocket.emit("door_result", result);
return;
}
const temp = socket.data.role;
socket.data.role = partnerSocket.data.role;
partnerSocket.data.role = temp;
const startPos = { x: 1, y: 1};
console.log(pairState);
const result = {correct: isCorrect};
socket.emit("door_result", result);
socket.emit("door_result", { correct: true});
socket.emit("new_round", startPos);
socket.emit("role", socket.data.role);
if (partnerSocket){
partnerSocket.emit("door_result", { correct: true });
partnerSocket.emit("new_round", startPos);
partnerSocket.emit("role", partnerSocket.data.role);
}
if (partnerId){
io.to(partnerId).emit("door_result", result);
}

12
todo.md
View File

@@ -1,6 +1,6 @@
[ ] Randomizer les chemins
[ ] Donner les instructions via le son
[ ] Gerer une fin de niveau win/lose
[ ] Ajouter un compteur de niveau et un chronometre
[ ] Enregistrer les scores
[ ] Ajouter des instructions
-[] Randomizer les chemins
-[] Donner les instructions via le son
-[] Gerer une fin de niveau win/lose
-[] Ajouter un compteur de niveau et un chronometre
-[] Enregistrer les scores
-[] Ajouter des instructions