Arcade/kiosk name flow, free cursor in menu and portable Linux export
Every game over unlocks the profile and frees the name, so the menu always asks for a new player name: the field is empty at every boot, restart or game over and the game does not start without a name (no anonymous scores). The player identity is derived from the entered name (deterministic FNV-1a, 16 hex chars valid for the public API) and the profile keeps the best score per name. Backend untouched. Mouse: player._ready() captured the pointer before the menu existed, so the start screen was not clickable. The cursor now always starts visible; the capture happens only in player.begin_play(), called by start_game(). New `playing` flag gates Esc and the Web click capture to the actual match. Linux export preset: single-file x86_64 binary with the PCK embedded, no libstdc++ dependency, official 4.7.1 template (glibc >= 2.28). Notes and the export_presets.cfg `#`-is-not-a-comment trap documented in docs/KIOSK-ARCADE.md. Tests: profile 30/30, start screen 15/15 (cursor free at menu, captured only in game), boss 50/50, rebalance 14/14, touch 14 PASS, API 42/42, all other suites pass.
This commit is contained in:
+31
-17
@@ -1,7 +1,9 @@
|
||||
extends CanvasLayer
|
||||
## Schermata iniziale: nome del giocatore, pulsante di avvio e classifica globale
|
||||
## (tutte le partite). Il pulsante di avvio e' anche il gesto che sblocca l'audio
|
||||
## nel browser, quindi la partita parte solo da qui.
|
||||
## Schermata iniziale (modalita' arcade/kiosk): nome del giocatore, pulsante di avvio
|
||||
## e classifica globale. Il campo del nome viene mostrato VUOTO a ogni partita, quindi
|
||||
## a ogni avvio, riavvio o game over viene richiesto un nome nuovo: il profilo
|
||||
## precedente non viene mai dato per scontato. Il pulsante di avvio e' anche il gesto
|
||||
## che sblocca l'audio nel browser, quindi la partita parte solo da qui.
|
||||
signal started(player_name: String)
|
||||
|
||||
const Profile = preload("res://scripts/player_profile.gd")
|
||||
@@ -18,7 +20,8 @@ var rows_box: VBoxContainer
|
||||
var status_label: Label
|
||||
var me_label: Label
|
||||
var rows_shown := ROWS_DESKTOP
|
||||
## Vero quando il nome e' gia' stato scelto: niente campo di testo, solo il saluto.
|
||||
## Con la regola arcade il nome non e' mai bloccato: il campo c'e' sempre. La variabile
|
||||
## resta per i profili scritti dalle versioni precedenti (arrivano gia' "bloccati").
|
||||
var name_locked := false
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -29,9 +32,19 @@ func _ready() -> void:
|
||||
if leaderboard != null:
|
||||
leaderboard.fetch()
|
||||
|
||||
## Nome con cui si giochera': quello memorizzato se e' bloccato, altrimenti il campo.
|
||||
## Nome con cui si giochera': solo quello scritto nel campo della partita corrente.
|
||||
func _stored_name() -> String:
|
||||
return Profile.sanitize_name(str(profile.get("name", Profile.DEFAULT_NAME)))
|
||||
if name_field != null:
|
||||
return name_field.text.strip_edges()
|
||||
return ""
|
||||
|
||||
## Chiamato da main.gd quando si torna al menu dopo il game over: campo liberato,
|
||||
## cosi' il giocatore della partita successiva deve scrivere il proprio nome.
|
||||
func reset_for_new_player() -> void:
|
||||
if name_field != null:
|
||||
name_field.text = ""
|
||||
name_field.grab_focus()
|
||||
_set_status("nome per la nuova partita")
|
||||
|
||||
func _build_ui() -> void:
|
||||
var touch_mode: bool = player != null and player.touch_mode
|
||||
@@ -53,11 +66,8 @@ func _build_ui() -> void:
|
||||
column.add_child(title)
|
||||
column.add_child(_label("MatGames — classifica globale", 15, DIM, HORIZONTAL_ALIGNMENT_CENTER))
|
||||
|
||||
if name_locked:
|
||||
# Nome gia' scelto: non si richiede piu' (e nessun campo da toccare per sbaglio).
|
||||
column.add_child(_label("giocatore: %s" % _stored_name(), 22, AMBER, HORIZONTAL_ALIGNMENT_CENTER))
|
||||
else:
|
||||
column.add_child(_build_name_row())
|
||||
# Regola arcade/kiosk: il nome si chiede sempre, campo vuoto all'apertura.
|
||||
column.add_child(_build_name_row())
|
||||
|
||||
var play := Button.new()
|
||||
play.text = "GIOCA"
|
||||
@@ -98,12 +108,12 @@ func _build_ui() -> void:
|
||||
board_column.add_child(status_label)
|
||||
_show_rows([])
|
||||
|
||||
## Riga del nome, mostrata solo finche' il nome non e' stato scelto.
|
||||
## Riga del nome: sempre presente, campo vuoto (nessun nome dato per scontato).
|
||||
func _build_name_row() -> HBoxContainer:
|
||||
var name_row := HBoxContainer.new()
|
||||
name_row.add_theme_constant_override("separation", 8)
|
||||
name_field = LineEdit.new()
|
||||
name_field.text = str(profile.get("name", Profile.DEFAULT_NAME))
|
||||
name_field.text = ""
|
||||
name_field.max_length = Profile.NAME_MAX
|
||||
name_field.placeholder_text = "il tuo nome"
|
||||
name_field.virtual_keyboard_enabled = true # necessario su mobile Web
|
||||
@@ -177,7 +187,7 @@ func show_leaderboard_error(reason: String) -> void:
|
||||
## Su Web la tastiera virtuale di Godot e' sperimentale: in aggiunta al campo di testo
|
||||
## si offre il prompt nativo del browser, che ha sempre la tastiera del telefono.
|
||||
func _ask_name() -> void:
|
||||
if name_locked or name_field == null:
|
||||
if name_field == null:
|
||||
return
|
||||
var current := Profile.js_escape(name_field.text)
|
||||
if OS.has_feature("web") and ClassDB.class_exists("JavaScriptBridge"):
|
||||
@@ -192,7 +202,11 @@ func _ask_name() -> void:
|
||||
## altrove (sfondo, campo del nome, tasto Invio della tastiera del telefono) non deve
|
||||
## avviare nulla.
|
||||
func _start() -> void:
|
||||
if name_locked or name_field == null:
|
||||
started.emit(_stored_name())
|
||||
if name_field == null:
|
||||
return
|
||||
started.emit(Profile.sanitize_name(name_field.text))
|
||||
var name := name_field.text.strip_edges()
|
||||
if name == "":
|
||||
# Su macchina condivisa un punteggio senza nome sarebbe anonimo: non si parte.
|
||||
_set_status("inserisci il tuo nome per la nuova partita")
|
||||
return
|
||||
started.emit(Profile.sanitize_name(name))
|
||||
|
||||
Reference in New Issue
Block a user