# Abstraction des entrées et contrôles ## Règle générale Le gameplay manipule des actions logiques et non des périphériques physiques. Une action comme `Primary`, `Left` ou `Pause` peut donc provenir d'un clavier, d'une souris, d'un écran tactile ou d'un gamepad sans modifier les règles du jeu. ## Desktop Entrées possibles : - clavier : flèches, WASD, espace, touches de fonction ; - souris : clic principal/secondaire, position, mouvement relatif, molette ; - gamepad et joystick ; - trackpad lorsqu'il est présenté comme pointeur ou geste exploitable. ## Android Schémas de contrôle envisagés : - boutons virtuels ; - tap simple ; - swipe horizontal ou vertical ; - drag direct ; - joystick virtuel ; - touch relatif sans joystick visible ; - multitouch ; - accéléromètre, gyroscope et orientation lorsqu'un jeu le justifie ; - vibration/haptique comme retour, derrière un service plateforme. ## Web Le navigateur peut combiner clavier, souris et tactile. Le mapping doit produire les mêmes actions logiques que les autres plateformes. ## État normalisé Une représentation de type suivant peut être introduite lorsque nécessaire : ```rust pub struct InputState { pub move_x: f32, pub move_y: f32, pub primary: bool, pub secondary: bool, pub pause: bool, } ``` Cette structure n'est pas imposée comme API définitive à la baseline ; elle illustre le contrat recherché. ## Orientation d'écran Portrait convient particulièrement aux jeux one-button, merge, puzzle, idle, stacking et climber. Paysage convient mieux aux shooters, runners latéraux, survivor-like, tower defense et jeux utilisant deux zones de contrôle. ## Pointeur primaire normalisé Le moteur V1 expose un `PointerState` indépendant de la plateforme : - `active` indique qu'un pointeur primaire est maintenu ; - `x` et `y` sont normalisés dans `[0.0, 1.0]` ; - la plateforme borne les coordonnées avant de les transmettre au gameplay. SDL3 fournit cette abstraction sur Android avec les événements `FingerDown`, `FingerMotion`, `FingerUp` et `FingerCanceled`. La baseline `0.1.0-0-pre.8` mappe également un doigt actif vers `GameAction::Primary`. Cette association est volontairement minimale et pourra être remplacée par des zones tactiles ou boutons virtuels par jeu. Le gameplay ne dépend d'aucun type Android, Java ou SDL3. ## Impulsion Primary et état maintenu À partir de `0.1.0-0-pre.10`, `GameAction::Primary` représente une impulsion de déclenchement pour souris/tactile : - `MouseButtonDown` gauche produit une impulsion `Primary` ; - `FingerDown` produit une impulsion `Primary` ; - les mouvements mettent à jour `PointerState` sans répéter `Primary` ; - `MouseButtonUp`, `FingerUp` et `FingerCanceled` désactivent le pointeur. Cette séparation empêche un contact maintenu de produire un succès par frame. ## Directions clavier et tactile Les flèches clavier produisent `Left`, `Right`, `Up` et `Down`. Snake utilise désormais un geste directionnel et non la position absolue du tap. Pour souris et tactile : - `Down` mémorise l'origine normalisée ; - les mouvements mettent à jour le pointeur sans produire de direction ; - `Up` compare l'origine et la position finale ; - le déplacement doit dépasser un seuil normalisé minimal ; - l'axe dominant détermine `Left`, `Right`, `Up` ou `Down` ; - un simple tap ou un micro-mouvement ne produit aucune direction ; - `Canceled` annule le geste. Reflex conserve son impulsion `Primary` sur `Down` et reste donc indépendant de la reconnaissance du swipe. ## Baseline Snake portable `0.3.0` La crate `game-snake-poc` consomme uniquement le contrat générique `engine-v1-common` pour son gameplay. Elle ne dépend pas de `engine-v1-platform-api`, de SDL3, du DOM ou d'un type de périphérique concret. Le contrat d'entrée Snake retenu pour le premier POC Web est volontairement minimal : - `Left`, `Right`, `Up` et `Down` pilotent la direction ; - le rejet d'un demi-tour opposé reste une règle du gameplay Snake ; - `Primary`, `Secondary`, `Pause` et le pointeur normalisé ne sont pas requis par le gameplay Snake actuel ; - le host traduit clavier, swipe ou boutons virtuels vers les mêmes actions directionnelles ; - le rendu reste exposé par `EngineGame::scene` sous forme d'`EngineScene`, sans dépendance au Canvas ou à SDL3. L'adapter WASM de `0-pre.3` adapte ce contrat existant plutôt que créer un second modèle d'entrée ou de rendu propre au Web. Il mémorise au plus une direction logique en attente ; `tick()` la consomme pour le prochain update puis remet l'entrée en attente à zéro. Un événement clavier ou tactile ne fait donc pas avancer la simulation à lui seul. Le host Web reste responsable de transformer ses événements physiques ou widgets en appels `left`, `right`, `up` ou `down`, puis de piloter la cadence des `tick()`. Les besoins de provenance, monétisation ou autres services plateforme appartiennent au host/launcher et ne justifient pas une dépendance plateforme inutilisée dans la crate de gameplay. ## Requête de sortie La plateforme ne décide plus directement de terminer un jeu. Elle traduit l'événement physique en `QuitRequest` : - fermeture de fenêtre → `QuitSource::WindowClose` ; - `Escape` Desktop → `QuitSource::Escape` ; - Back Android → `QuitSource::PlatformBack`. `EngineGame::quit_requested` retourne un `QuitDecision`. Le comportement par défaut est `QuitDecision::Exit`. Un jeu peut retourner `QuitDecision::Continue` après avoir modifié son état afin de mettre la partie en pause, demander confirmation, revenir à un écran précédent, préparer un Hall of Fame, sauvegarder ou commencer une action avant une sortie ultérieure. Sur Android, `SDL_ANDROID_TRAP_BACK_BUTTON=1` reste activé. Le runtime reconnaît le Back via `Keycode::AcBack` ou `Scancode::AcBack`. Le contrôle `X` SDL spécifique Android de `0-pre.11.fix.4` est supprimé : le contrôle système Back est la frontière plateforme de référence. Une future UI de confirmation ou navigation appartient au jeu ou à une couche UI moteur.