Le Quatorzième Jour — un FPS cel-shadé qui se joue comme on lit une planche.
Quatorze jours après l'assassinat de la Chancelière Kessler, un homme se réveille dans l'épave d'une cabine de téléphérique. Pas de nom. Pas de souvenirs. Un chiffre tatoué sous la clavicule.
▶ Jouer · Architecture · Décisions · Journal
Un hommage à une certaine bande dessinée d'espionnage adaptée en jeu de tir, refait avec les outils d'aujourd'hui et une histoire entièrement neuve. Trois partis pris le définissent :
- Le trait est calculé, pas dessiné. Pas de coque inversée : un Sobel qui croise profondeur et normales, donc les silhouettes et les plis intérieurs. Les décalages d'échantillonnage sont perturbés à 11 images/seconde — le contour « bout » comme un encrage à la main plutôt que de rester figé comme un filtre.
- Les vignettes sont de vraies images. Quand un garde tombe, le jeu rend la scène depuis une seconde caméra à travers le même pipeline, gèle l'image et l'épingle dans un coin de la page. Ce n'est pas une icône : c'est le même instant, sous un autre angle.
- Zéro asset binaire. Aucun fichier son, aucune texture, aucun modèle. Les sons sont synthétisés à l'exécution, la géométrie est faite de boîtes, les textures sont générées. Le jeu entier tient sous 700 ko (≈170 ko gzip) et se lance depuis un lien.
┌───────────────────────────────────────────────┐
│ Game │
│ ordre strict : joueur → gardes → monde → FX │
└───────────────────────────────────────────────┘
│ │ │
┌─────────────┘ │ └──────────────┐
▼ ▼ ▼
┌───────────────┐ ┌────────────────┐ ┌────────────────┐
│ Player │ │ Enemy ×N │ │ BrushWorld │
│ capsule + ADS │ │ vue · ouïe │ │ boîtes AABB │
│ recul ressort │ │ 5 états │ │ grille XZ │
└───────────────┘ └────────────────┘ └────────────────┘
└──────────────────────────┬──────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────┐
│ Stage │
│ [1] couleur toon + profondeur [2] normales [3] ComicPass │
│ Sobel · trame │
│ grain · vignetage │
└──────────────────────────────────────────────────────────────────────┘
│
┌──────────────┴───────────────┐
▼ ▼
┌───────────────┐ ┌────────────────┐
│ écran │ │ ComicPanels │
│ (canvas) │ │ même pipeline, │
└───────────────┘ │ image gelée │
└────────────────┘
| Couche | Dossier | Rôle |
|---|---|---|
| Rendu | src/render/ |
Contexte WebGL, cel-shading, encrage, trame, palette fermée |
| Simulation | src/player/ |
Contrôleur FPS, table d'armes, view model procédural |
src/ai/ |
Gardes : cône de vision, ouïe, escouades, hitbox par pièce | |
src/world/ |
Monde de boîtes, LevelBuilder, levels/level01.ts |
|
| Mise en scène | src/ui/ |
HUD encré, vignettes BD, onomatopées ancrées en 3D, menus |
src/fx/ |
Traçantes, impacts, sang, douilles — tout est poolé | |
| Récit | src/story/ |
Tout le texte joueur. Souvenirs, documents, répliques |
| Noyau | src/core/ |
Entrées, boucle, audio synthétisé, sauvegarde, maths |
| Outillage | tools/dashboard/ |
Cockpit de suivi local (hors bundle) |
Les détails qui comptent — pourquoi deux passes, pourquoi une sonde de sol, pourquoi les vignettes
sont limitées à une par seconde — sont dans docs/ARCHITECTURE.md.
npm install
npm run dev
# → http://localhost:5114npm run verify # types + format + tests — la même porte que la CI
npm run build # → dist/, prêt pour n'importe quel hébergeur statique
npm run dashboard # cockpit de suivi → http://localhost:5014Prérequis : Node ≥ 20.19 et un navigateur avec WebGL 2 (Chrome, Edge, Firefox à jour). Le jeu détecte l'absence de WebGL 2 et l'annonce plutôt que d'afficher un écran noir.
| Touche | Action | Touche | Action |
|---|---|---|---|
ZQSD / WASD |
se déplacer | Clic gauche |
tirer |
Maj |
courir | Clic droit |
viser (ADS) |
Ctrl / C |
s'accroupir | R |
recharger |
Espace |
sauter | F |
corps-à-corps |
A |
se pencher | E |
interagir / fouiller |
Molette / 1 2 |
changer d'arme | Échap |
pause & carnet |
S'accroupir ralentit de 45 % la vitesse à laquelle un garde vous identifie. Le Hush-22 fait sept fois moins de bruit que le Colt. Les deux sont des façons de ne pas déclencher l'escouade.
Cascades, Cold Fork. Six actes, de l'épave à la gare aval : la cabine, le corps du pilote et son Colt, la ligne d'arbres et les premiers gardes, le poste forestier, la salle des treuils, la descente. Cinq souvenirs et trois documents à retrouver — ils remplissent le carnet et racontent qui sont les Quatorze.
Le chapitre deux, Casier 14, se passe à la gare de Denver. Feuille de route complète.
npm run dashboard # → http://localhost:5014Un cockpit local sans dépendance : diagramme de Gantt en SVG fait main, courbe de progression, carte du système, journal de session, et un audit des huit conventions du dépôt que le serveur revérifie toutes les 4 secondes — y compris sur lui-même. Il n'est pas déployé, c'est un outil de poste de travail (ADR-007).
| Sujet | Commande |
|---|---|
| Types | npm run typecheck — tsc --noEmit, strict |
| Format | npm run format / npm run format:check |
| Tests | npm test / npm run test:watch |
| Tout | npm run verify |
Il n'y a pas d'ESLint : la configuration TypeScript (strict, noUncheckedIndexedAccess,
exactOptionalPropertyTypes, noUnusedLocals) fait office de linter, et un second outil qui répète
le premier coûterait du temps de CI sans rien apprendre — voir
ADR-005.
La CI reprend exactement ces commandes, avec les tests sur les trois systèmes d'exploitation : le
solveur de collisions et le PRNG déterministe qui habille les niveaux doivent donner le même
résultat partout, sinon un niveau se reconstruit différemment selon qui joue. Voir
CONTRIBUTING.md.
Les PR sont bienvenues — lisez CONTRIBUTING.md. Deux règles faciles à
manquer : rien ne doit allouer dans la boucle de frame, et aucune phrase française hors de
src/story/.
MIT © 2026 Benoit Bacot.
Œuvre originale. XIV n'est affilié à aucun éditeur ni ayant droit ; l'univers, les personnages et le scénario sont inventés pour ce projet.