Mode select dialog at startup (Target/Zen/Infinite), Zen only for Target, refined circus-wood look (codex)
This commit is contained in:
@@ -67,6 +67,7 @@ var sound_defeat: AudioStreamWAV
|
||||
var sound_lose_heart: AudioStreamWAV
|
||||
var hearts: Node2D
|
||||
var victory_layer: CanvasLayer
|
||||
var mode_select: CanvasLayer
|
||||
var victory_shown := false
|
||||
var ball_sounds := {} # color_name -> AudioStreamWAV (tono pentatonico)
|
||||
var bgm: AudioStreamPlayer
|
||||
@@ -88,7 +89,12 @@ func _ready() -> void:
|
||||
victory_layer = load("res://scripts/victory_overlay.gd").new()
|
||||
victory_layer.reset_requested.connect(_reset_after_victory)
|
||||
add_child(victory_layer)
|
||||
mode_select = load("res://scripts/mode_select.gd").new()
|
||||
mode_select.mode_chosen.connect(_start_with_mode)
|
||||
add_child(mode_select)
|
||||
_new_game()
|
||||
# primo avvio: mostra il dialog di scelta modalità
|
||||
mode_select.show_menu()
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
@@ -373,6 +379,11 @@ func _new_game() -> void:
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _start_with_mode() -> void:
|
||||
# chiamato dal dialog di scelta modalità: avvia la partita con la modalità scelta
|
||||
_new_game()
|
||||
|
||||
|
||||
func _handle_click(pos: Vector2) -> void:
|
||||
var clicked: Area2D = null
|
||||
var best := HIT_RADIUS
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
extends CanvasLayer
|
||||
## Dialog di scelta modalità mostrato all'apertura del gioco:
|
||||
## - Target (a punteggio) con opzione Zen (senza tempo)
|
||||
## - Infinita (a vite / endless, ignora il punteggio)
|
||||
|
||||
signal mode_chosen # emesso quando si preme GIOCA
|
||||
|
||||
const DISPLAY_FONT := preload("res://assets/fonts/NotoSerifDisplay-CondensedExtraBold.ttf")
|
||||
const WOOD_TEXTURE := preload("res://assets/wood_board_rounded.png")
|
||||
const INK := Color("#482615")
|
||||
const BRASS := Color("#d5a83f")
|
||||
const BRASS_LIGHT := Color("#f6d77a")
|
||||
|
||||
var target_btn: Button
|
||||
var infinite_btn: Button
|
||||
var zen_cb: CheckButton
|
||||
var play_btn: Button
|
||||
var _card: Control
|
||||
var _group := ButtonGroup.new()
|
||||
|
||||
|
||||
class CircusTrim extends Control:
|
||||
func _ready() -> void:
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
queue_redraw()
|
||||
|
||||
func _draw() -> void:
|
||||
var colors := [Color("#a9403e"), Color("#d5a83f"), Color("#397b76")]
|
||||
var count := 11
|
||||
var span := 440.0
|
||||
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 i in count:
|
||||
var x := start_x + i * (span / float(count - 1)) - 16.0
|
||||
var points := PackedVector2Array([Vector2(x, 7), Vector2(x + 32, 7), Vector2(x + 16, 31)])
|
||||
draw_colored_polygon(points, colors[i % colors.size()])
|
||||
draw_polyline(PackedVector2Array([points[0], points[1], points[2], points[0]]), Color("#6b341c"), 1.5, true)
|
||||
|
||||
|
||||
class BrassStuds extends Control:
|
||||
func _ready() -> void:
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
queue_redraw()
|
||||
|
||||
func _draw() -> void:
|
||||
for p in [Vector2(22, 22), Vector2(size.x - 22, 22), Vector2(22, size.y - 22), Vector2(size.x - 22, size.y - 22)]:
|
||||
draw_circle(p + Vector2(1.5, 2.5), 8.0, Color(0.12, 0.05, 0.02, 0.45))
|
||||
draw_circle(p, 8.0, Color("#b17b24"))
|
||||
draw_circle(p - Vector2(2, 2), 4.5, BRASS_LIGHT)
|
||||
draw_line(p - Vector2(3, 0), p + Vector2(3, 0), Color("#765018"), 1.5, true)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
visible = false
|
||||
_build()
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
func _build() -> void:
|
||||
var dim := ColorRect.new()
|
||||
dim.color = Color(0.045, 0.018, 0.012, 0.77)
|
||||
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
dim.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
add_child(dim)
|
||||
|
||||
var center := CenterContainer.new()
|
||||
center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(center)
|
||||
|
||||
_card = PanelContainer.new()
|
||||
_card.custom_minimum_size = Vector2(750, 550)
|
||||
var frame := _flat_style(Color("#70411f"), Color("#edca69"), 6, 31)
|
||||
frame.shadow_color = Color(0, 0, 0, 0.58)
|
||||
frame.shadow_size = 22
|
||||
frame.shadow_offset = Vector2(0, 9)
|
||||
frame.content_margin_left = 10
|
||||
frame.content_margin_right = 10
|
||||
frame.content_margin_top = 10
|
||||
frame.content_margin_bottom = 10
|
||||
_card.add_theme_stylebox_override("panel", frame)
|
||||
center.add_child(_card)
|
||||
|
||||
var wood := PanelContainer.new()
|
||||
wood.add_theme_stylebox_override("panel", _wood_style())
|
||||
_card.add_child(wood)
|
||||
|
||||
var studs := BrassStuds.new()
|
||||
studs.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
wood.add_child(studs)
|
||||
|
||||
var margin := MarginContainer.new()
|
||||
margin.add_theme_constant_override("margin_left", 50)
|
||||
margin.add_theme_constant_override("margin_right", 50)
|
||||
margin.add_theme_constant_override("margin_top", 28)
|
||||
margin.add_theme_constant_override("margin_bottom", 32)
|
||||
wood.add_child(margin)
|
||||
|
||||
var vb := VBoxContainer.new()
|
||||
vb.add_theme_constant_override("separation", 12)
|
||||
vb.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
margin.add_child(vb)
|
||||
|
||||
var bunting := CircusTrim.new()
|
||||
bunting.custom_minimum_size = Vector2(0, 34)
|
||||
vb.add_child(bunting)
|
||||
|
||||
var title := Label.new()
|
||||
title.text = "Scegli la modalità"
|
||||
title.add_theme_font_override("font", DISPLAY_FONT)
|
||||
title.add_theme_font_size_override("font_size", 45)
|
||||
title.add_theme_color_override("font_color", Color("#6d3419"))
|
||||
title.add_theme_color_override("font_outline_color", Color("#f5d985"))
|
||||
title.add_theme_constant_override("outline_size", 3)
|
||||
title.add_theme_color_override("font_shadow_color", Color(0.25, 0.09, 0.02, 0.3))
|
||||
title.add_theme_constant_override("shadow_offset_x", 0)
|
||||
title.add_theme_constant_override("shadow_offset_y", 3)
|
||||
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
vb.add_child(title)
|
||||
|
||||
var sub := Label.new()
|
||||
sub.text = "Come vuoi giocare?"
|
||||
sub.add_theme_font_size_override("font_size", 18)
|
||||
sub.add_theme_color_override("font_color", INK)
|
||||
sub.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
vb.add_child(sub)
|
||||
|
||||
# Pulsanti modalità (comportamento radio).
|
||||
var hb := HBoxContainer.new()
|
||||
hb.add_theme_constant_override("separation", 18)
|
||||
hb.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
vb.add_child(hb)
|
||||
|
||||
target_btn = _make_mode_button("🎯 TARGET", "Raggiungi il punteggio stabilito")
|
||||
infinite_btn = _make_mode_button("♾ INFINITA", "A vite, senza limite di punteggio")
|
||||
target_btn.button_group = _group
|
||||
infinite_btn.button_group = _group
|
||||
_group.pressed.connect(_on_mode_changed)
|
||||
hb.add_child(target_btn)
|
||||
hb.add_child(infinite_btn)
|
||||
|
||||
# Checkbox Zen (solo per la modalità Target).
|
||||
var zen_center := CenterContainer.new()
|
||||
zen_center.custom_minimum_size = Vector2(0, 52)
|
||||
vb.add_child(zen_center)
|
||||
zen_cb = CheckButton.new()
|
||||
zen_cb.text = " ZEN · senza countdown né decadimento"
|
||||
zen_cb.custom_minimum_size = Vector2(420, 46)
|
||||
zen_cb.add_theme_font_size_override("font_size", 17)
|
||||
zen_cb.add_theme_color_override("font_color", INK)
|
||||
zen_cb.add_theme_color_override("font_hover_color", Color("#67391d"))
|
||||
zen_cb.add_theme_stylebox_override("normal", _flat_style(Color("#ead6a8"), Color("#a77835"), 2, 12))
|
||||
zen_cb.add_theme_stylebox_override("hover", _flat_style(Color("#f2dfb2"), BRASS, 3, 12))
|
||||
zen_cb.add_theme_stylebox_override("pressed", _flat_style(Color("#dfc58c"), Color("#966324"), 3, 12))
|
||||
zen_cb.button_pressed = false
|
||||
zen_cb.alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
zen_cb.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
zen_center.add_child(zen_cb)
|
||||
|
||||
var play_center := CenterContainer.new()
|
||||
vb.add_child(play_center)
|
||||
play_btn = Button.new()
|
||||
play_btn.text = "◆ GIOCA ◆"
|
||||
play_btn.custom_minimum_size = Vector2(380, 66)
|
||||
play_btn.add_theme_font_override("font", DISPLAY_FONT)
|
||||
play_btn.add_theme_font_size_override("font_size", 29)
|
||||
play_btn.add_theme_color_override("font_color", Color("#fff1c7"))
|
||||
play_btn.add_theme_color_override("font_hover_color", Color.WHITE)
|
||||
play_btn.add_theme_color_override("font_pressed_color", Color("#f8dc91"))
|
||||
play_btn.add_theme_stylebox_override("normal", _button_style(Color("#824720"), Color("#d9a947"), 5))
|
||||
play_btn.add_theme_stylebox_override("hover", _button_style(Color("#98562a"), BRASS_LIGHT, 5))
|
||||
play_btn.add_theme_stylebox_override("pressed", _button_style(Color("#653318"), Color("#b7832e"), 4))
|
||||
play_btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
play_btn.pressed.connect(_on_play)
|
||||
play_center.add_child(play_btn)
|
||||
|
||||
|
||||
func _button_style(color: Color, border: Color, width: int) -> StyleBoxFlat:
|
||||
var style := _flat_style(color, border, width, 14)
|
||||
style.shadow_color = Color(0.14, 0.05, 0.02, 0.5)
|
||||
style.shadow_size = 6
|
||||
style.shadow_offset = Vector2(0, 4)
|
||||
return style
|
||||
|
||||
|
||||
func _make_mode_button(title_text: String, hint_text: String) -> Button:
|
||||
var btn := Button.new()
|
||||
btn.text = title_text + "\n" + hint_text
|
||||
btn.custom_minimum_size = Vector2(305, 100)
|
||||
btn.add_theme_font_override("font", DISPLAY_FONT)
|
||||
btn.add_theme_font_size_override("font_size", 20)
|
||||
btn.add_theme_color_override("font_color", INK)
|
||||
btn.add_theme_color_override("font_hover_color", Color("#572b16"))
|
||||
btn.add_theme_color_override("font_pressed_color", Color("#fff5d6"))
|
||||
btn.add_theme_color_override("font_focus_color", Color("#fff5d6"))
|
||||
btn.add_theme_constant_override("outline_size", 1)
|
||||
btn.toggle_mode = true
|
||||
btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
var normal := _flat_style(Color("#ead7ac"), Color("#9b6b30"), 3, 14)
|
||||
normal.shadow_color = Color(0.18, 0.07, 0.02, 0.35)
|
||||
normal.shadow_size = 5
|
||||
normal.shadow_offset = Vector2(0, 3)
|
||||
var hover := _flat_style(Color("#f3dfad"), BRASS_LIGHT, 4, 14)
|
||||
hover.shadow_color = Color(0.72, 0.43, 0.08, 0.3)
|
||||
hover.shadow_size = 8
|
||||
var selected := _flat_style(Color("#a85b2c"), Color("#f4cf67"), 5, 14)
|
||||
selected.shadow_color = Color(0.95, 0.65, 0.18, 0.42)
|
||||
selected.shadow_size = 10
|
||||
selected.shadow_offset = Vector2(0, 2)
|
||||
btn.add_theme_stylebox_override("normal", normal)
|
||||
btn.add_theme_stylebox_override("hover", hover)
|
||||
btn.add_theme_stylebox_override("pressed", selected)
|
||||
btn.add_theme_stylebox_override("hover_pressed", selected)
|
||||
btn.add_theme_stylebox_override("focus", selected)
|
||||
return btn
|
||||
|
||||
|
||||
func show_menu() -> void:
|
||||
# preseleziona dall'ultima scelta salvata
|
||||
var mode: int = Settings.game_mode
|
||||
if mode == 2:
|
||||
infinite_btn.button_pressed = true
|
||||
target_btn.button_pressed = false
|
||||
else:
|
||||
target_btn.button_pressed = true
|
||||
infinite_btn.button_pressed = false
|
||||
zen_cb.button_pressed = (mode == 1)
|
||||
_on_mode_changed()
|
||||
visible = true
|
||||
get_tree().paused = true
|
||||
_card.modulate.a = 0.0
|
||||
_card.scale = Vector2(0.93, 0.93)
|
||||
_card.pivot_offset = _card.size * 0.5
|
||||
play_btn.modulate.a = 0.0
|
||||
var tw := create_tween()
|
||||
tw.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
|
||||
tw.set_parallel(true)
|
||||
tw.tween_property(_card, "modulate:a", 1.0, 0.22)
|
||||
tw.tween_property(_card, "scale", Vector2.ONE, 0.38).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
|
||||
tw.tween_property(play_btn, "modulate:a", 1.0, 0.3).set_delay(0.24)
|
||||
|
||||
|
||||
func _on_mode_changed(_btn: BaseButton = null) -> void:
|
||||
# lo Zen è disponibile SOLO per la modalità Target
|
||||
zen_cb.visible = target_btn.button_pressed
|
||||
|
||||
|
||||
func hide_menu() -> void:
|
||||
visible = false
|
||||
get_tree().paused = false
|
||||
|
||||
|
||||
func _on_play() -> void:
|
||||
# applica la scelta e salva (per ricordarla al prossimo avvio)
|
||||
if infinite_btn.button_pressed:
|
||||
Settings.game_mode = 2
|
||||
elif zen_cb.button_pressed:
|
||||
Settings.game_mode = 1
|
||||
else:
|
||||
Settings.game_mode = 0
|
||||
Settings.save_settings()
|
||||
hide_menu()
|
||||
mode_chosen.emit()
|
||||
Reference in New Issue
Block a user