Add gamepad support: stick look, trigger fire, pad menu confirm
- project.godot: joypad events on the ten existing actions (left stick move, A jump, right trigger/RB fire, X reload, B/LB grenade, Start pause, Back fullscreen), four new look_* actions on the right stick (deadzone 0.2) and ui_accept/ui_cancel redefined with the pad buttons A/B while keeping Enter/KP Enter/Space/Esc: the 4.7.1 engine maps no pad button on those. - scripts/player.gd: gamepad_mode turns on by itself on the first pad input; _can_aim() replaces the "mouse captured" gate of shoot and grenade (the pad never captures the pointer, same trap already fixed for touch); _handle_gamepad_look() converts the right stick into equivalent relative mouse pixels (900 px/s at full deflection, m^1.8 response) and still goes through apply_look(); restart accepts A/X and the death text follows the device in use. - scripts/start_screen.gd: pad hint shown only when a controller is connected, refreshed on Input.joy_connection_changed. - tools/test_gamepad.gd: 33 checks on map structure, keyboard preservation, real event pipeline, gamepad_mode and analog look. - docs/GAMEPAD.md: mapping, code map, verification, known limit (kiosk name entry still needs a keyboard: on-screen keyboard is the next step). Verified: test_gamepad 33/33, test_fullscreen_shortcut 8/8, test_touch_controls 14/14 (--touch), test_grenade 24/24, test_boss 50/50, test_rebalance_branding 14/14, test_player_profile 30/30. test_start_screen keeps its 2 pre-existing headless failures (identical on HEAD).
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# Gamepad / controller
|
||||
|
||||
Supporto ai controller implementato il 2026-10-24. Il gameplay non è stato
|
||||
riscritto: tutte le azioni passano già dalla Input Map, quindi il lavoro è stato
|
||||
mappare i binding, aggiungere il ramo analogico della visuale e aprire i gate che
|
||||
prima pretendevano il mouse catturato.
|
||||
|
||||
## Mappatura (layout SDL/Xbox)
|
||||
|
||||
| Azione | Tastiera/mouse | Gamepad |
|
||||
| --- | --- | --- |
|
||||
| `move_forward` / `move_back` | W / S, frecce | stick sinistro Y (asse 1) |
|
||||
| `move_left` / `move_right` | A / D, frecce | stick sinistro X (asse 0) |
|
||||
| `jump` | Spazio | A (pulsante 0) |
|
||||
| `shoot` | tasto sinistro del mouse | grilletto destro (asse 5) · RB (10) |
|
||||
| `reload` | R | X (pulsante 2) |
|
||||
| `grenade` | tasto destro del mouse | B (1) · LB (9) |
|
||||
| `pause` | Esc | Start (6) |
|
||||
| `toggle_fullscreen` | Alt+F | Back/Select (4) |
|
||||
| `look_*` (nuove) | movimento del mouse | stick destro (assi 2 e 3) |
|
||||
|
||||
Tutti i binding joypad hanno `device = -1`, quindi funzionano con qualunque pad
|
||||
collegato, non solo con il primo.
|
||||
|
||||
## Dove sta il codice
|
||||
|
||||
- `project.godot` → `[input]`: eventi `InputEventJoypadButton` / `InputEventJoypadMotion`
|
||||
sulle azioni esistenti, quattro nuove azioni `look_left/right/up/down` (deadzone 0.2)
|
||||
e la ridefinizione di `ui_accept`/`ui_cancel`.
|
||||
- `scripts/player.gd`:
|
||||
- `gamepad_mode`: si accende da solo al primo pulsante/stick usato (`_is_gamepad_activity`);
|
||||
- `_can_aim()` sostituisce il gate `touch_mode or mouse_mode == CAPTURED` di sparo e
|
||||
granata: senza, col pad non si sarebbe potuto né sparare né lanciare;
|
||||
- `_handle_gamepad_look(dt)`: converte lo stick destro in "pixel relativi
|
||||
equivalenti" (900 px/s a fondo corsa, curva `m^1.8`) e li passa ad `apply_look()`,
|
||||
che resta l'unico punto con sensibilità e limiti di inclinazione;
|
||||
- a partita finita ricomincia la partita anche con A/X, e il messaggio di morte
|
||||
cambia testo in base al dispositivo in uso.
|
||||
- `scripts/start_screen.gd`: riga di aiuto che compare **solo** se c'è un pad
|
||||
collegato (aggiornata in hotplug via `Input.joy_connection_changed`).
|
||||
|
||||
## Perché `ui_accept` va ridefinito a mano
|
||||
|
||||
Nel motore 4.7.1 `ui_accept` è mappato su Invio, Invio del tastierino e Spazio, e
|
||||
`ui_cancel` solo su Esc: **nessun pulsante di gamepad**. Con il pad si poteva
|
||||
navigare fra i controlli (le `ui_up/down/left/right` hanno già dpad e stick) ma non
|
||||
confermare. La ridefinizione in `project.godot` rimette anche i tasti di tastiera:
|
||||
senza, Invio e Spazio avrebbero smesso di funzionare. Il test lo controlla.
|
||||
|
||||
## Verifica
|
||||
|
||||
```bash
|
||||
godot --headless --path . --script res://tools/test_gamepad.gd
|
||||
```
|
||||
|
||||
33 controlli: struttura della mappa, conservazione dei tasti su `ui_accept`/`ui_cancel`,
|
||||
pipeline eventi reale (`Input.parse_input_event` con un pad su device 0), accensione di
|
||||
`gamepad_mode`, rotazione della visuale con lo stick destro e limiti di inclinazione.
|
||||
|
||||
Con un pad vero conviene rifare la stessa prova a schermo reale
|
||||
(`--rendering-method gl_compatibility`) perché il puntatore e il focus non sono
|
||||
verificabili in headless. Suite esistenti riverificate: `test_fullscreen_shortcut`,
|
||||
`test_touch_controls -- --touch`, `test_grenade`, `test_boss`, `test_rebalance_branding`,
|
||||
`test_player_profile` tutte verdi. `test_start_screen` ha 2 FAIL preesistenti
|
||||
(pulsante GIOCA in headless), identici su HEAD senza queste modifiche.
|
||||
|
||||
## Limite noto: il nome del giocatore
|
||||
|
||||
La regola arcade/kiosk chiede il nome a ogni avvio, e il campo è un `LineEdit` con
|
||||
`virtual_keyboard_enabled`: la tastiera su schermo del motore però esiste solo su
|
||||
Android/iOS/Web. Con **solo** il pad, su desktop non c'è modo di scrivere il nome.
|
||||
Fase successiva: tastiera on-screen navigabile col dpad (griglia A-Z), oppure scelta
|
||||
del nome da una lista di profili recenti.
|
||||
Reference in New Issue
Block a user