Refactor Godot architecture into AppShell, modular menus and game domains

This commit is contained in:
enne2
2026-09-06 17:07:05 +02:00
parent a73fb4b55f
commit f4a9da6bc3
209 changed files with 2726 additions and 2072 deletions
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://cja6yryyc2swh"
path="res://.godot/imported/NotoSerifDisplay-CondensedExtraBold.ttf-e11f32cef921919fe1a1f689f5bd0dee.fontdata"
[deps]
source_file="res://shared/assets/fonts/NotoSerifDisplay-CondensedExtraBold.ttf"
dest_files=["res://.godot/imported/NotoSerifDisplay-CondensedExtraBold.ttf-e11f32cef921919fe1a1f689f5bd0dee.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=3
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b8b7jc0pcxwjk"
path="res://.godot/imported/wood_board_rounded.png-35308896ac2addc0f5df2dae13ed6a0c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shared/assets/textures/wood_board_rounded.png"
dest_files=["res://.godot/imported/wood_board_rounded.png-35308896ac2addc0f5df2dae13ed6a0c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+58
View File
@@ -0,0 +1,58 @@
class_name AudioFactory
extends RefCounted
## Factory condivisa per suoni procedurali morbidi e sensory-friendly.
static func create_tone(freq: float, duration: float, amp: float = 0.3) -> AudioStreamWAV:
var sample_rate := 22050
var num_samples := int(sample_rate * duration)
var data := PackedByteArray()
data.resize(num_samples)
var attack := int(sample_rate * 0.01)
for i in num_samples:
var t := float(i) / sample_rate
var env := 1.0
if i < attack:
env = float(i) / attack
env *= exp(-3.0 * t / duration)
var value := int(clampf(sin(t * freq * TAU) * env * amp * 127.0, -128.0, 127.0))
data[i] = value & 0xff
var stream := AudioStreamWAV.new()
stream.format = AudioStreamWAV.FORMAT_8_BITS
stream.mix_rate = sample_rate
stream.data = data
return stream
static func create_arpeggio(freqs: Array[float], note_duration: float = 0.12, amp: float = 0.3) -> AudioStreamWAV:
var sample_rate := 22050
var samples_per_note := int(sample_rate * note_duration)
var data := PackedByteArray()
data.resize(samples_per_note * freqs.size())
var index := 0
var attack := int(sample_rate * 0.01)
for freq in freqs:
for i in samples_per_note:
var t := float(i) / sample_rate
var env := 1.0
if i < attack:
env = float(i) / attack
env *= exp(-3.0 * t / note_duration)
var value := int(clampf(sin(t * freq * TAU) * env * amp * 127.0, -128.0, 127.0))
data[index] = value & 0xff
index += 1
var stream := AudioStreamWAV.new()
stream.format = AudioStreamWAV.FORMAT_8_BITS
stream.mix_rate = sample_rate
stream.data = data
return stream
static func play_once(parent: Node, stream: AudioStream, volume_db: float = 0.0) -> AudioStreamPlayer:
var player := AudioStreamPlayer.new()
player.stream = stream
player.volume_db = volume_db
parent.add_child(player)
player.finished.connect(player.queue_free)
player.play()
return player
+1
View File
@@ -0,0 +1 @@
uid://b8mwlvhphs2ks
Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://btu7j7kp70h1p"
path="res://.godot/imported/boot_splash.png-fdbf73098cc225d48e7dceea23cbdbf2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shared/branding/boot_splash.png"
dest_files=["res://.godot/imported/boot_splash.png-fdbf73098cc225d48e7dceea23cbdbf2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ctskih3vqn5pg"
path="res://.godot/imported/upendi_avatar.png-77772ece5e9cc1c14b5946e6ff8015ce.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shared/branding/upendi_avatar.png"
dest_files=["res://.godot/imported/upendi_avatar.png-77772ece5e9cc1c14b5946e6ff8015ce.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 798 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dwn12ta3hlsap"
path="res://.godot/imported/upendi_logo.png-97057ee5f00f659c881acb6eec561519.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shared/branding/upendi_logo.png"
dest_files=["res://.godot/imported/upendi_logo.png-97057ee5f00f659c881acb6eec561519.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bd4rmhhbbm2a2"
path="res://.godot/imported/upendi_logo_transparent.png-e2029c17c7caf7864f2ea5b8b99f6857.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shared/branding/upendi_logo_transparent.png"
dest_files=["res://.godot/imported/upendi_logo_transparent.png-e2029c17c7caf7864f2ea5b8b99f6857.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+80
View File
@@ -0,0 +1,80 @@
extends Node
## Singleton Settings: valori di calibrazione del gameplay, caricati/salvati
## in user://settings.cfg. Modificati dal menù di configurazione e applicati
## al riavvio della scena.
const PATH := "user://settings.cfg"
const VERSION := 6 # incrementa quando cambiano i default, per resettare i file vecchi
var version := VERSION
var start_time := 4.5 # tempo iniziale (s) tra un ordine e l'altro
var min_time := 0.8 # tempo minimo (velocità massima)
var score_ramp := 8000.0 # punteggio per difficoltà piena (velocità massima)
var points_per_combo := 1 # punti per ogni lancio corretto (lineare, default 1)
var target_score := 1000 # punteggio da raggiungere per la vittoria
var max_combo := 5.0 # combo massimo di default (configurabile)
var combo_decay_threshold := 0.0 # combo sopra cui inizia il decay (0 = da subito)
var combo_decay_rate := 0.15 # combo persi al secondo per unità sopra la soglia
var difficulty_decay_rate := 0.3 # decay aggiuntivo legato alla difficoltà
# Modalità di gioco (mutuamente esclusive): 0=Classica (a punteggio), 1=Zen, 2=Survival
var game_mode := 0
# Accessibilità / neurodivergenza
var gentle_errors := true # errore: combo -1 invece di azzerare
func _ready() -> void:
load_settings()
func load_settings() -> void:
var cfg := ConfigFile.new()
if cfg.load(PATH) != OK:
return # usa i default
version = cfg.get_value("meta", "version", 0)
if version < VERSION:
# file di impostazioni vecchio: applica i nuovi default e risalva
reset_defaults()
save_settings()
return
start_time = cfg.get_value("gameplay", "start_time", start_time)
min_time = cfg.get_value("gameplay", "min_time", min_time)
score_ramp = cfg.get_value("gameplay", "score_ramp", score_ramp)
points_per_combo = cfg.get_value("gameplay", "points_per_combo", points_per_combo)
target_score = cfg.get_value("gameplay", "target_score", target_score)
game_mode = cfg.get_value("gameplay", "game_mode", game_mode)
max_combo = cfg.get_value("gameplay", "max_combo", max_combo)
combo_decay_threshold = cfg.get_value("gameplay", "combo_decay_threshold", combo_decay_threshold)
combo_decay_rate = cfg.get_value("gameplay", "combo_decay_rate", combo_decay_rate)
difficulty_decay_rate = cfg.get_value("gameplay", "difficulty_decay_rate", difficulty_decay_rate)
gentle_errors = cfg.get_value("accessibility", "gentle_errors", gentle_errors)
func save_settings() -> void:
var cfg := ConfigFile.new()
cfg.set_value("meta", "version", VERSION)
cfg.set_value("gameplay", "start_time", start_time)
cfg.set_value("gameplay", "min_time", min_time)
cfg.set_value("gameplay", "score_ramp", score_ramp)
cfg.set_value("gameplay", "points_per_combo", points_per_combo)
cfg.set_value("gameplay", "target_score", target_score)
cfg.set_value("gameplay", "game_mode", game_mode)
cfg.set_value("gameplay", "max_combo", max_combo)
cfg.set_value("gameplay", "combo_decay_threshold", combo_decay_threshold)
cfg.set_value("gameplay", "combo_decay_rate", combo_decay_rate)
cfg.set_value("gameplay", "difficulty_decay_rate", difficulty_decay_rate)
cfg.set_value("accessibility", "gentle_errors", gentle_errors)
cfg.save(PATH)
func reset_defaults() -> void:
start_time = 4.5
min_time = 0.8
score_ramp = 8000.0
points_per_combo = 1
target_score = 1000
game_mode = 0
max_combo = 5.0
combo_decay_threshold = 0.0
combo_decay_rate = 0.15
difficulty_decay_rate = 0.3
gentle_errors = true
+1
View File
@@ -0,0 +1 @@
uid://tvu3ae4txaud
+17
View File
@@ -0,0 +1,17 @@
class_name BrassStuds
extends Control
## Quattro borchie decorative agli angoli del controllo.
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_IGNORE
queue_redraw()
func _draw() -> void:
var positions := [Vector2(22, 22), Vector2(size.x - 22, 22), Vector2(22, size.y - 22), Vector2(size.x - 22, size.y - 22)]
for position in positions:
draw_circle(position + Vector2(1.5, 2.5), 8.0, Color(0.12, 0.05, 0.02, 0.45))
draw_circle(position, 8.0, Color("#b17b24"))
draw_circle(position - Vector2(2, 2), 4.5, CircusTheme.BRASS_LIGHT)
draw_line(position - Vector2(3, 0), position + Vector2(3, 0), Color("#765018"), 1.5, true)
+1
View File
@@ -0,0 +1 @@
uid://biuj6k801px5u
+36
View File
@@ -0,0 +1,36 @@
class_name CircusTheme
extends RefCounted
## Palette e StyleBox comuni agli overlay circensi.
const FONT := preload("res://shared/assets/fonts/NotoSerifDisplay-CondensedExtraBold.ttf")
const WOOD_TEXTURE := preload("res://shared/assets/textures/wood_board_rounded.png")
const INK := Color("#482615")
const BRASS := Color("#d5a83f")
const BRASS_LIGHT := Color("#f6d77a")
static func flat_style(color: Color, border: Color, width: int, radius: int) -> StyleBoxFlat:
var style := StyleBoxFlat.new()
style.bg_color = color
style.border_color = border
style.set_border_width_all(width)
style.set_corner_radius_all(radius)
return style
static func wood_style() -> StyleBoxTexture:
var style := StyleBoxTexture.new()
style.texture = WOOD_TEXTURE
style.texture_margin_left = 35.0
style.texture_margin_right = 35.0
style.texture_margin_top = 35.0
style.texture_margin_bottom = 35.0
return style
static func button_style(color: Color, border: Color, width: int, radius: int = 14) -> StyleBoxFlat:
var style := flat_style(color, border, width, radius)
style.shadow_color = Color(0.14, 0.05, 0.02, 0.48)
style.shadow_size = 6
style.shadow_offset = Vector2(0, 4)
return style
+1
View File
@@ -0,0 +1 @@
uid://cir4lpc4uim1b
+22
View File
@@ -0,0 +1,22 @@
class_name CircusTrim
extends Control
## Filo di bandierine decorativo riutilizzabile.
@export var flag_count := 11
@export var span := 440.0
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_IGNORE
queue_redraw()
func _draw() -> void:
var colors := [Color("#a9403e"), Color("#d5a83f"), Color("#397b76")]
var start_x := (size.x - span) * 0.5
draw_line(Vector2(start_x - 10, 8), Vector2(start_x + span + 10, 8), Color("#63361f"), 3.0, true)
for index in flag_count:
var x := start_x + index * (span / float(flag_count - 1)) - 16.0
var points := PackedVector2Array([Vector2(x, 7), Vector2(x + 32, 7), Vector2(x + 16, 31)])
draw_colored_polygon(points, colors[index % colors.size()])
draw_polyline(PackedVector2Array([points[0], points[1], points[2], points[0]]), Color("#6b341c"), 1.5, true)
+1
View File
@@ -0,0 +1 @@
uid://cinfcyv6v0h2y