![UPENDI](/branding/upendi_logo.png) # JuggleBoard Game Gioco arcade **reaction & chaining** per dispositivi mobili (orizzontale), realizzato in **Godot 4.7** (GDScript), ispirato al prodotto riabilitativo **"Juggle Board" by Craig Quat / Play Juggling**. **Prodotto per la [Cooperativa Sociale UPENDI](https://www.upendi.it/)** (Gravina in Puglia) — Pedagogia del Circo e Circo Sociale. Target: bambini, anche neurodivergenti (autismo, ADHD, iperreattività sensoriale): suoni morbidi (sine, niente onde quadre/sega), palette tenue, modalità Zen e errori gentili. --- ## Gameplay - **5 corsie orizzontali in legno** (plancia a tutta larghezza), ognuna con una **pallina colorata** glossy (corallo, blu, verde, giallo, viola) a riposo sull'alloggiamento destro. - Un **bersaglio in alto** (HUD a cartiglio) indica quale pallina toccare; la pallina rotola a sinistra e torna (con **rotazione realistica** attorno all'asse perpendicolare al moto). - Devi concatenare i lanci prima che scada il timeout. **Difficoltà crescente legata SOLO al punteggio** (`score_ramp = 8000` → velocità massima). - Punteggio per lancio = **combo × valore punto** (`points_per_combo`, default 1; combo max 5). - **Suoni generati proceduralmente** in 8-bit (sine morbide); BGM circense AI (Lyria) in OGG. ### Modalità di gioco (dialog all'avvio) | Modalità | Descrizione | |----------|-------------| | **Target (Classica)** | Raggiungi il punteggio `target_score` (default 1000) → VITTORIA | | **Target (Zen)** | Come Target ma **senza countdown né decay** combo | | **Infinita (Survival)** | **A vite**: 4 cuori; errore o timeout = −1 cuore; 0 cuori → **GAME OVER** (ignora il target) | Le modalità sono **mutuamente esclusive**; lo Zen è disponibile **solo** per la modalità Target. ### Protezione adulti (lock) Il menù **Opzioni** è protetto: va sbloccato premendo la sequenza **giallo → verde → blu → rosso** tra le 5 biglie (pallini che mostrano i colori premuti; reset dopo feedback rosso 2s se la sequenza di 4 è errata). --- ## Requisiti - **Godot 4.7.x** (testato con 4.7.1), renderer **GL Compatibility**. - Per l'APK Android: JDK 17, Android SDK (vedi sotto), template Android. ## Eseguire ```bash godot --path . # gioco godot -e . # editor godot --headless --path . --quit-after 120 # smoke test (errori) ``` ## Struttura ``` project.godot # viewport 1280×720 orizzontale, GL Compatibility, ETC2/ASTC export_presets.cfg # preset Web e Android app/ scenes/app_shell.tscn # scena iniziale configurata in project.godot scripts/app_shell.gd # coordina menu, selettore modalità e gioco attivo menus/ scenes/ # shell menu e schermate P1, P2a, P3a scripts/main_menu_controller.gd # navigazione e transizioni tra le schermate scripts/screens/ # costruzione delle schermate Home, Juggle e Palestra scripts/components/ # UI e audio condivisi dei menu assets/ # fondali, tendoni, pulsanti e shader dei menu games/ juggleboard/ scenes/ # scena di gioco, opzioni, lock adulto e fine partita scripts/game_controller.gd # regole, punteggio, combo, timer e modalità scripts/components/ # plancia, biglie e bersaglio scripts/ui/ # HUD, cuori, opzioni e overlay scripts/audio/ # BGM e feedback sonori assets/ # texture e BGM di JuggleBoard juggling_gym/ # asset provvisori della futura Palestra di giocoleria shared/ settings/settings.gd # AUTOLOAD Settings: parametri e user://settings.cfg audio/ # fabbrica dei suoni procedurali ui/ # tema, cornici e decorazioni circensi riusabili assets/ # font e texture condivise branding/ # logo UPENDI e boot splash docs/ # mockup, materiali di design e ARCHITECTURE.md build/ # directory ignorata per gli export Web e Android ``` Il flusso e le responsabilità dei componenti sono descritti in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). ## Impostazioni (`shared/settings/settings.gd` → `user://settings.cfg`) Parametri modificabili dal menù Opzioni: tempi (start/min), `score_ramp`, `points_per_combo`, `target_score`, `max_combo`, decay combo (threshold/rate), `difficulty_decay_rate`, `gentle_errors`, `game_mode` (0 Classica, 1 Zen, 2 Survival). > **CRITICO**: `shared/settings/settings.gd` ha `const VERSION`. Quando si cambiano i **default**, incrementare `VERSION`: i file `settings.cfg` salvati con versione più vecchia vengono **resettati ai nuovi default** (altrimenti i vecchi valori salvati sovrascrivono i nuovi default). --- ## Build Web ```bash godot --headless --path . --export-release "Web" build/web/index.html ``` ## Pubblicare il Web (enne2.net) ```bash cd build/web scp -r . debian@enne2.net:/home/debian/public_html/autgame/ ``` → URL: **https://enne2.net/pub/autgame/** (Nginx: `location /pub/` alias `/home/debian/public_html/`, autoindex on). Nota: troppe connessioni SSH rapide attivano fail2ban → raggruppa i comandi. ## Build APK Android Setup una tantum (macchina di sviluppo, senza sudo): ```bash # 1) JDK portatile (Temurin 17) # ~/.local/opt/jdk-17.0.20+8 (scarica da api.adoptium.net) # 2) Android SDK in ~/Android/Sdk: # cmdline-tools/latest/bin/sdkmanager (scaricare commandlinetools) # sdkmanager "platform-tools" "platforms;android-35" "platforms;android-36" \ # "build-tools;35.0.0" "build-tools;36.0.0" (con JAVA_HOME esportato) # 3) Impostazioni editor Godot (~/.config/godot/editor_settings-4.7.tres): # export/android/android_sdk_path = "~/Android/Sdk" # export/android/java_sdk_path = "~/.local/opt/jdk-17.0.20+8" # 4) Debug keystore (alias androiddebugkey, pass android): # ~/.local/share/godot/keystores/debug.keystore # (usato anche come release keystore nel preset export_presets.cfg) # 5) project.godot deve avere rendering/textures/vram_compression/import_etc2_astc=true ``` Build + firma: ```bash export JAVA_HOME=~/.local/opt/jdk-17.0.20+8 export ANDROID_HOME=~/Android/Sdk export PATH="$JAVA_HOME/bin:$ANDROID_HOME/build-tools/36.0.0:$PATH" godot --headless --path . --export-release "Android" build/android/autgame.apk # output: APK firmato v2/v3 (apksigner) in build/android/autgame.apk ``` Il preset usa l'**export classico** (`gradle_build/use_gradle_build=false`), che richiede i template Android in `~/.local/share/godot/export_templates/4.7.1.stable/` (da Godot_v4.7.1-stable_export_templates.tpz: `android_release.apk`, `android_debug.apk`, `android_source.zip`). ## Pubblicare la release su git.enne2.net (API) ```bash TOKEN=$(python3 -c "import yaml;d=yaml.safe_load(open('$HOME/.config/tea/config.yml'));print([l['token'] for l in d['logins'] if l['name']=='enne2'][0])") # nuova release (o riusa l'id esistente, es. 15 per v0.1): curl -s -X POST https://git.enne2.net/api/v1/repos/enne2/autgame/releases \ -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ -d '{"tag_name":"v0.2","name":"0.2","body":"..."}' # -> id RELEASE_ID # sostituire l'asset APK: AID=$(curl -s https://git.enne2.net/api/v1/repos/enne2/autgame/releases/$RELEASE_ID \ -H "Authorization: token $TOKEN" | python3 -c "import sys,json;print(json.load(sys.stdin)['assets'][0]['id'])") curl -s -X DELETE .../releases/$RELEASE_ID/assets/$AID -H "Authorization: token $TOKEN" curl -s -X POST .../releases/$RELEASE_ID/assets?name=autgame.apk -H "Authorization: token $TOKEN" \ -F "attachment=@build/android/autgame.apk" ``` Note: il CLI `tea repos create` ha un bug ("GetOrgByName") con owner utente → creare repo via `POST /api/v1/user/repos`. Avatar repo: `POST /api/v1/repos/{owner}/{repo}/avatar` con body JSON `{"image": ""}`. ## Cattura screenshot interna Godot Per il debugging grafico usare il Viewport Capture interno, non KDE/Spectacle come metodo primario. Il controller menu include flag di verifica: ```bash # P1 (default), P2a, P3a o dialog modalità: godot --path . -- --capture-menus godot --path . -- --capture-menus --capture-p2a godot --path . -- --capture-menus --capture-p3a godot --path . -- --capture-menus --capture-mode-dialog ``` Gli screenshot vengono salvati in `/tmp/autgame_menu_*.png` dopo `await RenderingServer.frame_post_draw`, quindi includono il Viewport completo senza bordi della finestra. ## Workflow sviluppo (pi/Codex) - La **logica** va implementata e verificata direttamente in Godot (test headless + screenshot). - Per il **polish visivo** (tema legno/ottone/circo), mandare gli **screenshot** dello stato attuale a Codex CLI con prompt chiaro: ```bash codex exec -C /home/enne2/Dev/autgame --dangerously-bypass-approvals-and-sandbox \ -i shot1.png -i shot2.png < prompt.txt ``` - **Chiudere sempre il processo godot dopo gli screenshot** (altrimenti interferisce). ## Asset generati con AI - Texture legno e sfondo circo: modello immagini Antigravity. - BGM circense: **API Gemini Lyria** (`lyria-3-pro-preview`), convertita in **OGG Vorbis** (Godot non importa .opus) con loop attivo nell'import. - Logo UPENDI (boot splash, avatar repo, README): Gemini image / immagine da upendi.it. --- © Cooperativa Sociale UPENDI — Gravina in Puglia