Files
Ransom-s-wake/docs/briefs/terrain-site-zone1-gameplay.md
T
2026-10-06 19:30:36 +02:00

318 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Proposition — terrain du site de la zone I : « Banc du Vigilant »
**Statut : validé par Olivier le 2026-10-06** (plan de masse, objet secondaire à 62 m, pipeline par script de cuisson, nom « Banc du Vigilant » conservé). Sert de spécification de référence pour l'implémentation.
Rédigée le 2026-10-06 à partir de `docs/GAME_DESIGN_PLAN.md`,
`docs/VERTICAL_SLICE_TECHNICAL_PLAN.md`, `docs/POC_B_TECHNICAL_BASELINE.md`,
des ADR 0004, 0006, 0008, 0010 et du code sous `game/world/`. Rien n'a été
exécuté ; aucun fichier de jeu n'est modifié par ce brief.
---
## 1. Objectif
Donner au premier site de plongée (navire de prospection, zone I, 35 m) un
terrain statique, crédible et porteur de gameplay : le relief doit cacher
l'épave, se lire au sonar, offrir une route sûre et une route risquée, et
rendre la recherche intéressante sans marqueur. C'est la pièce « terrain
graybox » de la tranche 3 du plan technique.
Terminé quand :
- un joueur sans aide trouve l'accès à l'épave cible en 5 à 10 minutes après
l'arrivée dans la zone (critère §5 du plan technique) ;
- les deux routes existent, se distinguent au sonar et se justifient par les
ressources (profondeur, batterie, collisions) ;
- le sonar renvoie roche, sable et métal selon la cellule touchée, pas un seul
matériau pour tout le fond ;
- l'environnement de test du véhicule utilise la même implémentation de terrain
que le site (une seule implémentation par concept) ;
- `bash scripts/quality_gate.sh` passe.
## 2. Ce qui existe et ce qui contraint
| Élément | État | Conséquence pour le terrain |
|---|---|---|
| `game/world/sites/vehicle_test_environment.gd` | heightmap analytique 61×69, 180×200 m, -40 à -78 m, `HeightMapShape3D` | graybox de test ; devient un client du nouvel acteur terrain |
| `game/world/sonar/reference_bathymetry_acquisition.gd` | rayons verticaux, lit `sonar_material` / `sonar_reflectivity` sur le collider | le sonar suit tout terrain qui a une collision ; matériau par corps, pas par cellule |
| ADR 0010 | surface unique en V1 | pas de grotte, tunnel ni surplomb porteur d'information |
| Plan technique §3 | terrain conçu à la main, route sûre + route risquée | pas de génération procédurale à l'exécution |
| Plan technique §13 | chargement du site ≤ 3 s, 60 FPS 1080p | taille et découpage du maillage bornés |
| ADR 0010 | les limites de zone ne sont pas un relief à interpréter | la frontière jouable est une règle applicative, pas un mur de terrain |
| GDP §18 | low-poly atmosphérique, textures simples, identité par lumière et brouillard | réalisme = formes et lumière crédibles, pas photoréalisme |
| GDP §4.1 | coque I certifiée 60 m ; 100–115 % = dégâts croissants | une route ou un objet entre 60 et 69 m est un risque lisible, pas une mort |
| GDP §7.1 | zone d'écho de surface : 150 m, puis 75 m, minimum 50 m | le joueur arrive à ≤ 75 m de l'épave ; la portée sonar est 95 m |
| GDP §13.2 | une cible récente, deux leurres légers inscrits au registre | trois sites d'épave sur un seul terrain |
**Point à vérifier avant de bâtir dessus** (non vérifié à l'exécution) : dans
`vehicle_test_environment.gd`, le maillage visuel place la ligne 0 à z = +28
(proche) alors que `HeightMapShape3D` place la ligne 0 au z local le plus
négatif. Si c'est confirmé, la collision actuelle est le terrain visuel
retourné avant/arrière, et le sonar scanne la collision, pas le maillage. Les
tests d'intégration ne le détecteraient pas (ils comptent des échantillons,
pas une forme). Le nouvel acteur terrain doit avoir un test qui compare
hauteur visuelle et hauteur de collision en quelques points.
## 3. Partis pris de réalisme
Le site est une **plate-forme carbonatée de bordure de plateau** caraïbe,
l'environnement réel le plus courant à 25–45 m dans l'arc antillais :
- **Plateau** à 22–32 m : dalle de calcaire corallien recouverte de sable
biogène, patch reefs isolés, rides de sable orientées par la houle.
- **Système d'éperons et sillons** (« spur and groove ») sur la bordure
externe : crêtes rocheuses parallèles séparées de couloirs de sable de 8 à
20 m de large, descendant vers la rupture de pente. C'est la forme la plus
lisible au sonar et la plus naturelle pour créer des couloirs de navigation.
- **Rupture de pente** à 42–48 m puis **tombant** jusqu'à 85 m, avec un
**cône d'éboulis** au pied des sillons.
- **Sédimentation** : un navire échoué sur une pente de sable biogène
s'enfonce et se recouvre partiellement en quelques mois ; les objets lourds
glissent vers le bas de la pente. Les deux phénomènes servent le gameplay.
Ce qui reste hors réalisme volontairement : pas de corail animé, pas de
végétation dense, pas de courant (V0.5), pas de houle. Les formes, la lumière
décroissante avec la profondeur, le brouillard et les particules portent la
crédibilité, conformément à la direction artistique.
## 4. Le site
### 4.1 Dimensions
| Donnée | Valeur proposée |
|---|---:|
| Zone jouable | 600 × 600 m |
| Terrain physique | 768 × 768 m (marge de 84 m de chaque côté, noyée dans le brouillard) |
| Heightmap | 512 × 512 px, 1,5 m par cellule, 16 bits |
| Profondeur min / max du terrain | 20 m / 88 m |
| Profondeur d'écrasement coque I | hors terrain : le fond ne tue jamais par lui-même |
| Mouillage du navire | centre nord du plateau, 24 m de fond |
| Point de départ du sous-marin | sous le navire, 10 m de profondeur |
Les distances sont dimensionnées pour l'autonomie Standard (environ 1,2 km,
16 minutes d'oxygène) : aucune épave à plus de 320 m du mouillage, aucune
paire d'épaves à plus de 260 m l'une de l'autre.
### 4.2 Plan de masse (nord en haut, navire au centre nord)
```text
N
+---------------------------+ 20 m plateau clair, sable + patch reefs
| [Navire] |
| Rides . . | 26 m [B] leurre 1 : voilier de plaisance
| ~ ~ ~ [B] | posé à plat sur le sable, visible
| ~ ~ ~ ~ |
| les Deux ^^ l'Échine | 28 m crête longue nord-sud = fil d'Ariane
| Frères ^^ |||| |
| |||| |
| la Saignée |||| | 40 m [C] leurre 2 : caboteur acier dans
| \\\\\\ || [C] | un patch reef, échos roche + métal
| \\\\\\ || |
| \\\\\\ ====== | 45 m rupture de pente (ligne continue)
| \\\\\ [A] | 35 m [A] CIBLE : navire de prospection
| ----- .. . | dans un sillon, poupe sur la rupture
| tombant . . . | 50-64 traîne de débris descendant la pente
| ======== . | 62 m objet secondaire, légèrement
| 85 m | sous la profondeur certifiée
+---------------------------+
S
```
Noms de travail : **l'Échine** (crête), **les Deux Frères** (deux pitons
jumeaux), **les Rides** (champ de rides de sable), **la Saignée** (sillon
principal), **le Tombant**.
### 4.3 Les trois épaves et leur terrain
**[A] Cible — navire de prospection (35 m).** Couché dans le sillon de la
Saignée, à 15 m de la rupture de pente. Coque enfoncée d'un tiers dans le
sable (GDP §7.6, « coque enterrée dans le sédiment ») : au sonar, elle se lit
comme une bosse allongée métallique dans un couloir, pas comme une silhouette
évidente. La poupe dépasse au-dessus de la rupture ; le portique, un conteneur
et une partie du gréement ont glissé en contrebas et forment une **traîne de
débris** de 50 à 64 m le long du tombant. La traîne est un fil conducteur :
un joueur qui descend trop tôt sur le tombant la rencontre et peut la
remonter jusqu'à la coque. Caché par : la bosse de l'Échine à l'est, la
profondeur du sillon, le sédiment.
**[B] Leurre 1 — voilier de plaisance (26 m).** Posé à plat sur le sable, en
plein plateau, au bord des Rides. Facile à trouver, visible de loin. Bois et
résine : écho faible, aucun métal massif. Il apprend au joueur à lire une
silhouette et une matière au sonar. Contradiction découvrable : pas de
portique, un seul mât, taille moitié moindre.
**[C] Leurre 2 — caboteur en acier (40 m).** Encastré dans un patch reef sur
le flanc est de l'Échine. Même ordre de taille que la cible, même matériau :
le vrai piège. Les échos roche et métal se mêlent ; il faut contourner et
scanner deux fois pour isoler le contact. Contradictions : immatriculation
différente, deux hélices au lieu d'une, pas de portique, avarie qui ne
correspond pas au rapport.
### 4.4 Les deux routes vers la cible
**Route sûre — par l'Échine (≈ 420 m, 26–32 m).** Depuis le navire, suivre la
crête longue vers le sud. Elle est lumineuse, large, sans obstacle, et se lit
d'un seul scan. Elle mène au bord du plateau au-dessus de la Saignée : il
faut ensuite descendre dans le sillon par son extrémité nord, à faible
pente. Coût : temps et batterie. Récompense : zéro dégât, retour facile à
estimer.
**Route risquée — par la Saignée (≈ 260 m, 36–48 m).** Un sillon de 12 à
18 m de large, aux parois de 8 à 10 m, qui coupe le plateau en diagonale et
débouche directement sur la proue de la cible. Sombre (les projecteurs
deviennent nécessaires), étroit (collisions), en pente (la batterie de
remontée compte). Au sonar : une dépression continue, lisible comme une
« ouverture possible » (GDP §7.2, point 4). Aucune paroi ne surplombe, donc
compatible ADR 0010. Récompense : moitié moins de distance.
**Le tombant — la tentation (50–64 m).** Pas une route : une pente qui
descend sous la rupture. L'objet secondaire (1 unité, ~200 €) repose à 62 m,
dans la zone 100–107 % de la profondeur certifiée : craquements, dégâts lents,
alerte claire. Le joueur voit la traîne de débris descendre et doit décider
de s'arrêter. C'est le « site légèrement sous la profondeur certifiée » de
GDP §7.6 appliqué à un objet optionnel, jamais à la cible.
### 4.5 Repères pour naviguer sans GPS
Le joueur n'a ni carte locale ni marqueur. Le terrain doit donc fournir des
amers reconnaissables au sonar à 95 m :
| Amer | Forme sonar | Rôle |
|---|---|---|
| l'Échine | crête longue, orientée nord-sud | fil d'Ariane entre le navire et la cible |
| les Deux Frères | deux pitons jumeaux, 9 m de haut, 20 m d'écart | repère ouest unique, sert à se recaler |
| les Rides | ondulations régulières de 1 m | signe « plateau nord, navire proche » |
| la Saignée | sillon rectiligne, bords nets | entrée de la route risquée |
| la rupture de pente | ligne continue de rupture | « ne pas dépasser » et limite sud |
Chaque amer est unique sur le site : aucune forme n'est répétée ailleurs,
pour que la reconnaissance ne trompe pas.
## 5. Ce que le terrain apporte au gameplay
1. **Chercher avant de récupérer** (pilier GDP §1.4) : la cible n'est ni la
plus visible [B] ni la plus « métallique » [C] ; elle est la plus cachée.
L'écho de surface amène à ≤ 75 m, le sillon et le sédiment font le reste.
2. **Lecture du sonar comme compétence** : rides = plateau, crête = route,
dépression = passage, bosse dans un couloir = chose enfouie. Le site
enseigne un vocabulaire que les sites suivants réutiliseront.
3. **Risque prévisible** : chaque danger s'annonce avant de coûter. Le sillon
est visiblement étroit, la pente visiblement longue, l'objet à 62 m
visiblement sous la ligne de rupture.
4. **Décision de retour** : la route risquée à l'aller et l'Échine au retour
est le plan « malin » ; le terrain rend ce raisonnement possible.
5. **Enquête matérielle** : la traîne de débris raconte le naufrage (impact
sur la rupture, glissement, enfouissement) et concorde avec le rapport de
la société, ce que les leurres ne font pas.
6. **Rejouabilité** : revenir au site après identification (GDP §8, « repère
local ») pour récupérer l'objet secondaire est une mini-expédition avec un
seul but : gérer la profondeur.
## 6. Sonar et matériaux par cellule
Aujourd'hui le matériau sonar est une meta par corps. Le site a besoin de
roche, sable et métal selon l'endroit touché :
- un **masque de matériaux** 512 × 512 (R = roche, G = sable, B = réservé
débris/concrétion) accompagne la heightmap ;
- l'acteur terrain expose `sonar_material_at(world_position)` et
`sonar_reflectivity_at(world_position)` ; l'acquisition les appelle quand
le collider les possède, sinon lit la meta comme aujourd'hui ;
- réflectivités de départ : roche 0,72 (valeur actuelle), sable 0,45, métal
1,0. Les valeurs vivent dans la définition de site, pas dans le code.
Les épaves restent des corps distincts avec leur propre meta ; le clustering
de contacts existant les sépare du fond.
## 7. Rendu
- Un seul matériau terrain, shader Forward+ : mélange **triplanaire** sable /
roche piloté par la pente (sable sous 25°, roche au-dessus de 40°, fondu
entre), normal map de rides sur le sable, teinte assombrie avec la
profondeur pour suivre la palette GDP §18.2 (vert clair à 25 m, bleu froid
à 45 m, indigo au pied du tombant).
- Maillage découpé en **64 tuiles de 96 × 96 m** (64 × 64 cellules), avec
`visibility_range` pour ne dessiner que les tuiles dans le brouillard
utile ; une seule `HeightMapShape3D` pour la collision.
- Props low-poly posés à la main, en nombre borné : blocs d'éboulis au pied
du tombant, têtes de corail sur les patch reefs, rien d'animé.
- Brouillard, lumière directionnelle et particules de la scène de test
actuelle sont conservés et réglés par site.
## 8. Architecture proposée
| Couche | Élément | Responsabilité |
|---|---|---|
| `game/domain/sites/` | `DiveSiteDefinition` (Resource typée) | id, chemin de scène, heightmap, masque, origine, taille de cellule, profondeur de référence, limites jouables, position de départ, mouillage, placements d'épaves, zones d'écho, réflectivités |
| `game/domain/sites/` | `TerrainHeightField` (RefCounted pur) | lecture de hauteur et de matériau à une position, conversion monde ↔ cellule, bornes ; testable sans scène |
| `game/application/sites/` | `PlayableBoundsRule` | « hors zone » comme résultat typé depuis la télémétrie ; émet un avertissement, jamais un mur |
| `game/world/sites/` | `BathymetricTerrainActor` | construit tuiles, collision et matériau depuis la définition ; expose matériau sonar par position |
| `game/world/sites/` | `dive_site_zone1.tscn` | scène du site : terrain, environnement, points d'injection pour épaves et navire |
| `game/composition/` | câblage | charge la définition, instancie le site, injecte la règle de bornes |
| `content/sites/` | `zone1_vigilant.tres` + `zone1_vigilant_height.png` + `zone1_vigilant_mask.png` | données du site |
| `tools/` (hors runtime) | script de cuisson | produit les PNG depuis une description de primitives géomorphologiques ; déterministe, versionné, jamais appelé par le jeu |
Les conventions du contrat : hauteur en mètres négatifs vers le bas, +X est,
-Z nord (convention Godot, convertie une seule fois dans
`TerrainHeightField`), heightmap 16 bits avec `depth_min_m` et `depth_max_m`
explicites. Ces points vont dans un **ADR 0012 — terrain de site en champ de
hauteur authoré**, requis par les guardrails §5 et §11 (nouveau contrat de
données persistant dans le dépôt).
`vehicle_test_environment.gd` perd sa formule analytique : la formule devient
le premier cas d'usage du script de cuisson, et la scène de test charge une
petite définition de site (fixture) comme le ferait le vrai site.
## 9. Pipeline d'auteur
1. **Graybox cuit** (cette tranche) : une description déclarative des
primitives (plateau, crête, pitons, sillon, rupture, tombant, rides)
dans le script de cuisson. Itération en minutes, diff lisible, aucun outil
externe. C'est « conçu à la main » : chaque forme est placée et nommée.
2. **Passe de sculpture** (tranche 6) : export de la heightmap vers Blender,
retouche manuelle, réimport. Le contrat ne change pas.
3. **Jamais** de génération à l'exécution ni de dépendance à un plugin
terrain ; si un plugin devenait souhaitable, ADR d'abord.
## 10. Tests
- **Unitaires** : `TerrainHeightField` (interpolation bilinéaire, bornes,
conversion monde ↔ cellule, matériau par cellule) ; `PlayableBoundsRule`.
- **Acteur** : hauteur de collision égale à la hauteur du champ en plusieurs
points, dont les quatre coins (ferme le doute du §2).
- **Contrats** sur `zone1_vigilant.tres` : trois placements d'épave dans les
limites ; cible et objets requis au-dessus de 60 m ; objet secondaire entre
60 et 69 m ; les amers listés sont uniques (pas deux crêtes de même
signature) ; les deux routes existent sous forme de chemins de contrôle
(liste de points) dont chaque point respecte sa profondeur annoncée et
n'est pas dans la roche.
- **Intégration** : charger le site, lancer un scan de référence depuis la
position de départ et vérifier roche et sable dans le buffer ; un rayon
vers le sillon touche le terrain ; temps de chargement sous 3 s.
- **Humains** (playtest tranche 3) : 8/10 trouvent l'accès en 5–10 min ; les
testeurs nomment spontanément au moins un amer.
## 11. Ordre de construction
1. ADR 0012, `DiveSiteDefinition`, `TerrainHeightField` et leurs tests.
2. `BathymetricTerrainActor` avec tuiles, collision et matériau sonar par
position ; migration de l'environnement de test sur une fixture.
3. Script de cuisson et première heightmap du Banc du Vigilant (graybox) ;
bornes jouables ; scène `dive_site_zone1.tscn`.
4. Shader triplanaire et props bornés.
5. Points d'injection pour les trois épaves et le navire (les épaves
elles-mêmes appartiennent au reste de la tranche 3).
Chaque étape laisse la barrière verte et la scène jouable.
## 12. Décisions demandées à Olivier
1. **Validation du plan de masse** (§4.2–4.4) : trois épaves, deux routes, un
tombant tentateur. Variante possible : déplacer le leurre 2 dans la Saignée
pour piéger la route risquée.
2. **Objet secondaire à 62 m** : garder la tentation sous la profondeur
certifiée, ou le remonter à 55 m pour un premier site plus doux ?
3. **Pipeline** : script de cuisson d'abord (recommandé) ou sculpture Blender
dès le graybox ?
4. **Nom** : « Banc du Vigilant » ou autre.