New remappable action `toggle_fullscreen` (Alt+F) handled in main.gd::_input(), so it works in the menu, during a match with the pointer captured and in the boss sandbox; the event is marked handled so the key does not reach the rest of the game. toggle_fullscreen() switches between WINDOW_MODE_FULLSCREEN and WINDOW_MODE_WINDOWED; the state lives in main.fullscreen (initialised from the real window mode) instead of querying the driver on every press, so the toggle is deterministic and testable. On Web it is a no-op because fullscreen belongs to the page. Desktop HUD hint updated. New tools/test_fullscreen_shortcut.gd: 8 checks (action and key mapping, alternation, bare F inert, works mid-match without freeing the cursor). Verified on a real display: window_get_mode 0 -> 3 -> 0.
7.2 KiB
Modalità arcade/kiosk (macchina condivisa) e build Linux
1. Regola di flusso
Il gioco è installato su un computer condiviso. Il profilo precedente non viene mai dato per scontato:
- il campo del nome del menu è sempre presente e vuoto a ogni avvio e a ogni riavvio;
- alla morte (game over) il profilo viene sbloccato e il nome liberato, così al
ritorno al menu —
Ro pulsanteRICOMINCIA— viene richiesto il nome della nuova partita; - senza nome scritto la partita non parte (
GIOCAnon emettestarted), perché un punteggio senza nome sarebbe anonimo in classifica.
Il name lock delle versioni precedenti (zombie_fps_locked = 1 → menu con
giocatore: Mat e nessun campo) è ignorato: Profile.is_name_locked() restituisce
false con ALWAYS_ASK_NAME. I profili vecchi e i valori di localStorage arrivano
ancora letti, ma solo come chiave del miglior punteggio.
Identità (backend invariato, API pubblica così com'è): player_id nasce dal nome
inserito, player_id_for_name() = FNV-1a 32 bit con due semi → 16 caratteri
esadecimali, accettato dal server (8–64 [A-Za-z0-9_-]). Stesso nome = stessa persona
anche dopo un riavvio; nome diverso = identità diversa. Il record è tenuto per nome
(bests nel file .cfg).
Permalink del flusso: start_screen.gd::_start() → main.gd::start_game() (id e best
del nome, leaderboard.player_id, player.begin_play()) → morte → main.gd::_on_player_died()
(record_best con il nome della partita appena conclusa, unlock_name, salvataggio,
reset_for_new_player()) → reload → menu con campo vuoto.
1b. Cursore del mouse
Bug risolto: player.gd::_ready() catturava il pointer (MOUSE_MODE_CAPTURED) alla
costruzione del giocatore, cioè prima del menu, quindi il cursore era già bloccato
sulla schermata iniziale e i pulsanti non erano cliccabili.
player.gd::_ready()imposta sempreMOUSE_MODE_VISIBLE.- La cattura avviene solo in
player.gd::begin_play(), chiamata damain.gd::start_game()quando si preme GIOCA. - Nuovo flag
player.playing:Esc(pausa) e il click sul Web catturano il cursore solo durante la partita, mai nel menu. - In modalità touch il cursore non viene catturato (serve ai controlli on-screen).
- Alla morte
_die()lo riporta visibile, quindi la schermata di morte è cliccabile.
File toccati
| File | Modifica |
|---|---|
scripts/player_profile.gd |
ALWAYS_ASK_NAME, player_id_for_name(), fnv1a32(), best_for_name(), record_best(), unlock_name(); nome non presupposto, record per nome |
scripts/start_screen.gd |
campo del nome sempre mostrato e vuoto, reset_for_new_player(), GIOCA bloccato a campo vuoto |
scripts/main.gd |
start_game() deriva id e record dal nome e chiama player.begin_play(); _on_player_died() sblocca il profilo e invia il nome della partita conclusa |
scripts/player.gd |
cursore visibile al menu, begin_play() con la cattura, flag playing |
scripts/game_hud.gd |
promemoria dei comandi desktop aggiornato con Alt+F |
tools/test_player_profile.gd |
30 controlli (campo libero, id derivato, record per nome, game over) |
tools/test_start_screen.gd |
15 controlli (campo sempre richiesto, partenza bloccata a campo vuoto, campo liberato dopo il game over, cursore libero al menu e catturato solo in partita) |
1c. Scorciatoia Alt+F (finestra / schermo intero)
- Azione in
project.godot:toggle_fullscreen=Alt+F(rimappabile dal pannello Input Map come le altre). - Gestita in
main.gd::_input(), quindi vale sempre: menu, partita (anche con il cursore catturato) e sandbox del boss. L'evento viene marcato come gestito, così il tasto non arriva al resto del gioco. main.gd::toggle_fullscreen()alternaWINDOW_MODE_FULLSCREENeWINDOW_MODE_WINDOWED; lo stato vive inmain.fullscreen, inizializzato dalla modalità reale della finestra. Nel browser non fa nulla (il fullscreen è della pagina).- Verificato su display reale:
window_get_mode0 (finestra) → 3 (schermo intero) → 0. tools/test_fullscreen_shortcut.gd: 8 controlli (azione e tasto mappati, alternanza, F da solo inerte, funzionamento in partita senza liberare il cursore).
2. Verifiche eseguite
G="$HOME/.local/opt/godot-4.7.1/Godot_v4.7.1-stable_linux.x86_64"
"$G" --headless --path . --script res://tools/test_player_profile.gd # 30/30 PASS
"$G" --path . --rendering-method gl_compatibility --script res://tools/test_start_screen.gd # 15/15 PASS
# suite precedenti, riuscite dopo la modifica:
"$G" --headless --path . --script res://tools/test_boss.gd # 50/50
"$G" --headless --path . --script res://tools/test_rebalance_branding.gd # 14/14
"$G" --headless --path . --script res://tools/test_spawn_windows.gd
"$G" --headless --path . --script res://tools/test_wave_growth.gd
"$G" --headless --path . --script res://tools/test_gameplay_improvements.gd
"$G" --headless --path . --script res://tools/test_fullscreen_shortcut.gd # 8/8 PASS
python3 tools/test_scores_api.py # 42/42
Nessuna modifica al backend: nessun cambiamento a nginx, Docker, API o database.
La release Web pubblicata (https://enne2.net/pub/zombie-fps/) resta quella precedente
finché non viene riesportata e rimpiantata con questa regola.
3. Build Linux portabile
export_presets.cfg → preset.1 (name Linux, platform Linux):
export_filter="all_resources"
exclude_filter="addons/*,tools/*,docs/*,build/*,assets/**/*.mdl,assets/half_life_manifest.json"
export_path="build/linux/work_death_balance.x86_64"
binary_format/embed_pck=true
binary_format/architecture="x86_64"
- PCK incorporato: sul kiosk serve un solo file (
work_death_balance.x86_64, 80.517.080 byte = template 73.470.264 + PCK 7.046.808), verificato eseguendolo da una cartella vuota (--headless -- --smoke→SMOKE: wave=0 alive=0 player_hp=100.0). - Dipendenze dinamica minime:
libc,libm,librt,libpthread,libdl+ld-linux-x86-64.so.2. Nessunalibstdc++(già linkata staticamente nel template). - Baseline glibc del template ufficiale 4.7.1: simboli richiesti fino a
GLIBC_2.28(readelf -V) → il binario gira su glibc ≥ 2.28 (distro dal 2018 in poi). È il miglior risultato ottenibile senza ricompilare l'engine. - musl statico scartato: un binario completamente statico non carica le librerie grafiche, perché i driver OpenGL/Vulkan linkano glibc (funziona solo headless). Non è adatto a un gioco con finestra.
- Runtime richiesto sul kiosk (non linkato, caricato a runtime): driver OpenGL
(Compatibility) o Vulkan (Forward+, renderer nativo attuale), X11 o Wayland,
ALSA o PulseAudio. Sono
dlopen, quindi non rompono la portabilità del binario. - Attenzione:
#dentroexport_presets.cfgnon è un commento per il parser → una riga commentata dopobinary_format/embed_pck=trueha fatto esportare il PCK separato.
Avvio sul kiosk
La build nativa non ha un'origine di pagina, quindi la classifica va indicata esplicitamente (è la stessa API pubblica già in uso):
./work_death_balance.x86_64 --api=https://enne2.net/api/zombie-fps/
Senza --api= la classifica è disattiva di proposito (una build di prova non deve
poter scrivere alla classifica pubblica).