Projet

Still

Jeu d'horreur narratif à la première personne, jouable dans le navigateur, où tout (décors, créatures, sons) est généré par le code.

Rôle

Conception et développement

Stack

Typescript • Three.js

Impact

3 chapitres • ~800 tests • textures, modèles et sons générés par code

Aperçu

Cinq ans après la disparition de sa femme, un homme reçoit une photo de sa famille. Il décide de se rendre dans l'hôpital où elle travaillait, dans l'espoir de la retrouver.

Voir le projet en ligne (nouvel onglet)

Pourquoi ce projet ?

Je voulais voir jusqu'où on peut aller dans un navigateur, sans moteur de jeu ni fichiers d'assets : un jeu en 3D complet, avec son ambiance, son récit et son rythme, où chaque texture, chaque modèle et chaque son est généré par le code. Et raconter une vraie histoire, celle d'un homme qui refuse d'abandonner, plutôt qu'un simple enchaînement de frayeurs.

Fonctionnalités clés

  • Trois chapitres, trois étages, trois règles : ce qui vous protégeait à un étage ne vous protège plus au suivant.
  • Des créatures à l'IA distincte : pathfinding sur grille, territoire de patrouille, bruits qui se propagent selon l'acoustique des pièces, perte de trace.
  • Furtivité : casiers où se cacher, souffle à retenir, lampe qui se vide et qu'il faut secouer pour la recharger.
  • Un récit par documents : dossiers, registres, notes de service, écrits comme de vrais documents, jamais adressés au joueur.
  • Un générique, des points de reprise et un écran de chapitres.
  • Réglages : qualité graphique automatique, luminosité, volume, sensibilité de la souris, repérage des objets.

Architecture & choix techniques

  • Rendu 100 % procédural : matériaux PBR (peinture écaillée, carrelage usé, flaques, peau) générés en parallèle dans des Web Workers, rendu HDR, post-traitement maison (bloom, aberration chromatique, grain) qui réagit au danger et au rythme cardiaque.
  • Son 100 % synthétisé avec Web Audio : pas, souffle, voix, réverbération propre à chaque lieu. Le mixage joue sur le contraste : le silence devient le signal.
  • Simulation séparée de la présentation : les règles du jeu ne connaissent ni Three.js, ni le DOM, ni le son. Elles modifient un état et publient des événements typés ; le rendu, l'audio et l'interface s'y branchent. Le linter refuse toute importation qui franchirait la frontière.
  • Niveaux décrits en texte, validés par des règles de conception automatiques (pas de cul-de-sac, pas de grande salle vide, tout élément accessible).
  • Équilibrage par joueurs automatiques : des bots jouent des dizaines de parties et mesurent le taux de victoire quand on change un réglage.
  • Tests de bout en bout dans un vrai Chrome : une partie complète, du menu au générique.
  • Déploiement Vercel avec une CSP stricte vérifiée par un test, et les textes du récit brouillés dans le build pour éviter les spoilers.

Stack utilisée

  • Langage : TypeScript (strict)
  • 3D : Three.js
  • Son : Web Audio API
  • Build : Vite
  • Tests : Vitest, Playwright (e2e)
  • Qualité : ESLint, Prettier, GitHub Actions
  • Hébergement : Vercel

Ce que ce projet m'a apporté

  • Concevoir une architecture qui tient sur 50 000 lignes : frontières claires, événements typés, tout réglage au même endroit.
  • Le rendu et le son procéduraux, et l'optimisation qui va avec (workers, qualité adaptative).
  • Tester un jeu comme une application : simulation testable sans navigateur, bots d'équilibrage, tests e2e.
  • Travailler avec un assistant IA (Claude Code) comme binôme : décisions de conception validées avant le code, consignes et outils propres au dépôt.
  • L'écriture et la mise en scène de la peur : le rythme, le silence, ce qu'on ne montre pas.