diff --git a/assets/Tutorial_shield.jpeg.import b/assets/Tutorial_shield.jpeg.import index 2721869..0434bc8 100644 --- a/assets/Tutorial_shield.jpeg.import +++ b/assets/Tutorial_shield.jpeg.import @@ -3,15 +3,15 @@ importer="texture" type="CompressedTexture2D" uid="uid://baeea1yfs0cnn" -path="res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex" +path="res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://assets/Tutorial_Shield.jpeg" -dest_files=["res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex"] +source_file="res://assets/Tutorial_shield.jpeg" +dest_files=["res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex"] [params] diff --git a/scripts/GameSettings.gd b/scripts/GameSettings.gd new file mode 100644 index 0000000..7cdbd57 --- /dev/null +++ b/scripts/GameSettings.gd @@ -0,0 +1,5 @@ +class_name GameSettings + +## "immortal" — no damage, tier-based kick force +## "survival" — takes damage, fixed kick force +static var difficulty: String = "immortal" diff --git a/scripts/GameSettings.gd.uid b/scripts/GameSettings.gd.uid new file mode 100644 index 0000000..d8c41b2 --- /dev/null +++ b/scripts/GameSettings.gd.uid @@ -0,0 +1 @@ +uid://deu62njwuhjd3 diff --git a/scripts/MainMenu.gd b/scripts/MainMenu.gd index 1c80668..56a450b 100644 --- a/scripts/MainMenu.gd +++ b/scripts/MainMenu.gd @@ -3,6 +3,7 @@ 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 @@ -46,17 +47,57 @@ func _build_ui() -> void: vbox.add_child(_btn("Выход", _on_exit)) _build_settings_panel() + _build_difficulty_panel() 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 = Panel.new() + settings_panel = _make_opaque_panel() settings_panel.visible = false settings_panel.anchor_left = 0.5 settings_panel.anchor_right = 0.5 @@ -105,8 +146,62 @@ 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 = -230 + difficulty_panel.offset_right = 230 + difficulty_panel.offset_top = -160 + difficulty_panel.offset_bottom = 160 + 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) + + var immortal_btn := Button.new() + immortal_btn.text = "Бессмертный\nНет урона · тир пинков от мелких врагов" + immortal_btn.custom_minimum_size = Vector2(380, 72) + immortal_btn.add_theme_font_size_override("font_size", 18) + immortal_btn.connect("pressed", func() -> void: + GameSettings.difficulty = "immortal" + get_tree().change_scene_to_file("res://scenes/Main.tscn") + ) + vbox.add_child(immortal_btn) + + var survival_btn := Button.new() + survival_btn.text = "Выживание\nПолучаешь урон · фиксированная сила пинка" + survival_btn.custom_minimum_size = Vector2(380, 72) + survival_btn.add_theme_font_size_override("font_size", 18) + survival_btn.connect("pressed", func() -> void: + GameSettings.difficulty = "survival" + get_tree().change_scene_to_file("res://scenes/Main.tscn") + ) + vbox.add_child(survival_btn) + + vbox.add_child(_btn("Назад", func(): difficulty_panel.visible = false)) + func _on_play() -> void: - get_tree().change_scene_to_file("res://scenes/Main.tscn") + difficulty_panel.visible = true func _on_settings() -> void: settings_panel.visible = true diff --git a/scripts/Player.gd b/scripts/Player.gd index a1e3d59..a0b3ca5 100644 --- a/scripts/Player.gd +++ b/scripts/Player.gd @@ -180,7 +180,9 @@ func _do_kick() -> void: var obj_toughness: int = best.get("toughness_tier") if best.get("toughness_tier") != null else 0 var diff_tier := kick_tier - obj_toughness var force: float - if diff_tier < 0: + if GameSettings.difficulty == "survival": + force = 50.0 + elif diff_tier < 0: force = 15.0 elif diff_tier == 0: force = 50.0 @@ -229,6 +231,8 @@ func receive_kick(direction: Vector3, force: float) -> void: _squish_effect() func take_damage(amount: int, attacker_toughness: int = 0) -> void: + if GameSettings.difficulty == "immortal": + return if not is_alive or invincible_timer > 0.0: return invincible_timer = IFRAMES_DURATION