extends Control static var volume: float = 100.0 var settings_panel: Panel var difficulty_panel: Panel func _ready() -> void: process_mode = Node.PROCESS_MODE_ALWAYS set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) _build_ui() _apply_volume(volume) func _build_ui() -> void: var bg := ColorRect.new() bg.color = Color(0.06, 0.04, 0.10) bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) add_child(bg) var title := Label.new() title.text = "KickSurvivors" title.add_theme_font_size_override("font_size", 52) title.add_theme_color_override("font_color", Color.WHITE) title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER title.anchor_left = 0.5 title.anchor_right = 0.5 title.anchor_top = 0.0 title.offset_left = -200 title.offset_right = 200 title.offset_top = 110 add_child(title) var vbox := VBoxContainer.new() vbox.add_theme_constant_override("separation", 14) vbox.anchor_left = 0.5 vbox.anchor_right = 0.5 vbox.anchor_top = 0.5 vbox.anchor_bottom = 0.5 vbox.offset_left = -110 vbox.offset_right = 110 vbox.offset_top = -90 vbox.offset_bottom = 90 add_child(vbox) vbox.add_child(_btn("Играть", _on_play)) vbox.add_child(_btn("Настройки", _on_settings)) vbox.add_child(_btn("Выход", _on_exit)) _build_settings_panel() _build_difficulty_panel() func _big_btn(text: String, width: float, cb: Callable) -> Button: var b := _btn(text, cb) b.custom_minimum_size = Vector2(width, 72) b.add_theme_font_size_override("font_size", 18) return b func _btn(text: String, cb: Callable) -> Button: var b := Button.new() b.text = text b.custom_minimum_size = Vector2(220, 54) b.add_theme_font_size_override("font_size", 20) for state in ["normal", "hover", "pressed", "focus", "disabled"]: var sb := StyleBoxFlat.new() sb.bg_color = Color(0.18, 0.13, 0.30) if state == "normal" else ( Color(0.28, 0.20, 0.46) if state == "hover" else Color(0.12, 0.09, 0.22)) sb.border_width_left = 1 sb.border_width_right = 1 sb.border_width_top = 1 sb.border_width_bottom = 1 sb.border_color = Color(0.50, 0.38, 0.75) sb.corner_radius_top_left = 6 sb.corner_radius_top_right = 6 sb.corner_radius_bottom_left = 6 sb.corner_radius_bottom_right = 6 sb.content_margin_left = 20 sb.content_margin_right = 20 sb.content_margin_top = 12 sb.content_margin_bottom = 12 b.add_theme_stylebox_override(state, sb) b.connect("pressed", cb) return b static func _make_opaque_panel() -> Panel: var p := Panel.new() var sb := StyleBoxFlat.new() sb.bg_color = Color(0.08, 0.06, 0.14) sb.border_width_left = 2 sb.border_width_right = 2 sb.border_width_top = 2 sb.border_width_bottom = 2 sb.border_color = Color(0.35, 0.28, 0.55) sb.corner_radius_top_left = 8 sb.corner_radius_top_right = 8 sb.corner_radius_bottom_left = 8 sb.corner_radius_bottom_right = 8 sb.content_margin_left = 24 sb.content_margin_right = 24 sb.content_margin_top = 20 sb.content_margin_bottom = 20 p.add_theme_stylebox_override("panel", sb) return p func _build_settings_panel() -> void: settings_panel = _make_opaque_panel() settings_panel.visible = false settings_panel.anchor_left = 0.5 settings_panel.anchor_right = 0.5 settings_panel.anchor_top = 0.5 settings_panel.anchor_bottom = 0.5 settings_panel.offset_left = -200 settings_panel.offset_right = 200 settings_panel.offset_top = -130 settings_panel.offset_bottom = 130 add_child(settings_panel) var vbox := VBoxContainer.new() vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) vbox.alignment = BoxContainer.ALIGNMENT_CENTER vbox.add_theme_constant_override("separation", 18) settings_panel.add_child(vbox) var lbl := Label.new() lbl.text = "Настройки" lbl.add_theme_font_size_override("font_size", 26) lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vbox.add_child(lbl) var vol_lbl := Label.new() vol_lbl.name = "VolumeLabel" vol_lbl.text = "Громкость: %d" % int(volume) vol_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vbox.add_child(vol_lbl) var slider := HSlider.new() slider.min_value = 0 slider.max_value = 100 slider.step = 1 slider.value = volume slider.custom_minimum_size = Vector2(320, 32) slider.connect("value_changed", func(v: float) -> void: volume = v vol_lbl.text = "Громкость: %d" % int(v) _apply_volume(v) ) vbox.add_child(slider) vbox.add_child(_btn("Назад", func(): settings_panel.visible = false)) func _apply_volume(v: float) -> void: var db := linear_to_db(v / 100.0) if v > 0.0 else -80.0 AudioServer.set_bus_volume_db(0, db) func _build_difficulty_panel() -> void: difficulty_panel = _make_opaque_panel() difficulty_panel.visible = false difficulty_panel.anchor_left = 0.5 difficulty_panel.anchor_right = 0.5 difficulty_panel.anchor_top = 0.5 difficulty_panel.anchor_bottom = 0.5 difficulty_panel.offset_left = -310 difficulty_panel.offset_right = 310 difficulty_panel.offset_top = -240 difficulty_panel.offset_bottom = 240 add_child(difficulty_panel) var margin := MarginContainer.new() margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) margin.add_theme_constant_override("margin_left", 24) margin.add_theme_constant_override("margin_right", 24) margin.add_theme_constant_override("margin_top", 20) margin.add_theme_constant_override("margin_bottom", 20) difficulty_panel.add_child(margin) var vbox := VBoxContainer.new() vbox.alignment = BoxContainer.ALIGNMENT_CENTER vbox.add_theme_constant_override("separation", 16) margin.add_child(vbox) var title := Label.new() title.text = "Выберите сложность" title.add_theme_font_size_override("font_size", 26) title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vbox.add_child(title) vbox.add_child(_big_btn("Бессмертный\nНет урона · тир пинков от мелких врагов", 540, func() -> void: GameSettings.difficulty = "immortal" get_tree().change_scene_to_file("res://scenes/Main.tscn") )) vbox.add_child(_big_btn("Выживание\nПолучаешь урон · фиксированная сила пинка", 540, func() -> void: GameSettings.difficulty = "survival" get_tree().change_scene_to_file("res://scenes/Main.tscn") )) # Spawn speed row var spawn_lbl := Label.new() spawn_lbl.text = "Скорость спавна:" spawn_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER spawn_lbl.add_theme_font_size_override("font_size", 16) spawn_lbl.add_theme_color_override("font_color", Color(0.85, 0.78, 1.0)) vbox.add_child(spawn_lbl) var hbox := HBoxContainer.new() hbox.alignment = BoxContainer.ALIGNMENT_CENTER hbox.add_theme_constant_override("separation", 10) vbox.add_child(hbox) var spawn_options := [ ["Медленно", 15.0, 35.0], ["Нормально", 10.0, 20.0], ["Быстро", 5.0, 8.0], ] var spawn_btns: Array[Button] = [] for opt in spawn_options: var sb_btn := _btn(opt[0] as String, Callable()) sb_btn.custom_minimum_size = Vector2(110, 40) sb_btn.add_theme_font_size_override("font_size", 15) var enemy_iv: float = opt[1] var item_iv: float = opt[2] sb_btn.connect("pressed", func() -> void: GameSettings.enemy_spawn_interval = enemy_iv GameSettings.item_respawn_delay = item_iv for b in spawn_btns: b.modulate = Color(1, 1, 1) sb_btn.modulate = Color(0.7, 1.0, 0.5) ) hbox.add_child(sb_btn) spawn_btns.append(sb_btn) # default: normal spawn_btns[1].modulate = Color(0.7, 1.0, 0.5) vbox.add_child(_btn("Назад", func(): difficulty_panel.visible = false)) func _on_play() -> void: difficulty_panel.visible = true func _on_settings() -> void: settings_panel.visible = true func _on_exit() -> void: get_tree().quit()