Jeu Pygame pour piloter 1 ou 2 trains LEGO DUPLO avec clavier PC ou contrôleurs arcade/joysticks.
Jeu Pygame pour piloter un ou deux trains LEGO DUPLO avec clavier PC ou contrôleurs arcade/joysticks.
## Vue d'ensemble
`duploGame` est une application de type arcade/borne conçue pour simuler le contrôle d'un train DUPLO en temps réel. Elle prend en charge :
- le choix d'un mode 1 ou 2 joueurs,
- la connexion BLE à un ou plusieurs trains DUPLO,
- la configuration des mappings clavier et joystick,
- la gestion des déplacements, lumières, sons et arrêt d'urgence,
- le rendu d'une interface orientée borne arcade avec tablature visuelle.
Le programme s'appuie sur `pygame` pour l'interface et sur `duplo_controller` pour la communication avec les hubs DUPLO.
## Fonctionnalités
- splash screen au démarrage
- menu de connexion de 1 ou 2 trains
- écran partagé en 2 zones de contrôle indépendantes
- support clavier (2 joueurs) + joysticks (1 joystick par joueur)
- intégration de `duploController` (asynchrone) pour piloter les trains
- splash screen au démarrage avec sélection 1 train / 2 trains,
- menu de connexion BLE pour 1 ou 2 joueurs,
- scan automatique des trains DUPLO visibles en Bluetooth,
- support clavier et joystick arcade,
- remapping temps réel via écrans de configuration (A REVOIR, mieux vaut passer directement par les fichiers JSON joystick_mappings.json et keyboard_mappings.json),
- sauvegarde des mappings dans des fichiers JSON,
- logique de vitesse, lumière, son, couleur et arrêt immédiat,
- mode simulation si `duploController` n'est pas installé.
## Architecture du projet
Le code est organisé autour de quelques composants clés :
- `InputManager` : normalise les actionneurs clavier/joystick en événements simples (`up`, `down`, `start_pressed`, etc.).
- `TrainProxy` : encapsule la communication asynchrone avec un train unique.
- `DuploGame` : orchestre les écrans, la logique d'état et le rendu visuel.
- `AsyncLoopThread` : exécute la boucle asyncio dans un thread dédié pour éviter de bloquer la boucle Pygame.
Cette séparation permet d'isoler le traitement du signal physique des commandes de transport BLE et rend le code plus facile à maintenir.
- `START` joueur 1 : lancer le mode contrôle (si trains requis connectés)
- `SELECT` joueur 1 (ou touche `C`) : ouvrir la configuration joystick
- `ACTION 2` joueur 1 (ou touche `K`) : ouvrir la configuration clavier
- `1` / `2` : choisir 1 ou 2 trains,
- `UP` / `DOWN` : sélectionner le mode,
- `START` ou `ACTION 1` : valider et passer au menu,
- bouton engrenage : ouvrir l'écran de configuration,
- `ESC` : quitter.
### Menu de connexion
- `UP` / `DOWN` : choisir 1 ou 2 joueurs,
- `LEFT` / `RIGHT` : sélectionner le train dans la liste scanée,
- `ACTION 1` sur chaque joueur : connecter / déconnecter le train sélectionné,
- `START` joueur 1 : lancer le mode contrôle si les trains requis sont connectés,
- `SELECT` joueur 1 ou touche `C` : ouvrir la configuration joystick,
- `ACTION 2` joueur 1 ou touche `K` : ouvrir la configuration clavier.
### Configuration joystick
- `LEFT/RIGHT` : sélectionner joueur 1 ou 2
- `UP/DOWN` : sélectionner la fonction à mapper (`UP`, `DOWN`, `LEFT`, `RIGHT`, `A1..A6`, `SELECT`, `START`)
- `ACTION 1` : entrer en mode capture, puis appuyer sur le bouton physique à associer
- `SELECT` : reset mapping par défaut du joueur sélectionné
- `START` : retour menu
- `LEFT/RIGHT` : sélectionner le joueur 1 ou 2,
- `UP/DOWN` : choisir la fonction à mapper (`UP`, `DOWN`, `LEFT`, `RIGHT`, `A1..A6`, `SELECT`, `START`),
- `ACTION 1` : entrer en mode capture, puis appuyer sur le bouton physique à associer,
- `SELECT` : réinitialiser le mapping du joueur courant,
- `START` : revenir au menu précédent.
Les mappings sont sauvegardés automatiquement dans `joystick_mappings.json` à la racine du projet,
et rechargés au prochain lancement du jeu.
Les mappings sont sauvegardés automatiquement dans `joystick_mappings.json` et rechargés au prochain lancement.
Important borne arcade: si votre encodeur expose le stick en boutons (et non en axes/hat),
mappez explicitement `UP`, `DOWN`, `LEFT`, `RIGHT` dans cet écran.
> Important pour les bornes arcade : si votre encodeur expose le stick en boutons plutôt qu'en axes/hat, il faut mapper explicitement `UP`, `DOWN`, `LEFT` et `RIGHT` dans l'écran de configuration.
### Configuration clavier
- `LEFT/RIGHT` : sélectionner joueur 1 ou 2
- `UP/DOWN` : sélectionner la fonction à mapper (`UP`, `DOWN`, `LEFT`, `RIGHT`, `A1..A6`, `SELECT`, `START`)
- `ACTION 1` : entrer en mode capture, puis appuyer sur la touche clavier à associer
- `SELECT` : reset mapping clavier par défaut du joueur sélectionné
- `START` : retour menu
- `LEFT/RIGHT` : sélectionner le joueur 1 ou 2,
- `UP/DOWN` : choisir la fonction à mapper (`UP`, `DOWN`, `LEFT`, `RIGHT`, `A1..A6`, `SELECT`, `START`),
- `ACTION 1` : entrer en mode capture, puis appuyer sur la touche clavier à associer,
- `SELECT` : réinitialiser le mapping du joueur courant,
- `START` : revenir au menu précédent.
Les mappings clavier sont sauvegardés automatiquement dans `keyboard_mappings.json` à la racine du projet,
et rechargés au prochain lancement du jeu.
Les mappings clavier sont sauvegardés dans `keyboard_mappings.json`.
### En jeu
- `UP` / `DOWN` : accélérer / freiner
- `LEFT` / `RIGHT` : changer la couleur de la lumière
- `ACTION 1..5` : sons du train
- `ACTION 6` ou `SELECT` : arrêt immédiat
- `START` : retour menu
- `ESC` : quitter
- `UP` / `DOWN` : accélérer / freiner,
- `LEFT` / `RIGHT` : changer la couleur de la lumière,
- `ACTION 1..5` : jouer les sons du train,
- `ACTION 6` ou `SELECT` : arrêt immédiat,
- `START` : ouvrir le menu de connexion si le train n'est pas connecté,
- `ESC` : quitter.
### Mappings clavier
### Mappings clavier par défaut
- Joueur 1:
- Joueur 1:
- Directions: `W/Z`, `S`, `A/Q`, `D`
- Actions 1..6: `1 2 3 4 5 6`
- Start: `Entrée`
- Select: `Backspace`
- Joueur 2:
- Joueur 2:
- Directions: `↑ ↓ ← →`
- Actions 1..6: `U I O J K L`
- Start: `Shift droit`
- Select: `Ctrl droit`
### Mappings joystick arcade (par défaut)
### Mappings joystick arcade par défaut
- Directions: D-Pad (hat) ou axes gauche X/Y
- Actions 1..6: boutons `0..5`
- Select: bouton `6`
- Start: bouton `7`
- Directions: D-Pad (hat) ou axes gauche X/Y,
- Actions 1..6: boutons `0..5`,
- Select: bouton `6`,
- Start: bouton `7`.
Ces mappings sont modifiables à chaud via l'écran de configuration joystick.
> Si `duploController` n'est pas installé, le jeu démarre en mode simulation (sans contrôle BLE réel).
## Notes de fonctionnement
- Si `duploController` n'est pas installé, l'application démarre en mode simulation et continue à fonctionner sans contrôle BLE réel.
- Le scan BLE est fait en arrière-plan dans un thread dédié pour éviter de bloquer le rendu.
- Les controllers identiques peuvent partager des identifiants SDL similaires ; le code évite ces collisions en associant les événements du joystick par index de périphérique au lieu de se fier uniquement à l'instance ID.
- Les capturations de touches ou boutons pendant la configuration sont désactivées temporairement pour éviter les boucles de détection entre le mapping en cours et les états actifs du joueur.
> Pour le développement local, le plus simple est de lancer le jeu avec le fichier `main.py` et de tester la configuration des entrées depuis le menu d'options.