Implement production vertical slice foundation
This commit is contained in:
1 parent
9d4a89f355
commit
a18e82eb44
104 files changed
+10595
-268
No files matched your search
@@ -0,0 +1,73 @@
|
||||
# 0004 — Forward+ comme renderer unique de production
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
Les POC A et B ont été validés avec GL Compatibility afin de faciliter les
|
||||
premiers essais. Cette configuration a aussi conduit le POC A à simuler la
|
||||
diffusion des projecteurs avec des plans translucides dépendants du point de
|
||||
vue. Ces compromis restent documentés dans les baselines, mais ne répondent pas
|
||||
à la direction visuelle de la production : matériaux PBR, éclairage sous-marin,
|
||||
brouillard, particules et ombres réglables.
|
||||
|
||||
Maintenir plusieurs renderers augmenterait le nombre de configurations à
|
||||
tester et encouragerait des chemins graphiques divergents. Les performances
|
||||
doivent être ajustées par la qualité des effets, pas par un changement de
|
||||
renderer qui modifierait le rendu et les capacités disponibles.
|
||||
|
||||
## Décision
|
||||
|
||||
Forward+ est l'unique renderer pris en charge par le code et les builds de
|
||||
production. Le jeu ne propose ni sélection de renderer, ni repli automatique
|
||||
vers GL Compatibility.
|
||||
|
||||
Les POC demeurent des références historiques jetables dans leur configuration
|
||||
GL Compatibility documentée. Ils ne définissent pas une seconde configuration
|
||||
prise en charge et leur code ou leurs artifices graphiques ne sont pas repris
|
||||
en production.
|
||||
|
||||
Les réglages d'affichage permettent d'adapter les performances sans quitter
|
||||
Forward+. Ils couvrent au minimum des niveaux de qualité pour les particules,
|
||||
les ombres, la distance d'affichage et le post-traitement. Les effets
|
||||
atmosphériques coûteux, dont le brouillard volumétrique s'il est retenu après
|
||||
mesure, suivent la même politique. Des préréglages cohérents peuvent exposer
|
||||
ces valeurs ensemble, avec des réglages détaillés lorsque cela reste lisible.
|
||||
|
||||
Une baisse de qualité ne change aucune règle de gameplay et ne peut supprimer
|
||||
une information indispensable à la navigation, aux alarmes ou à la lecture du
|
||||
sonar. Les choix sont persistés dans les réglages du joueur, séparément de la
|
||||
sauvegarde de campagne.
|
||||
|
||||
Chaque mesure de performance indique le renderer Forward+, la résolution, le
|
||||
préréglage graphique, la machine, le build et la scène testée. La première
|
||||
scène de production mesure explicitement le coût des projecteurs, des ombres,
|
||||
du brouillard et des particules avant la phase de finition visuelle.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Le rendu de production possède une seule configuration architecturale à
|
||||
développer et vérifier.
|
||||
- Les machines ne prenant pas correctement en charge Forward+ ne sont pas des
|
||||
cibles de la V1.
|
||||
- Les performances faibles se traitent par des niveaux de qualité mesurés,
|
||||
des LOD et des budgets d'effets, sans branche de rendu alternative.
|
||||
- Le mode bas conserve la lisibilité fonctionnelle à 1080p tout en réduisant
|
||||
particules, ombres, distance d'affichage et post-traitement.
|
||||
- Le comportement visuel doit être vérifié sur macOS ARM64, Windows et Linux
|
||||
avant la fin de la verticale.
|
||||
- Les plans translucides utilisés comme volumes de phare dans le POC A ne sont
|
||||
pas promus ; les projecteurs de production sont reconstruits et profilés.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **GL Compatibility comme renderer de production** : rejeté, car ses limites
|
||||
contrarient les besoins d'éclairage et d'atmosphère visés.
|
||||
- **Forward+ avec GL Compatibility comme mode de secours** : rejeté, car cela
|
||||
imposerait deux chemins graphiques, deux profils de performance et davantage
|
||||
de régressions visuelles possibles.
|
||||
- **Mobile comme renderer de secours** : rejeté pour la V1 pour les mêmes
|
||||
raisons. Une cible matérielle future nécessiterait un nouvel ADR et une
|
||||
validation graphique dédiée.
|
||||
@@ -0,0 +1,139 @@
|
||||
# 0005 — Ticks de plongée fixes et mises à jour typées
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
La plongée combine une physique Godot, des ressources continues, des dégâts
|
||||
ponctuels, des outils électriques, des alarmes et plusieurs présentations. Si
|
||||
chaque acteur ou interface utilise sa propre horloge ou recalcule une partie de
|
||||
ces règles, la pause, les variations de framerate et l'ordre des signaux peuvent
|
||||
produire des résultats différents.
|
||||
|
||||
Les informations n'ont pas toutes la même nature. Une commande exprime une
|
||||
intention, la télémétrie décrit une mesure du monde, un snapshot décrit l'état
|
||||
autoritaire à un instant et un événement rapporte un fait survenu pendant une
|
||||
transition. Les regrouper dans un dictionnaire ou un signal générique rendrait
|
||||
leur propriétaire et leur temporalité implicites.
|
||||
|
||||
## Décision
|
||||
|
||||
### Horloge et cadence
|
||||
|
||||
La simulation de plongée utilise une cadence de physique configurée à 60 Hz.
|
||||
L'application fournit exactement un `DiveStep` au domaine pour chaque tick de
|
||||
physique accepté. Le domaine n'accède ni à l'horloge système, ni au framerate,
|
||||
ni à l'arbre de scènes.
|
||||
|
||||
Un `DiveTick` contient au minimum l'identifiant de session, une séquence
|
||||
strictement croissante et la durée du pas en secondes. La durée normale vaut
|
||||
`1 / 60` seconde. Un pas nul, négatif, non fini ou désordonné est refusé. Un pas
|
||||
supérieur à 0,1 seconde est subdivisé de manière déterministe par l'application
|
||||
ou refusé ; il n'est jamais appliqué comme un grand saut unique.
|
||||
|
||||
La pause suspend la production de `DiveStep`. À la reprise, le temps passé en
|
||||
pause n'est ni simulé, ni rattrapé. Les tests utilisent des ticks construits
|
||||
explicitement et n'attendent jamais le temps réel.
|
||||
|
||||
### Contrats d'entrée séparés
|
||||
|
||||
- `VehicleCommand` contient l'intention de propulsion issue du clavier ou d'un
|
||||
autre périphérique remappé. La souris n'oriente jamais le sous-marin.
|
||||
- `CameraLookCommand` contient uniquement le mouvement de regard dans la
|
||||
cabine. Il ne traverse pas le contrat de pilotage du véhicule.
|
||||
- `VehicleTelemetry` est un snapshot immuable produit par l'acteur physique :
|
||||
transform, vitesses, profondeur et efforts réellement appliqués.
|
||||
- `DiveTelemetrySample` réduit cette télémétrie aux mesures nécessaires aux
|
||||
règles de plongée. Le domaine ne reçoit aucun `Node` ou `Transform3D` Godot.
|
||||
- `CollisionObservation` décrit un impact ponctuel avec une séquence stable et
|
||||
sa vitesse normale en mètres par seconde. Les observations sont traitées de
|
||||
manière idempotente.
|
||||
- `ToolPowerDemand`, `EjectionIntent` et `ReturnRouteSample` décrivent
|
||||
séparément la demande électrique des outils, l'intention d'éjection et les
|
||||
données connues pour estimer le retour.
|
||||
- `DiveStep` agrège ces entrées pour un tick sans changer leur responsabilité.
|
||||
|
||||
Ces frontières utilisent des objets typés. Les dictionnaires anonymes restent
|
||||
confinés aux codecs ou aux prototypes et ne traversent pas la production.
|
||||
|
||||
### Règles résolues et session
|
||||
|
||||
Au début de chaque plongée, `DiveRulesResolver` construit un
|
||||
`ResolvedDiveRules` immuable en appliquant, dans cet ordre :
|
||||
|
||||
1. les règles de base ;
|
||||
2. les capacités et améliorations du sous-marin ;
|
||||
3. le profil de difficulté ;
|
||||
4. les aides d'accessibilité qui modifient le gameplay ;
|
||||
5. la validation et le bornage des valeurs.
|
||||
|
||||
`DiveSession` est l'unique propriétaire de l'oxygène, de la batterie, de la
|
||||
coque, des seuils de pression, des alertes, de l'estimation de retour et de
|
||||
l'état terminal de la plongée. C'est un objet de domaine pur : il reçoit un
|
||||
`DiveStep`, applique les règles résolues dans un ordre fixe et retourne un
|
||||
`DiveUpdate`.
|
||||
|
||||
L'ordre d'un pas est : validation, consommation, pression, collisions ordonnées,
|
||||
éjection, estimation du retour, alertes, état terminal, puis publication. Une
|
||||
session terminale ne rejoue pas sa conséquence et refuse toute mutation de
|
||||
gameplay ultérieure.
|
||||
|
||||
### Snapshot et événements
|
||||
|
||||
Chaque pas accepté produit un seul `DiveUpdate` cohérent, associé à la session
|
||||
et à la séquence du tick. Il contient :
|
||||
|
||||
- un `DiveSnapshot` immuable représentant l'état autoritaire après le pas ;
|
||||
- zéro ou plusieurs événements typés décrivant uniquement les faits survenus
|
||||
pendant ce pas.
|
||||
|
||||
Le snapshot contient les valeurs actuelles et maximales, leurs unités et leurs
|
||||
ratios pour batterie, oxygène, coque, pression et profondeur, ainsi que
|
||||
l'estimation du retour, les alertes, l'éjection et l'éventuel motif terminal.
|
||||
Il permet à un nouvel écran de se synchroniser sans rejouer l'historique.
|
||||
|
||||
Les événements, tels que `AlertLevelChanged`, `HullDamaged`,
|
||||
`ResourceDepleted` et `DiveTerminated`, déclenchent les réactions ponctuelles :
|
||||
audio, animation, journal ou transition applicative. Ils portent une identité
|
||||
ou une séquence permettant aux adaptateurs d'éviter un double traitement. Un
|
||||
événement ne remplace jamais une valeur persistante du snapshot.
|
||||
|
||||
La présentation et l'audio consomment `DiveUpdate`. Ils ne recalculent ni
|
||||
seuils, ni dégâts, ni consommation, ni fin de plongée. Ils ne mutent jamais
|
||||
directement `DiveSession` ou l'acteur physique ; toute action repart sous forme
|
||||
de commande applicative.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Une même suite de règles, commandes, télémétries et observations produit le
|
||||
même résultat dans les tests et dans le jeu.
|
||||
- La pause est une absence de ticks, pas un multiplicateur de temps dispersé
|
||||
entre plusieurs systèmes.
|
||||
- Le HUD peut afficher des valeurs exactes et des pourcentages sans posséder
|
||||
une copie concurrente des ressources.
|
||||
- L'audio peut réagir une seule fois aux transitions tout en consultant l'état
|
||||
courant à tout moment.
|
||||
- La conversion entre les types Godot et les données pures nécessite des
|
||||
adaptateurs explicites.
|
||||
- Ajouter une nouvelle entrée ou sortie de simulation demande un contrat nommé
|
||||
et des tests, mais évite les clés implicites et les dépendances de scène.
|
||||
- Les consommations indépendantes du tick de plongée, notamment les actions de
|
||||
port, restent des cas d'usage de campagne distincts.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Chaque système utilise `_process(delta)`** : rejeté, car les règles
|
||||
dépendraient du framerate et leur ordre serait difficile à garantir.
|
||||
- **`DiveSession` lit directement la physique et l'horloge Godot** : rejeté,
|
||||
car le domaine ne serait plus pur ni testable sans scène.
|
||||
- **Un dictionnaire unique de données par frame** : rejeté, car commandes,
|
||||
mesures, états et événements auraient une temporalité implicite.
|
||||
- **Publier uniquement des événements** : rejeté, car un écran ouvert plus tard
|
||||
devrait reconstruire l'état en rejouant l'historique.
|
||||
- **Publier uniquement un snapshot** : rejeté, car les consommateurs devraient
|
||||
comparer deux états et réinventer les transitions ponctuelles.
|
||||
- **Rattraper les ticks après une pause ou un ralentissement important** :
|
||||
rejeté, car cela provoquerait des consommations et dégâts invisibles ou des
|
||||
pics de calcul au retour.
|
||||
@@ -0,0 +1,149 @@
|
||||
# 0006 — Contrat sonar commun et porte de sélection de l'acquisition
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
Le POC B a validé une représentation bathymétrique continue, révélée
|
||||
progressivement, qui rend le relief navigable. Son acquisition principale
|
||||
utilise toutefois des sondes verticales disposées devant le véhicule et peut
|
||||
montrer le dessus de surfaces qu'un faisceau frontal ne verrait pas. Une passe
|
||||
frontale distincte détecte les anomalies métalliques. Cette combinaison est
|
||||
lisible, mais elle n'est ni une simulation acoustique fidèle, ni une
|
||||
implémentation de production.
|
||||
|
||||
Une acquisition entièrement frontale serait plus cohérente avec la position du
|
||||
capteur, mais risque de produire des trous, de perdre la continuité du relief ou
|
||||
de rendre le sonar à nouveau difficile à interpréter. Le comportement validé du
|
||||
POC doit donc rester la référence pendant l'expérience, sans importer son code
|
||||
jetable dans la production.
|
||||
|
||||
L'acquisition, la reconstruction et la présentation doivent pouvoir évoluer
|
||||
séparément. Sinon, comparer deux méthodes imposerait aussi de réécrire le
|
||||
renderer et rendrait leurs résultats impossibles à évaluer équitablement.
|
||||
|
||||
## Décision
|
||||
|
||||
### Contrat commun
|
||||
|
||||
Toutes les acquisitions candidates produisent le même `SonarScan`. Celui-ci
|
||||
contient au minimum :
|
||||
|
||||
- un identifiant de scan et l'identifiant de la session ;
|
||||
- le transform du capteur figé à l'émission ;
|
||||
- la portée, les ouvertures et la durée de révélation ;
|
||||
- les dimensions logiques de la grille ;
|
||||
- un `SonarSampleBuffer` immuable ;
|
||||
- des `SonarContact` distincts ;
|
||||
- l'échelle de couleur et les valeurs réelles minimales et maximales ;
|
||||
- l'état prêt, capture, révélation ou récupération.
|
||||
|
||||
Le repère du scan est figé au déclenchement, avec son origine au capteur, +X à
|
||||
tribord, +Y vers le haut et +Z vers l'avant, en mètres. L'adaptateur du monde
|
||||
convertit le -Z avant de Godot vers ce contrat. Aucun consommateur ne déduit ou
|
||||
réinterprète cette convention.
|
||||
|
||||
`SonarSampleBuffer` encapsule des tableaux parallèles compacts de positions,
|
||||
normales, intensités, élévations réelles, matériaux et statuts d'observation.
|
||||
Un même index décrit un échantillon ; la ligne et la colonne sont dérivées des
|
||||
dimensions de grille. Un accesseur typé comme `sample_at(row, column)` masque la
|
||||
représentation interne et vérifie les bornes. Le buffer devient immuable avant
|
||||
sa publication.
|
||||
|
||||
Les contacts ne sont pas obtenus en moyennant tous les retours d'un matériau.
|
||||
Un clustering spatial déterministe produit plusieurs `SonarContact`, chacun
|
||||
avec une identité, un matériau, un centre, des limites, une intensité maximale
|
||||
et un nombre d'échantillons.
|
||||
|
||||
### Acquisition, reconstruction et présentation
|
||||
|
||||
L'adaptateur sonar du monde possède l'acquisition physique. Le service
|
||||
applicatif valide et structure les échantillons ainsi que les contacts. La
|
||||
présentation reconstruit et affiche le relief à partir du scan publié ; elle ne
|
||||
fait ni classification métier, ni détection de mission.
|
||||
|
||||
La palette d'altitude reste relative au scan pour préserver le contraste, mais
|
||||
les élévations réelles en mètres sont conservées et une légende chiffrée indique
|
||||
l'échelle employée. Noir représente l'inconnu, pas une profondeur arbitraire.
|
||||
|
||||
Un seul scan courant et un seul scan précédent en fondu existent au maximum.
|
||||
La vue compacte et la vue agrandie affichent la même texture produite par un
|
||||
renderer unique. Elles ne reconstruisent pas deux maillages indépendants.
|
||||
|
||||
La révélation de référence dure 2,5 secondes, puis la récupération 0,35 seconde.
|
||||
Une nouvelle demande n'est pas mise en file pendant cette séquence. Ces valeurs
|
||||
restent configurables et testées, mais leur temporalité appartient au service
|
||||
sonar, pas au HUD.
|
||||
|
||||
### Porte de sélection
|
||||
|
||||
Deux acquisitions sont réécrites derrière ce contrat uniquement pendant une
|
||||
calibration bornée :
|
||||
|
||||
1. la méthode de référence inspirée du POC B, combinant une grille
|
||||
bathymétrique lisible et une détection frontale des anomalies ;
|
||||
2. une méthode par faisceau frontal, reconstruite dans le même buffer.
|
||||
|
||||
La comparaison utilise les mêmes poses de capteur, scènes, portées, dimensions
|
||||
de sortie et cas de test : pente, chenal, rupture de relief, épave, ouverture,
|
||||
zones masquées et plusieurs contacts métalliques séparés. Elle mesure au
|
||||
minimum :
|
||||
|
||||
- la compréhension du relief et d'un passage par des testeurs ;
|
||||
- la détection de l'épave et de plusieurs anomalies sans fusion incorrecte ;
|
||||
- la stabilité face aux trous et aux rotations du véhicule ;
|
||||
- le coût CPU moyen et maximal, les allocations et le coût de reconstruction ;
|
||||
- la conservation de l'effet de révélation validé.
|
||||
|
||||
Le faisceau frontal n'est retenu que s'il atteint une lisibilité et une
|
||||
stabilité au moins équivalentes à la réécriture de référence dans les budgets
|
||||
de la verticale. Dans le cas contraire, la méthode inspirée du POC devient
|
||||
l'acquisition de production. La fidélité acoustique ne prime pas sur la
|
||||
capacité du joueur à lire le relief et à naviguer.
|
||||
|
||||
La porte produit un compte rendu et un ADR de sélection. Après cette décision,
|
||||
une seule acquisition reste autoritaire dans `game/`. L'autre implémentation
|
||||
n'est pas maintenue comme chemin de secours ; les scènes, données de calibration
|
||||
et résultats comparatifs peuvent être conservés pour prévenir les régressions.
|
||||
|
||||
### Persistance
|
||||
|
||||
Ni les échantillons bruts, ni le buffer, ni le maillage, ni les couleurs d'un
|
||||
scan sous-marin ne sont sauvegardés. La campagne persiste seulement les faits
|
||||
sémantiques sécurisés : zones d'écho de surface, épaves localisées, identités et
|
||||
observations. Une sauvegarde ne tente jamais de reconstruire une image sonar en
|
||||
cours de révélation.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Le comportement apprécié dans le POC reste disponible comme référence et
|
||||
issue sûre sans promouvoir son code.
|
||||
- Une acquisition peut être remplacée sans modifier le renderer, le HUD ou les
|
||||
règles de mission.
|
||||
- Le buffer compact limite les allocations, mais demande un accesseur typé et
|
||||
des tests d'alignement de tous les tableaux.
|
||||
- Les conversions de coordonnées sont explicites et testables.
|
||||
- Plusieurs anomalies restent distinctes, contrairement à la moyenne globale
|
||||
provisoire du POC.
|
||||
- Le rendu sonar possède une seule reconstruction et une seule texture, ce qui
|
||||
réduit les divergences entre les deux tailles d'affichage.
|
||||
- La calibration ajoute un coût court à la tranche sonar, borné par une porte
|
||||
de décision et supprimant ensuite le chemin perdant.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Copier le sonar du POC B dans la production** : rejeté, car cela
|
||||
introduirait ses dépendances, sa reconstruction complète et ses contrats
|
||||
implicites dans `game/`.
|
||||
- **Choisir immédiatement le faisceau frontal** : rejeté, car sa vraisemblance
|
||||
ne garantit pas la lisibilité déjà difficile à obtenir.
|
||||
- **Conserver durablement les deux acquisitions** : rejeté, car deux
|
||||
implémentations autoritaires doubleraient réglages, tests et risques de
|
||||
régression.
|
||||
- **Publier directement des nœuds, maillages ou dictionnaires depuis le monde** :
|
||||
rejeté, car acquisition et présentation resteraient couplées.
|
||||
- **Sauvegarder la carte sonar brute** : rejeté, car elle représente une vue
|
||||
temporaire dérivée du monde et alourdirait le format sans bénéfice de
|
||||
progression.
|
||||
@@ -0,0 +1,192 @@
|
||||
# 0007 — Sauvegardes JSON versionnées et remplaçables sans perte
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
La campagne contient un état métier durable : argent, dette, position du
|
||||
navire, contrats, archives, épaves connues, cargaison et améliorations. Une
|
||||
plongée contient en plus un état physique très fréquent et temporaire. Tenter
|
||||
de sérialiser les nœuds, les collisions, le maillage sonar ou la position
|
||||
arbitraire du sous-marin couplerait la sauvegarde aux scènes et rendrait les
|
||||
migrations fragiles.
|
||||
|
||||
Le joueur doit pouvoir conserver plusieurs étapes d'une même campagne, utiliser
|
||||
des sauvegardes manuelles et reprendre après un crash sans perdre un
|
||||
sous-marin à cause d'une écriture interrompue. Les réglages de plateforme et
|
||||
d'accessibilité ne doivent pas être dupliqués dans chaque état de campagne.
|
||||
|
||||
## Décision
|
||||
|
||||
### Format et enveloppe
|
||||
|
||||
Chaque sauvegarde est un document JSON explicite. Son enveloppe contient au
|
||||
minimum :
|
||||
|
||||
```text
|
||||
schema_version entier positif
|
||||
campaign_id identifiant stable de la partie
|
||||
save_id identifiant stable de cette sauvegarde
|
||||
created_at_utc date ISO 8601 utilisée comme métadonnée d'affichage
|
||||
kind before_dive | after_dive | campaign | manual
|
||||
display_name libellé facultatif d'une sauvegarde manuelle
|
||||
payload état de campagne versionné
|
||||
```
|
||||
|
||||
Les identifiants sont générés et validés par l'application. Un libellé saisi
|
||||
par le joueur n'est jamais utilisé comme nom de fichier ou fragment de chemin.
|
||||
Les horodatages viennent d'une horloge injectée ; ils n'influencent aucune
|
||||
règle de gameplay.
|
||||
|
||||
Le codec JSON appartient à l'infrastructure. Il convertit entre les
|
||||
dictionnaires du format et des objets de transfert typés, puis entre ces objets
|
||||
et le domaine. Aucun dictionnaire anonyme, chemin de scène, `Node`, `Resource`
|
||||
arbitraire ou objet exécutable ne traverse cette frontière.
|
||||
|
||||
Le payload contient au minimum :
|
||||
|
||||
- difficulté, argent et dette ;
|
||||
- `VesselLocation`, disponibilité du sous-marin et ressources non remplies ;
|
||||
- contrats, objectifs connus et révélations ;
|
||||
- zones d'écho, épaves localisées, identités et observations sécurisées ;
|
||||
- états persistants d'ouverture et d'interaction ;
|
||||
- panier, cale, stockage et objets narratifs ;
|
||||
- archives, plans et améliorations ;
|
||||
- dernier résultat de plongée.
|
||||
|
||||
Les références de contenu utilisent des identifiants stables validés au
|
||||
chargement. Une valeur dérivée est recalculée à partir de ses sources lorsqu'il
|
||||
est possible de le faire sans perte d'information.
|
||||
|
||||
### Organisation des fichiers
|
||||
|
||||
Les campagnes sont rangées sous :
|
||||
|
||||
```text
|
||||
user://saves/<campaign_id>/
|
||||
autosave_before_dive.json
|
||||
autosave_after_dive.json
|
||||
autosave_campaign.json
|
||||
manual/<save_id>.json
|
||||
active_dive.marker.json
|
||||
```
|
||||
|
||||
Les fichiers temporaires et de secours utilisent des suffixes techniques dans
|
||||
le même dossier que leur cible. Ils ne sont pas affichés comme des sauvegardes.
|
||||
Le `campaign_id` identifie la lignée créée par une nouvelle partie ; il ne
|
||||
représente pas une seconde campagne narrative.
|
||||
|
||||
Les réglages du joueur sont versionnés et stockés séparément sous
|
||||
`user://settings.json`. Ils comprennent notamment commandes, accessibilité,
|
||||
audio, affichage et qualité Forward+. Charger une autre sauvegarde de campagne
|
||||
ne les remplace pas.
|
||||
|
||||
### Politique des emplacements
|
||||
|
||||
Trois emplacements automatiques ont une signification fixe :
|
||||
|
||||
- `before_dive` est écrit après validation de la préparation et avant le
|
||||
chargement de la scène sous-marine ;
|
||||
- `after_dive` est écrit après application unique du résultat de plongée au
|
||||
navire et à la campagne ;
|
||||
- `campaign` est écrit après une action durable de progression, notamment
|
||||
transfert, analyse, remise, vente, entretien ou achat.
|
||||
|
||||
Chaque autosauvegarde conserve sa dernière version valide comme secours
|
||||
invisible. Une sauvegarde manuelle remplacée conserve également sa précédente
|
||||
version valide comme secours technique.
|
||||
|
||||
Le joueur peut créer jusqu'à dix sauvegardes manuelles nommées, uniquement
|
||||
lorsqu'aucune plongée n'est active. Atteindre la limite exige de choisir et de
|
||||
confirmer un remplacement ou une suppression ; aucune sauvegarde visible n'est
|
||||
effacée automatiquement.
|
||||
|
||||
`Continuer` charge la sauvegarde principale valide la plus récente parmi tous
|
||||
les emplacements visibles. Si elle est invalide, son secours est essayé, puis
|
||||
la recherche continue avec les autres sauvegardes valides. `Charger` affiche
|
||||
les sauvegardes visibles avec leur statut sans supprimer ni réécrire les
|
||||
fichiers invalides.
|
||||
|
||||
### Écriture récupérable
|
||||
|
||||
Une écriture suit toujours cette procédure :
|
||||
|
||||
1. sérialiser vers un fichier temporaire créé dans le dossier de la cible ;
|
||||
2. fermer le fichier, puis le relire intégralement ;
|
||||
3. décoder, migrer si nécessaire et valider le document relu ;
|
||||
4. préserver la cible valide actuelle comme secours ;
|
||||
5. remplacer la cible par renommage sur le même volume ;
|
||||
6. restaurer le secours si le remplacement final échoue ;
|
||||
7. signaler explicitement le succès ou l'erreur à l'application.
|
||||
|
||||
La dernière sauvegarde valide n'est jamais supprimée avant qu'une nouvelle
|
||||
copie complète ait été écrite et validée. Un échec d'I/O ne devient ni une
|
||||
réussite silencieuse, ni un nouvel état de campagne.
|
||||
|
||||
Au démarrage, l'infrastructure peut supprimer uniquement les temporaires
|
||||
orphelins dont la cible ou le secours valide a été identifié. Elle ne supprime
|
||||
jamais automatiquement une sauvegarde visible invalide.
|
||||
|
||||
### Plongée interrompue
|
||||
|
||||
Après réussite de l'autosauvegarde `before_dive`, le démarrage effectif de la
|
||||
plongée crée `active_dive.marker.json`. Ce marqueur contient seulement le
|
||||
`campaign_id`, le `save_id` de reprise et un identifiant de session. Il ne
|
||||
contient aucune position, ressource, collision ou donnée sonar.
|
||||
|
||||
Une fin de plongée traitée avec succès supprime le marqueur après écriture de
|
||||
l'état `after_dive`. Si le jeu redémarre avec un marqueur valide, il propose ou
|
||||
effectue la reprise depuis l'autosauvegarde `before_dive` référencée. Le crash
|
||||
n'inflige ni perte automatique du véhicule, ni consommation intermédiaire.
|
||||
|
||||
La position arbitraire du sous-marin, les vitesses, particules, collisions,
|
||||
échantillons sonar, couleurs et maillages dynamiques ne sont jamais sauvegardés.
|
||||
|
||||
### Versions et migrations
|
||||
|
||||
`schema_version` existe dès la V1. Le chargement applique des migrations
|
||||
explicites, successives et déterministes d'une version prise en charge vers la
|
||||
version courante, puis valide l'ensemble des invariants et références de
|
||||
contenu.
|
||||
|
||||
Une fixture anonymisée de chaque version prise en charge est conservée sous
|
||||
`tests/fixtures/`. Les tests vérifient migration, aller-retour, sauvegarde
|
||||
tronquée, référence absente, secours et refus d'une version inconnue.
|
||||
|
||||
Une version plus récente que celle du jeu est refusée proprement. Le fichier
|
||||
original n'est ni modifié, ni rétrogradé. Une migration réussie en mémoire ne
|
||||
réécrit pas non plus l'original avant une nouvelle sauvegarde explicitement
|
||||
déclenchée.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Les sauvegardes survivent aux changements de scènes et peuvent être testées
|
||||
sans lancer une plongée.
|
||||
- Plusieurs étapes d'une partie coexistent sans transformer les libellés du
|
||||
joueur en chemins dangereux.
|
||||
- Une plongée ne peut pas être reprise à la seconde exacte de l'interruption ;
|
||||
elle recommence depuis sa préparation validée.
|
||||
- Les sauvegardes et leurs secours consomment davantage d'espace, mais elles ne
|
||||
contiennent pas les données physiques ou sonar volumineuses.
|
||||
- Chaque modification du format exige une migration et des fixtures de
|
||||
contrat. Toute exception nécessite un nouvel ADR.
|
||||
- Les réglages restent disponibles même lorsqu'aucune campagne valide n'existe.
|
||||
- Les erreurs de disque ou de validation restent récupérables et visibles pour
|
||||
le joueur.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Sérialiser l'arbre de scènes Godot** : rejeté, car les chemins, nœuds et
|
||||
états physiques ne constituent pas un contrat de sauvegarde stable.
|
||||
- **Sauvegarder pendant la plongée** : rejeté pour la V1, car restaurer une
|
||||
simulation cohérente coûterait beaucoup plus que reprendre avant le départ.
|
||||
- **Une seule sauvegarde écrasée en place** : rejeté, car une interruption
|
||||
d'écriture pourrait détruire toute la progression.
|
||||
- **Un format binaire opaque** : rejeté pour la V1, car il compliquerait
|
||||
inspection, fixtures et migrations sans besoin de taille démontré.
|
||||
- **Inclure les réglages dans chaque sauvegarde** : rejeté, car ils
|
||||
appartiennent au joueur et à la plateforme, pas à une étape de campagne.
|
||||
- **Supprimer automatiquement les sauvegardes invalides ou excédentaires** :
|
||||
rejeté, car la récupération ou le choix doit rester sous contrôle du joueur.
|
||||
@@ -0,0 +1,128 @@
|
||||
# 0008 — Services possédés et injectés par la composition
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
Les réglages, l'accès aux sauvegardes, l'audio et une campagne chargée doivent
|
||||
survivre à plusieurs changements d'écran. Godot permet de résoudre ce besoin
|
||||
avec des autoloads, des singletons statiques ou un bus de signaux global. Ces
|
||||
solutions rendent toutefois les dépendances accessibles depuis n'importe quel
|
||||
script, masquent leur durée de vie et compliquent l'isolation des tests.
|
||||
|
||||
La verticale possède déjà une couche `composition`, seule autorisée à connaître
|
||||
les implémentations concrètes de toutes les autres couches. Elle peut donc
|
||||
maintenir les objets de longue durée sans les transformer en état global.
|
||||
|
||||
## Décision
|
||||
|
||||
### Aucun accès global de gameplay
|
||||
|
||||
Aucun autoload personnalisé, singleton statique, registre global, service
|
||||
locator ou bus de signaux global n'est introduit pour le gameplay de la
|
||||
verticale. Une longue durée de vie ne suffit pas à justifier un accès global.
|
||||
|
||||
Les singletons fournis par Godot restent des détails de plateforme. Seuls les
|
||||
adaptateurs autorisés les utilisent ; le domaine et les cas d'usage ne lisent
|
||||
pas directement `Input`, `SceneTree`, `AudioServer`, les fichiers ou l'horloge.
|
||||
|
||||
### Racine persistante
|
||||
|
||||
`vertical_slice_root.tscn` est la racine de composition persistante de la
|
||||
verticale. Elle crée les implémentations concrètes, les relie à leurs ports et
|
||||
possède un emplacement destiné à l'écran ou au monde actif. Une transition
|
||||
remplace ce contenu enfant sans remplacer la racine et sans demander aux scènes
|
||||
de rechercher des services dans l'arbre.
|
||||
|
||||
La composition est responsable de :
|
||||
|
||||
- construire les adaptateurs d'infrastructure et les cas d'usage ;
|
||||
- charger ou créer l'état de campagne ;
|
||||
- injecter les contrats requis avant d'activer une scène ;
|
||||
- connecter les sorties d'une scène aux commandes applicatives appropriées ;
|
||||
- déconnecter et libérer les dépendances de portée courte lors d'une
|
||||
transition ;
|
||||
- choisir l'écran suivant à partir d'un résultat applicatif explicite.
|
||||
|
||||
Une scène ne parcourt pas ses parents, `/root`, un groupe global ou un chemin
|
||||
absolu afin de découvrir une dépendance. Elle expose une méthode de
|
||||
configuration, des propriétés typées ou un constructeur de composition
|
||||
explicite. L'absence d'une dépendance requise échoue immédiatement en
|
||||
développement et dans les tests de chargement.
|
||||
|
||||
### Durées de vie
|
||||
|
||||
Trois portées sont distinguées :
|
||||
|
||||
1. **Application** : réglages, localisation, adaptateurs d'entrée et d'audio,
|
||||
horloge de plateforme, accès au stockage et liste des sauvegardes. Ils vivent
|
||||
tant que la racine existe.
|
||||
2. **Campagne** : `CampaignState`, progression de mission et cas d'usage liés à
|
||||
une partie. Ils sont créés lors d'une nouvelle partie ou d'un chargement et
|
||||
détruits lors de sa fermeture ou de son remplacement.
|
||||
3. **Plongée** : `ResolvedDiveRules`, `DiveSession`, acteurs, adaptateurs
|
||||
physiques et service sonar courant. Ils sont créés au départ d'une plongée
|
||||
et détruits après production de son résultat immuable.
|
||||
|
||||
Un objet de portée longue peut fournir un port à une portée plus courte. Il ne
|
||||
conserve pas en retour une référence implicite vers un acteur ou une scène déjà
|
||||
détruite. Les connexions de signaux suivent la même propriété et sont retirées
|
||||
avec leur portée.
|
||||
|
||||
Les services d'infrastructure ne deviennent pas propriétaires des règles. Par
|
||||
exemple, le dépôt de sauvegarde écrit un document demandé par un cas d'usage ;
|
||||
il ne décide pas quand une mission progresse ou combien d'argent est gagné.
|
||||
|
||||
### Navigation et communications
|
||||
|
||||
La présentation traduit une interaction en commande ou appel de cas d'usage.
|
||||
Elle consomme ensuite un résultat, un snapshot ou un événement typé. Elle ne
|
||||
modifie jamais directement l'état de campagne ou un acteur du monde.
|
||||
|
||||
Les événements locaux peuvent utiliser les signaux Godot entre objets déjà
|
||||
reliés par la composition. Un signal décrit un fait passé et ne sert pas de
|
||||
canal global anonyme. Une intention reste une commande nommée.
|
||||
|
||||
Chaque écran et composition de plongée peut être instancié dans un test avec de
|
||||
faux ports, sans charger une campagne réelle, le stockage de la machine ou tous
|
||||
les autres écrans.
|
||||
|
||||
### Évolution
|
||||
|
||||
Tout nouvel autoload, accès statique global ou exception durable à cette
|
||||
politique exige un ADR qui précise son propriétaire, sa durée de vie, son API,
|
||||
sa stratégie de réinitialisation et son isolation en test.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Les dépendances et leur durée de vie sont visibles à l'endroit où les scènes
|
||||
sont assemblées.
|
||||
- Un changement d'écran ne détruit pas les services applicatifs nécessaires à
|
||||
la session.
|
||||
- Une nouvelle campagne peut remplacer proprement la précédente sans conserver
|
||||
ses signaux, caches ou acteurs.
|
||||
- Les écrans sont testables avec des doubles légers et ne dépendent pas d'un
|
||||
ordre d'initialisation d'autoloads.
|
||||
- La composition contient davantage de code d'assemblage explicite et doit
|
||||
rester distincte des règles de gameplay.
|
||||
- Les transitions doivent libérer leurs objets de portée courte et seront
|
||||
couvertes par des tests d'intégration et de fuite de nœuds.
|
||||
- Les fonctionnalités transversales passent par des ports nommés plutôt que par
|
||||
une commodité globale.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Un autoload par service** : rejeté, car sauvegarde, campagne, audio et
|
||||
navigation deviendraient accessibles et mutables depuis toutes les couches.
|
||||
- **Un unique `GameManager` autoload** : rejeté, car il concentrerait
|
||||
assemblage, navigation et règles dans un propriétaire générique.
|
||||
- **Un bus d'événements global** : rejeté, car producteurs et consommateurs
|
||||
seraient reliés par des noms implicites et des durées de vie difficiles à
|
||||
vérifier.
|
||||
- **Remplacer toute la scène courante à chaque écran** : rejeté comme
|
||||
navigation principale, car les services persistants devraient alors être
|
||||
globaux ou reconstruits avec un état dupliqué.
|
||||
- **Rechercher les services dans les parents ou par groupe Godot** : rejeté,
|
||||
car la dépendance resterait cachée et dépendrait de la forme de l'arbre.
|
||||
@@ -0,0 +1,163 @@
|
||||
# 0009 — Progression pilotée par les connaissances et actions du joueur
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
L'entreprise qui engage le joueur sait qu'elle poursuit un trésor, mais présente
|
||||
la première mission comme la récupération du travail du précédent opérateur.
|
||||
Le monde possède donc une vérité, le commanditaire possède des intentions et le
|
||||
joueur ne dispose au départ que d'une version partielle ou mensongère.
|
||||
|
||||
Une épave peut être localisée, identifiée, examinée, ouverte et revisitée sans
|
||||
que son objectif principal ait été sécurisé. Débloquer la suite dès la
|
||||
découverte du navire rendrait la récupération de l'objet ou de l'indice
|
||||
facultative et contredirait la boucle de campagne. À l'inverse, utiliser les
|
||||
secrets du contenu pour colorer une icône ou construire un objectif visible
|
||||
révélerait indirectement une information que le joueur n'a pas encore obtenue.
|
||||
|
||||
## Décision
|
||||
|
||||
### Trois niveaux d'information
|
||||
|
||||
Le modèle sépare explicitement :
|
||||
|
||||
1. **La vérité du contenu** : identité réelle d'une épave, objets présents,
|
||||
chronologie, motivations et liens narratifs. Elle réside dans les définitions
|
||||
de contenu et n'est jamais envoyée telle quelle à la présentation.
|
||||
2. **Les termes visibles du contrat** : `ContractTerms` contient uniquement le
|
||||
commanditaire affiché, les informations communiquées au joueur, l'objectif
|
||||
officiel, le paiement et les prérequis annoncés.
|
||||
3. **Les connaissances du joueur** : `MissionProgress` contient uniquement les
|
||||
faits observés, révélations acquises, objectifs connus, épaves localisées,
|
||||
identités établies et activités découvertes.
|
||||
|
||||
Les intentions cachées de l'entreprise et les véritables étapes de progression
|
||||
sont décrites dans des `CampaignObjectiveDefinition` distinctes de
|
||||
`ContractTerms`. Une définition peut rester invisible, devenir connue après une
|
||||
révélation ou n'exister que comme règle interne reliant des faits.
|
||||
|
||||
La sauvegarde persiste les identifiants et états nécessaires à la progression,
|
||||
mais l'application expose à chaque écran une projection filtrée par les
|
||||
connaissances du joueur. Le fait qu'une donnée existe dans le contenu ou le
|
||||
format de sauvegarde ne l'autorise pas à traverser le contrat de présentation.
|
||||
|
||||
### Faits, objectifs et révélations
|
||||
|
||||
Un fait est un événement métier idempotent déjà établi, par exemple :
|
||||
|
||||
- une zone d'écho a été obtenue ;
|
||||
- une épave a été localisée ;
|
||||
- une preuve a été observée ;
|
||||
- une identité a été établie ;
|
||||
- un accès a été ouvert ;
|
||||
- un objet se trouve sur le site, dans le panier, dans la cale ou a été remis ;
|
||||
- des données récupérées ont été analysées.
|
||||
|
||||
Une révélation est une nouvelle connaissance produite par une commande validée
|
||||
et ses prérequis, pas un texte déclenché par l'interface. Elle peut rendre
|
||||
visible un objectif, une activité, une identité ou une nouvelle zone probable.
|
||||
|
||||
Un `CampaignObjectiveDefinition` exprime des prérequis typés et un effet. La
|
||||
progression les évalue après les commandes applicatives. Elle ne dépend ni de
|
||||
la scène ouverte, ni d'un libellé, ni d'une comparaison effectuée dans le HUD.
|
||||
Les mêmes faits ne produisent une révélation qu'une seule fois.
|
||||
|
||||
Une hypothèse de joueur, telle que la cible présumée dans le dossier, reste
|
||||
révisable et n'est pas un fait d'identification. Elle ne valide ni le contrat,
|
||||
ni une étape cachée.
|
||||
|
||||
### Localisation distincte de l'accomplissement
|
||||
|
||||
Localiser ou identifier une épave ne satisfait pas automatiquement l'objectif
|
||||
qui y conduit. Chaque étape requiert le dernier fait métier prévu par sa
|
||||
définition : récupération, sécurisation dans la cale, analyse, lecture, remise
|
||||
ou autre action explicitement nommée.
|
||||
|
||||
Pour la première mission de la verticale :
|
||||
|
||||
1. le contrat visible demande de retrouver le navire de prospection et son
|
||||
module de cartographie ;
|
||||
2. la localisation rend l'épave revisitable, sans révéler la piste suivante ;
|
||||
3. l'identification confirme le navire, sans terminer la mission ;
|
||||
4. les objets placés dans le panier restent provisoires ;
|
||||
5. le treuillage puis `EmptyBasket` sécurisent le module et ses données dans la
|
||||
cale ;
|
||||
6. `AnalyzeRecoveredData` révèle la zone probable du U-Boot ;
|
||||
7. la remise physique du module et le paiement restent des actions séparées.
|
||||
|
||||
La copie analysable des données demeure acquise après son transfert, même si le
|
||||
module physique est remis ensuite. Les intentions réelles de l'entreprise ne
|
||||
deviennent visibles que par une révélation narrative prévue, pas par le simple
|
||||
accomplissement technique d'un objectif caché.
|
||||
|
||||
### Projection de la carte
|
||||
|
||||
La carte globale reçoit une projection de `MissionProgress` et applique les
|
||||
états suivants :
|
||||
|
||||
- une vérité de contenu non localisée n'est pas affichée comme épave ;
|
||||
- une zone d'écho connue reste une zone approximative ;
|
||||
- une épave localisée sans identité établie est nommée
|
||||
`Épave non identifiée` ;
|
||||
- une épave identifiée utilise le nom du navire ;
|
||||
- l'icône est colorée lorsqu'au moins une activité connue et réalisable reste à
|
||||
accomplir ;
|
||||
- l'icône devient monochrome lorsque toutes les activités connues sont
|
||||
terminées et qu'aucun objectif connu n'y demande une action.
|
||||
|
||||
Une activité cachée ne colore pas l'icône : cela divulguerait son existence.
|
||||
Lorsqu'une révélation la rend connue, la projection peut redevenir colorée.
|
||||
Cette couleur est une information de présentation dérivée d'un état métier
|
||||
filtré ; elle n'est pas sauvegardée comme vérité indépendante.
|
||||
|
||||
### Responsabilités
|
||||
|
||||
Le domaine possède faits, prérequis, états d'objets et transitions de
|
||||
progression. L'application exécute les commandes, publie les révélations et
|
||||
construit les projections autorisées. Le monde produit uniquement des
|
||||
observations et interactions. La présentation affiche les projections et émet
|
||||
des commandes ; elle ne lit jamais directement les définitions cachées.
|
||||
|
||||
Les tests de contenu vérifient au minimum :
|
||||
|
||||
- que le contrat visible ne référence pas une révélation prématurée ;
|
||||
- que chaque objectif de campagne possède une suite de prérequis atteignable ;
|
||||
- que la campagne reste terminable sans le pack d'archives facultatif ;
|
||||
- que localiser ou identifier seul la première épave ne révèle pas le U-Boot ;
|
||||
- que l'analyse des données sécurisées le révèle une seule fois ;
|
||||
- que chaque leurre possède des faits cohérents et une contradiction
|
||||
découvrable ;
|
||||
- qu'aucune projection ne contient un fait ou une activité encore caché.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- L'entreprise peut mentir sans dupliquer une seconde mission ou risquer que
|
||||
l'interface expose son véritable objectif.
|
||||
- Une épave découverte reste facile à retrouver, mais sa découverte ne court-
|
||||
circuite pas la récupération et l'analyse.
|
||||
- La carte peut revenir sur une épave lorsqu'une nouvelle activité y est
|
||||
révélée, sans modifier son historique d'exploration.
|
||||
- Ajouter une révélation exige des prérequis typés et un test de contenu, ce qui
|
||||
augmente le travail d'auteur mais réduit les blocages narratifs.
|
||||
- Les écrans reçoivent des projections dédiées plutôt que les ressources de
|
||||
contenu complètes.
|
||||
- Les états de couleur et les libellés de carte restent dérivés et ne créent
|
||||
pas une source de vérité concurrente.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Mettre objectifs visibles et cachés dans `ContractTerms`** : rejeté, car un
|
||||
écran ou un export de contrat pourrait révéler les intentions de l'entreprise.
|
||||
- **Utiliser des booléens globaux sans propriétaire** : rejeté, car leur origine,
|
||||
leur ordre et leurs prérequis seraient implicites.
|
||||
- **Débloquer la suite à l'identification de l'épave** : rejeté, car l'objet ou
|
||||
l'indice demandé deviendrait facultatif.
|
||||
- **Laisser l'UI déduire l'objectif suivant** : rejeté, car la présentation
|
||||
calculerait une règle de campagne.
|
||||
- **Colorer une épave tant qu'elle contient un secret quelconque** : rejeté,
|
||||
car la carte divulguerait les activités inconnues du joueur.
|
||||
- **Valider immédiatement la cible présumée** : rejeté, car l'hypothèse doit
|
||||
rester révisable et la déduction ne doit pas devenir un quiz d'interface.
|
||||
@@ -0,0 +1,99 @@
|
||||
# 0010 — Bathymétrie à surface unique pour la V1
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
Le sonar retenu représente le fond par une grille bathymétrique continue. Pour
|
||||
une ligne et une colonne données, cette structure ne peut stocker qu'une seule
|
||||
élévation autoritaire. Elle convient aux pentes, crêtes, chenaux, dépressions et
|
||||
reliefs ouverts, mais pas à un tunnel, une arche ou une grotte possédant
|
||||
plusieurs surfaces superposées au même emplacement horizontal.
|
||||
|
||||
Une représentation hybride pourrait combiner plusieurs couches, fragments de
|
||||
maillage, points volumétriques ou voxels locaux. Aucun site de la verticale
|
||||
n'exige encore cette complexité : les véritables grottes à plusieurs niveaux et
|
||||
les surplombs complexes sont hors périmètre de la V1.
|
||||
|
||||
## Décision
|
||||
|
||||
Le terrain navigable et les informations critiques du sonar de la V1 utilisent
|
||||
une bathymétrie à surface unique. Chaque cellule valide du scan possède au plus
|
||||
une hauteur de terrain reconstruite.
|
||||
|
||||
Les sites de la verticale sont conçus de sorte que :
|
||||
|
||||
- les routes nécessaires puissent être comprises depuis une carte de hauteur ;
|
||||
- aucun objectif n'exige de passer sous un surplomb naturel ou dans un tunnel ;
|
||||
- aucune preuve indispensable ne soit cachée par une seconde surface au même
|
||||
emplacement horizontal ;
|
||||
- une absence de mesure reste inconnue et ne soit pas comblée artificiellement ;
|
||||
- les limites de la zone jouable ne soient pas présentées comme un relief à
|
||||
interpréter.
|
||||
|
||||
Les épaves, le sous-marin, le navire et les accessoires restent de véritables
|
||||
modèles 3D pour le rendu et les collisions. Une épave peut présenter des
|
||||
ouvertures, des volumes, des éléments dressés et des zones interactives. Le
|
||||
sonar de la V1 n'a toutefois pas à reconstruire précisément son intérieur, son
|
||||
dessous ou plusieurs ponts superposés.
|
||||
|
||||
Les surfaces anormales et les épaves peuvent être signalées par des
|
||||
`SonarContact` distincts et par leur contribution visible à la surface
|
||||
extérieure. Une interaction, une observation visuelle ou un indice du dossier
|
||||
confirme ensuite leur nature. Le renderer sonar ne fabrique pas un volume
|
||||
intérieur pour compenser les limites de la bathymétrie.
|
||||
|
||||
Un surplomb purement décoratif reste autorisé s'il n'est ni une route, ni un
|
||||
abri nécessaire, ni le support d'une information de mission et si son absence
|
||||
ou sa simplification sur le sonar ne trompe pas le joueur. Cette exception est
|
||||
vérifiée lors de la revue du site et des tests humains.
|
||||
|
||||
Aucune interface générique pour plusieurs couches, aucun voxel local et aucun
|
||||
champ de distance ne sont ajoutés préventivement. Le contrat du scan conserve
|
||||
les valeurs réelles et les contacts nécessaires, sans prétendre résoudre un
|
||||
besoin futur non validé.
|
||||
|
||||
### Déclencheur d'une évolution
|
||||
|
||||
Un prototype de représentation hybride devient nécessaire seulement lorsqu'un
|
||||
site retenu exige au moins l'un des comportements suivants :
|
||||
|
||||
- naviguer au-dessus et au-dessous de surfaces superposées ;
|
||||
- lire au sonar l'entrée et la continuité d'une grotte ou d'un tunnel ;
|
||||
- distinguer plusieurs ponts, plafonds ou niveaux comme information de jeu ;
|
||||
- représenter une cible indispensable qu'une carte de hauteur rend ambiguë ou
|
||||
invisible.
|
||||
|
||||
Ce prototype comparera au minimum couches bathymétriques locales, fragments de
|
||||
maillage et représentation volumétrique bornée. Son adoption, ses données et
|
||||
son coût de persistance nécessiteront un nouvel ADR. Elle ne modifiera pas
|
||||
silencieusement le contrat de la V1.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- La reconstruction sonar reste continue, compacte et compatible avec le
|
||||
langage visuel validé par le POC B.
|
||||
- Le level design de la verticale doit éviter les configurations que le sonar
|
||||
ne peut pas communiquer honnêtement.
|
||||
- Les épaves peuvent conserver une géométrie visuelle riche sans imposer un
|
||||
sonar volumétrique.
|
||||
- Certaines formes 3D seront simplifiées ou absentes de la carte sonar ; elles
|
||||
ne peuvent pas porter seules une information critique.
|
||||
- Les budgets de la tranche sonar ne comprennent ni voxelisation, ni
|
||||
reconstruction multi-couche, ni navigation dans une grotte.
|
||||
- Une future évolution dispose de déclencheurs concrets et devra prouver sa
|
||||
lisibilité avant d'élargir le format de scan.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Construire immédiatement un sonar hybride** : rejeté, car aucun objectif de
|
||||
la verticale ne justifie encore son coût de données, de rendu et de test.
|
||||
- **Utiliser des voxels pour tous les sites** : rejeté, car les essais du POC B
|
||||
ont montré une lecture plus confuse que la surface bathymétrique continue.
|
||||
- **Aplatir silencieusement une grotte complexe dans la carte** : rejeté, car le
|
||||
sonar donnerait une information trompeuse au joueur.
|
||||
- **Interdire toute géométrie 3D complexe aux épaves** : rejeté, car la limite
|
||||
concerne la représentation sonar et le level design critique, pas les modèles
|
||||
visuels ou les collisions locales.
|
||||
@@ -0,0 +1,45 @@
|
||||
# 0011 — Godot 4.7.2 comme baseline de production
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-10-02
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
La verticale de production a démarré sous Godot 4.7.1 et la barrière qualité
|
||||
refusait toute autre version. L'environnement de développement disponible
|
||||
fournit désormais Godot 4.7.2. Conserver l'exigence exacte 4.7.1 empêche
|
||||
d'exécuter la barrière alors que cette mise à jour corrective reste dans la
|
||||
même branche 4.7 et ne change ni le renderer Forward+ ni les contrats de jeu.
|
||||
|
||||
Les POC A et B restent des références historiques figées sous Godot 4.7.1 et
|
||||
GL Compatibility. Leur baseline n'est pas réécrite rétroactivement.
|
||||
|
||||
## Décision
|
||||
|
||||
Godot 4.7.2 stable devient la version exacte exigée pour le projet de
|
||||
production et sa barrière qualité. Les documents de production et le commentaire
|
||||
du projet sont alignés sur cette version.
|
||||
|
||||
La barrière continue de comparer la version exacte au préfixe officiel attendu.
|
||||
Une version antérieure, une version corrective ultérieure ou une préversion est
|
||||
refusée jusqu'à une nouvelle décision explicite.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- La barrière s'exécute avec l'installation Godot 4.7.2 disponible.
|
||||
- Les résultats de la verticale sont reproductibles sur une version moteur
|
||||
unique.
|
||||
- La mise à jour doit être validée par le chargement de toutes les ressources,
|
||||
les tests unitaires et les tests d'intégration existants.
|
||||
- Les baselines des POC continuent de documenter la version 4.7.1 avec laquelle
|
||||
elles ont été validées.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Rester sur Godot 4.7.1** : rejeté, car cette version n'est plus
|
||||
l'installation disponible pour poursuivre la verticale.
|
||||
- **Accepter toute version 4.7.x** : rejeté, car une plage implicite rendrait
|
||||
les validations moins reproductibles.
|
||||
- **Supprimer le contrôle de version** : rejeté, car il masquerait les mises à
|
||||
jour du moteur au lieu de les valider explicitement.
|
||||
Reference in new issue
Block a user