Le projet
J'ai été invité à participer à une murder party construite sur les mécaniques du jeu "Among Us". Les civils accomplissent des tâches dans le lieu, les imposteurs se fondent parmi eux grâce à de fausses tâches et éliminent en silence. Le maître du jeu (MJ) arbitre l'ensemble. Sans outil, le MJ doit tout suivre de tête : qui est vivant, qui a fait quoi, qui a triché. J'ai donc conçu une application en deux interfaces : une console MJ pensée pour l'ordinateur et un espace joueur pensé pour le téléphone. Au cours de cet évènement, 17 joueurs ont utilisé l'application en temps réel sans souci.
Ma démarche
Penser le modèle de données avant l'interface
J'ai modélisé le schéma complet dès la première phase de conception : une vingtaine de tables, pour ne jamais avoir à le refondre. Il sépare deux types de données :
- Une bibliothèque durable : joueurs, rôles, capacités, cartes, tâches ;
- Les données éphémères propres à chaque partie.
Ouvrir une nouvelle partie ne touche jamais à la bibliothèque. Les résultats sont figés dans une table où l'on ne fait qu'ajouter des lignes. Le classement cumulé se calcule donc par une simple somme, sans risque de désynchronisation.
Du temps réel sur un hébergement mutualisé
L'hébergement O2switch n'accepte ni WebSocket ni processus serveur permanent. J'ai donc construit une boucle de polling HTTP adaptatif :
- Interrogation toutes les 2 s pendant la partie, toutes les 4 s en salle d'attente ;
- Pause quand l'onglet est masqué, puis reprise immédiate au retour ;
- En cas de coupure réseau, intervalle allongé progressivement jusqu'à 8 s (back-off), avec un indicateur « Connexion perdue » après deux échecs.
La présence des joueurs repose sur un heartbeat : un joueur est « en ligne » s'il a donné signe de vie depuis moins de 15 s.
Le serveur comme seul arbitre
Toutes les règles sont vérifiées côté serveur :
- Pendant une réunion d'urgence, l'API refuse toute action de jeu, quoi que le client envoie ;
- Un joueur éliminé ne peut plus demander de validation ;
- La distribution des rôles et la clôture de partie s'exécutent dans des transactions, donc tout réussit ou rien n'est écrit.
Avancer par phases testables
Le développement suit des jalons validés un par un : connexion et salle d'attente, puis bibliothèque, préparation et distribution, jeu en direct, et enfin fin de partie avec classement.
Un design system qui encode le jeu
L'interface suit l'esthétique d'une salle d'opérations nocturne. Le fond sombre permet de jouer dans la pénombre sans éblouir. La couleur porte l'information :
- Cyan pour les civils ;
- Cramoisi pour les imposteurs ;
- Violet pour les rôles solo ;
- Ambre pour le MJ.
Ces couleurs sont déclarées une seule fois en variables CSS (custom properties). L'espace joueur est conçu d'abord pour le mobile (mobile first), avec des zones tactiles d'au moins 44 px et le respect du réglage prefers-reduced-motion.
Fonctionnalités
Préparer une partie (capture d'écran 1)
- Bibliothèque réutilisable : joueurs avec photo, rôles (camp et points de victoire), capacités actives ou passives, tâches ;
- Éditeur de carte : on importe le plan du lieu et on pose chaque emplacement d'un clic. Les positions sont enregistrées en pourcentage, donc restent justes sur tous les écrans ;
- Tâches paramétrables : vraies tâches ou leurres, un ou plusieurs lieu, ordre de passage imposé ou libre, étape suivante montrée à l'avance ou non ;
- Composition de la partie : choix des participants avec leur présence en direct, nombre de rôles par camp, nombre de tâches par joueur ;
- Distribution aléatoire en un clic : les imposteurs reçoivent des leurres, les civils de vraies tâches. Le MJ peut ensuite retoucher l'attribution joueur par joueur avant de lancer.
Jouer (capture d'écran 2)
- Révélation secrète du rôle, sur une carte aux couleurs de son camp.
- Plan avec les lieux de ses tâches. Pour les tâches à étapes, chaque lieu se dévoile au fil de la progression.
- Demande de validation avec photo facultative, compressée dans le navigateur avant l'envoi.
- Deux jauges : la progression personnelle et celle du groupe.
- Écrans plein écran pour la réunion d'urgence, l'élimination et les messages du MJ.
- Reconnexion transparente si le téléphone se verrouille ou si la page est rechargée.
Piloter la partie (capture d'écran 3)
- Fiche de chaque participant : rôle, camp, vivant ou éliminé, connexion, avancement ;
- File des demandes de validation, avec la photo de preuve en plein écran, puis Valider ou Refuser ;
- Réunion d'urgence en un bouton : l'interface de tous les joueurs se fige ;
- Élimination ou résurrection d'un joueur, message diffusé à tous, fil d'événements horodaté ;
- Jauge collective honnête : les tâches non faites des joueurs éliminés sortent du calcul. Les civils peuvent donc encore gagner après des pertes.
Clore et comptabiliser
Le MJ désigne le camp vainqueur (ou décrit une autre issue) et coche les joueurs solo qui ont gagné. Les points sont calculés automatiquement :
- Vivant dans le camp gagnant : les points de victoire de son rôle ;
- Éliminé dans le camp gagnant : 1 point ;
- Sinon : 0.
Classement de la partie, classement cumulé sur toutes les parties, export JSON.
Stack technique
PHP (PDO) · MySQL InnoDB · JavaScript vanilla, sans framework ni dépendance · CSS custom properties · hébergement O2switch.
Sécurité :
- Mots de passe hachés avec password_hash ;
- Jetons de session aléatoires de 256 bits ;
- Requêtes préparées ;
- Échappement systématique des contenus affichés, contre les failles XSS ;
- Vérification du contenu réel de chaque image envoyée, pas seulement de son extension.
Et ensuite
Le schéma de base prévoit déjà la suite :
- Capacités utilisables en jeu : elles existent aujourd'hui dans la bibliothèque, mais ne sont pas encore jouables ;
- Sabotages avec minuteur ;
- Messagerie ciblée et sondages.
Ce que j'en rentiens
Ce fut un projet ambitieux, tant dans sa conception que dans son exécution. Aujourd'hui, il est fonctionnel et prêt à évaluer, ce qui en fait une fierté.
Galerie
Aperçu du site