- 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).
3.7 KiB
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]: eventiInputEventJoypadButton/InputEventJoypadMotionsulle azioni esistenti, quattro nuove azionilook_left/right/up/down(deadzone 0.2) e la ridefinizione diui_accept/ui_cancel.scripts/player.gd:gamepad_mode: si accende da solo al primo pulsante/stick usato (_is_gamepad_activity);_can_aim()sostituisce il gatetouch_mode or mouse_mode == CAPTUREDdi 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, curvam^1.8) e li passa adapply_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 viaInput.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
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.