# Frontend du POC Snake Web direct ## Rôle `Web/game-snake-poc/` est le premier host navigateur direct du projet. Il reste un package frontend autonome, extérieur au workspace Cargo, et consomme les bindings générés de `game-snake-poc-wasm`. La séparation est volontaire : ```text game-snake-poc ↓ game-snake-poc-wasm ↓ wasm-bindgen Web/game-snake-poc ↓ HTML + Sass/Bootstrap 5 + TypeScript + Canvas ``` Le frontend ne réimplémente aucune règle de Snake. Il traduit uniquement les entrées navigateur, cadence les appels à `tick()` et dessine la scène portable exposée par le bridge WASM. ## Baseline frontend KSP Le shell reprend volontairement la structure frontend utilisée par les applications Desk KSP : ```text Web/game-snake-poc/ ├── frontend/ │ ├── main.html │ ├── sass/ │ │ ├── _app.scss │ │ ├── _bootswatch.scss │ │ ├── _fontawesome.scss │ │ ├── _simplebar.scss │ │ ├── _variables.scss │ │ └── main.scss │ └── ts/ │ ├── game.ts │ ├── input.ts │ └── main.ts ├── package.json ├── tsconfig.json └── vite.config.ts ``` Les dépendances npm utiles sont alignées sur cette baseline : Bootstrap 5, Font Awesome, SimpleBar, `resize-observer-polyfill`, `sass-embedded`, TypeScript, Vite et les types nécessaires. Les dépendances réellement propres à Tauri et au tracing frontend KSP ne sont pas importées dans ce host navigateur direct. SimpleBar et le polyfill restent au contraire pertinents pour le shell Web lui-même. Le thème reprend la baseline Bootstrap/Bootswatch Pulse des apps Desk KSP, avec un header, un footer et une carte de contenu adaptés au jeu. Cette réutilisation reste une convention de présentation du POC ; elle ne crée aucune dépendance entre les dépôts KSP et games.sasedev. ## Shell HTML et présentation Le document `frontend/main.html` fournit : - un header de statut inspiré du template Desk KSP ; - un Canvas carré responsive pour le rendu du jeu ; - les indicateurs de score, longueur et état de chargement ; - quatre boutons directionnels tactiles ; - une zone d'erreur de démarrage ; - un footer léger commun au shell ; - une zone centrale `app-content.app-scrollable.h-100[data-simplebar]` bornée par `app-main` entre le header et le footer fixes, suivant le même contrat de shell que les apps Desk KSP. Bootstrap 5 et Font Awesome sont installés comme dépendances npm et intégrés au build Vite/Sass. Aucun CDN n'est nécessaire au POC local. Le Sass spécifique reste limité au shell, au Canvas et au pavé directionnel. Le gameplay ne dépend ni de Bootstrap, ni de Font Awesome, ni du DOM. ## Entrées Le frontend accepte : - les flèches du clavier ; - `WASD` ; - `ZQSD` ; - les quatre boutons directionnels tactiles/pointer. Une entrée appelle uniquement `left()`, `right()`, `up()` ou `down()` sur `SnakeWasmGame`. La simulation continue d'avancer exclusivement via `tick()`. ## Rendu Canvas Le frontend lit la couleur de fond et les rectangles normalisés exposés par `game-snake-poc-wasm`. Les coordonnées sont multipliées par la taille physique courante du Canvas. La grille Snake fait `12 × 20` cellules. Le shell conserve donc un ratio CSS `3 / 5` pour le plateau : une cellule normalisée garde la même largeur et la même hauteur visuelles au lieu d'être écrasée verticalement dans un Canvas carré. Le Canvas suit ensuite cette taille CSS et le `devicePixelRatio` du navigateur. Le header et le footer restent fixes. `app-main` borne la hauteur utile à `100vh - header - footer` et reste lui-même non scrollable. Comme dans les apps Desk KSP, un enfant `h-100` contient `app-content app-scrollable h-100` portant `data-simplebar`; cette zone possède explicitement `height: 100%` et `max-height: 100%`. Si le plateau portrait et les contrôles dépassent la hauteur disponible, SimpleBar porte donc le scroll de cette zone centrale sans déplacer le header ni le footer. Cette tranche couvre le resize visuel nécessaire au shell ; la gestion complète du lifecycle navigateur reste prévue par `0-pre.5`. ## Build Depuis la racine du dépôt, construire d'abord l'adapter WASM et ses bindings : ```bash cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown wasm-bindgen ../builds/sasedev-games/target/wasm32-unknown-unknown/debug/game_snake_poc_wasm.wasm \ --target web \ --out-dir ../builds/sasedev-games/game-snake-poc-web/wasm \ --out-name game_snake_poc_wasm ``` Puis installer et construire le frontend : ```bash cd Web/game-snake-poc npm install npm run build ``` Vite place son cache et le `dist/` sous : ```text ../builds/sasedev-games/game-snake-poc-web/ ``` Le dépôt ne reçoit donc ni bindings WASM générés, ni `dist/`, ni cache Vite. ## Smoke navigateur Après génération du WASM : ```bash cd Web/game-snake-poc npm run dev ``` Ouvrir explicitement `http://127.0.0.1:1434/main.html` — le host utilise volontairement `main.html` et ne fournit pas d'`index.html` — puis vérifier : 1. le statut passe à `Prêt` sans erreur ; 2. Snake est visible dans le Canvas ; 3. les flèches clavier déplacent Snake ; 4. `WASD` et `ZQSD` produisent les mêmes directions ; 5. les quatre boutons tactiles/pointer fonctionnent ; 6. le plateau conserve son ratio portrait `3 / 5` et les cellules ne sont pas écrasées ; 7. lorsque le contenu dépasse la hauteur utile, seule la zone centrale défile via SimpleBar tandis que header et footer restent fixes ; 8. le shell KSP-derived et le Canvas restent utilisables sur une largeur mobile et Desktop ; 9. score et longueur restent visibles et évoluent avec l'état WASM. ## Lifecycle navigateur `0-pre.5` ferme le lifecycle du POC. La boucle `requestAnimationFrame` est suspendue lorsque le document devient caché ou reçoit `pagehide`. La reprise sur `visibilitychange`/`pageshow` réinitialise l'origine temporelle et l'accumulateur afin de ne pas rattraper artificiellement les ticks perdus en arrière-plan. Un `ResizeObserver` attaché à la zone de jeu redessine le Canvas et rafraîchit la classe d'appareil observée sans faire avancer la simulation. La destruction de page libère l'instance WASM. ## Assets runtime Le package Vite utilise `vite-plugin-static-copy` pour exposer les deux assets de sonde depuis les sources canoniques : ```text assets/common/data/runtime.json -> dist/common/data/runtime.json assets/game-snake-poc/data/game.json -> dist/game/data/game.json ``` Les deux targets utilisent explicitement `rename: { stripBase: true }`. Ce point est nécessaire puisque les sources sont résolues en chemins absolus : seule la basename (`runtime.json` / `game.json`) doit être placée sous le `dest` canonique, sans conserver l'arborescence du chemin source. Le serveur Vite de développement expose ainsi les mêmes routes `/common/data/runtime.json` et `/game/data/game.json` que le build de production. Le frontend charge et valide les deux JSON avant le démarrage WASM. Le statut visible `Assets` permet de confirmer le chargement pendant le smoke. Aucune copie source n'est ajoutée sous `Web/`. ## Logging frontend `frontend/ts/logging.ts` centralise les diagnostics navigateur. Les événements sont structurés par niveau, target, action et champs, puis écrits dans la console. Ce module est volontairement distinct du bridge tracing Tauri : le host Web direct ne possède pas de backend Tauri à qui relayer ses événements. Le Rust natif continue d'utiliser `tracing`/`game-logging-lib`; le frontend console ne remplace pas cette façade Rust. ## Provenance runtime `game-snake-poc-wasm` dépend de `engine-v1-platform-api` uniquement au niveau adapter et conserve une `RuntimeProvenance`. Les dimensions `Web / Wasm / Browser` sont fixes ; le host renseigne la classe `Desktop`/`Phone`/`Tablet`/`Unknown` et le profil `Unknown`/`KeyboardMouse`/`Touch`/`Mixed` à partir des capacités et entrées réellement observées. Le shell affiche ces cinq dimensions afin que le smoke puisse confirmer que la provenance évolue lorsqu'un clavier/souris ou un contrôle tactile est utilisé. Le gameplay `game-snake-poc` reste sans dépendance plateforme.