From a6f6785188a340add353b5a62e6ad0d94e9763e0 Mon Sep 17 00:00:00 2001 From: Dmitrii Bykov Date: Sun, 24 May 2026 18:23:05 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=BF=D1=83=D1=81=D1=82=D0=B0=D1=8F,=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D1=86=20=D0=B2=20=D1=81=D1=82=D0=B5=D0=BD?= =?UTF-8?q?=D1=83,=20=D0=BD=D0=B5=D1=82=20=D0=BC=D0=B5=D0=BD=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ФИКС АКТА 2 (главный баг): - CenterContainer/WelcomeScreen/FourSquares имели anchor_right=1.0 + offset_right=640 → элементы уезжали ЗА пределы экрана (далеко на восток). Установочное окно было невидно. Заменил на anchors_preset=15 (full rect) без offset, теперь Center правильно центрирует Window. - PanelContainer без StyleBox = прозрачный. Добавлены 3 StyleBoxFlat (style_window — основное окно с рамкой, style_titlebar — тёмный header с жёлтым заголовком, style_panel — для вложенных панелей). Окно установки теперь видимо как настоящее Шиндовс-окно. - Body теперь без scroll_active (fit_content), Buttons с min_size 110×28 — кнопки чётко видны. ОТЕЦ: - Шёл на ЗАПАД (position.x - 2.5 = -0.8) в стену, а дверь на ВОСТОКЕ. Меняю на +1.0 (восток к двери при x=2.05). - _walk_father_out: сначала поворот корпуса 0.3 сек к двери (rotation:y = -PI/2), потом 1.4 сек шагание: * движение position:x на восток * абс(sin) bob тела на 0.04м (4 шага) * sin качание ног (LegL/LegR) и рук (ArmL/ArmR) в противофазе с амплитудой 0.4/0.24 радиан - Теперь отец действительно идёт к двери с шагающей походкой. ГЛАВНОЕ МЕНЮ (чего не хватало): - scenes/main_menu.tscn: тёмный фон с виньетками, заголовок жёлтым акцентом, 4 кнопки (Новая игра / Продолжить / Настройки / Выйти), StyleBoxFlat для кнопок. - main_menu.gd: ESC = Quit, кнопка «Новая игра» → SceneManager.go_room(), GameState.reset() при входе в меню. - project.godot main_scene = main_menu.tscn (было act1_room). - SceneManager + go_main() метод. HUD UX: - set_date_time("","") теперь прячет лейбл (раньше показывал "· "). В меню HUD скрыт полностью. - В Акте 1 и кухне при _ready восстанавливается crosshair + controls_hint (которые меню скрывает). ЧЕГО ВСЁ ЕЩЁ НЕ ХВАТАЕТ (для следующих сессий): - Звуки/SFX (шаги, клики, sfxr-эффекты, дверь) - Pause-меню по ESC во время геймплея - Save/load система (сейчас всё сбрасывается) - Анимация перехода между сценами (fade-in/out) - Реальные ассеты (CC0 модели мебели/персонажей) - Музыка/амбиент (CC0 трек комнаты) Co-Authored-By: Claude Opus 4.7 (1M context) --- project.godot | 2 +- scenes/main_menu.tscn | 121 ++++++++++++++++++++++++++++++ scenes/prologue/act2_install.tscn | 87 ++++++++++++++++----- scripts/main_menu.gd | 30 ++++++++ scripts/prologue/act1.gd | 47 +++++++++++- scripts/prologue/act1_kitchen.gd | 2 + scripts/ui/dialog_manager.gd | 4 + scripts/util/scene_manager.gd | 6 +- 8 files changed, 275 insertions(+), 24 deletions(-) create mode 100644 scenes/main_menu.tscn create mode 100644 scripts/main_menu.gd diff --git a/project.godot b/project.godot index a1d7fd3..b025b66 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Farming Simulator" config/description="Подросток-фермер CS/TF2/PUBG-кейсов в стране Р, 2020-2022. Pre-alpha." -run/main_scene="res://scenes/prologue/act1_room.tscn" +run/main_scene="res://scenes/main_menu.tscn" config/features=PackedStringArray("4.6", "GL Compatibility") [autoload] diff --git a/scenes/main_menu.tscn b/scenes/main_menu.tscn new file mode 100644 index 0000000..e4ebfbe --- /dev/null +++ b/scenes/main_menu.tscn @@ -0,0 +1,121 @@ +[gd_scene load_steps=3 format=3] + +[ext_resource type="Script" path="res://scripts/main_menu.gd" id="1_menu"] + +[sub_resource type="StyleBoxFlat" id="style_btn"] +bg_color = Color(0.15, 0.16, 0.2, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.4, 0.42, 0.48, 1) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_left = 2 +corner_radius_bottom_right = 2 +content_margin_left = 12.0 +content_margin_top = 6.0 +content_margin_right = 12.0 +content_margin_bottom = 6.0 + +[node name="MainMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_menu") + +[node name="BG" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color(0.06, 0.06, 0.09, 1) + +[node name="VignetteTop" type="ColorRect" parent="."] +offset_left = 0.0 +offset_top = 0.0 +offset_right = 640.0 +offset_bottom = 60.0 +color = Color(0.04, 0.04, 0.07, 1) + +[node name="VignetteBot" type="ColorRect" parent="."] +offset_left = 0.0 +offset_top = 300.0 +offset_right = 640.0 +offset_bottom = 360.0 +color = Color(0.04, 0.04, 0.07, 1) + +[node name="Center" type="CenterContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="V" type="VBoxContainer" parent="Center"] +custom_minimum_size = Vector2(320, 270) +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="Title" type="Label" parent="Center/V"] +layout_mode = 2 +text = "FARMING SIMULATOR" +horizontal_alignment = 1 +modulate = Color(0.94, 0.71, 0.1, 1) + +[node name="Tagline" type="Label" parent="Center/V"] +layout_mode = 2 +text = "Подросток-фермер CS/TF2/PUBG кейсов · 2020-2026" +horizontal_alignment = 1 +modulate = Color(0.7, 0.7, 0.7, 1) + +[node name="Spacer" type="Control" parent="Center/V"] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 + +[node name="BtnNew" type="Button" parent="Center/V"] +custom_minimum_size = Vector2(200, 32) +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_styles/normal = SubResource("style_btn") +text = "Новая игра" + +[node name="BtnContinue" type="Button" parent="Center/V"] +custom_minimum_size = Vector2(200, 32) +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_styles/normal = SubResource("style_btn") +disabled = true +text = "Продолжить (нет сохранения)" + +[node name="BtnSettings" type="Button" parent="Center/V"] +custom_minimum_size = Vector2(200, 32) +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_styles/normal = SubResource("style_btn") +disabled = true +text = "Настройки (TBD)" + +[node name="BtnQuit" type="Button" parent="Center/V"] +custom_minimum_size = Vector2(200, 32) +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_styles/normal = SubResource("style_btn") +text = "Выйти" + +[node name="Version" type="Label" parent="."] +offset_left = 8.0 +offset_top = 340.0 +offset_right = 280.0 +offset_bottom = 356.0 +text = "v0.1 pre-alpha · pre-canon build" +modulate = Color(0.5, 0.5, 0.5, 1) + +[node name="EscHint" type="Label" parent="."] +offset_left = 420.0 +offset_top = 340.0 +offset_right = 632.0 +offset_bottom = 356.0 +text = "ESC — выйти" +horizontal_alignment = 2 +modulate = Color(0.5, 0.5, 0.5, 1) diff --git a/scenes/prologue/act2_install.tscn b/scenes/prologue/act2_install.tscn index 38c1872..24a84de 100644 --- a/scenes/prologue/act2_install.tscn +++ b/scenes/prologue/act2_install.tscn @@ -1,29 +1,72 @@ -[gd_scene load_steps=2 format=3] +[gd_scene load_steps=5 format=3] [ext_resource type="Script" path="res://scripts/prologue/act2_install.gd" id="1_act2"] +[sub_resource type="StyleBoxFlat" id="style_window"] +bg_color = Color(0.13, 0.14, 0.18, 0.97) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(0.42, 0.44, 0.5, 1) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_left = 4 +corner_radius_bottom_right = 4 +content_margin_left = 12.0 +content_margin_top = 8.0 +content_margin_right = 12.0 +content_margin_bottom = 10.0 + +[sub_resource type="StyleBoxFlat" id="style_titlebar"] +bg_color = Color(0.08, 0.09, 0.13, 1) +border_width_bottom = 1 +border_color = Color(0.42, 0.44, 0.5, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +content_margin_left = 8.0 +content_margin_top = 4.0 +content_margin_right = 8.0 +content_margin_bottom = 4.0 + +[sub_resource type="StyleBoxFlat" id="style_panel"] +bg_color = Color(0.16, 0.17, 0.22, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.35, 0.37, 0.43, 1) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_left = 2 +corner_radius_bottom_right = 2 +content_margin_left = 8.0 +content_margin_top = 6.0 +content_margin_right = 8.0 +content_margin_bottom = 6.0 + [node name="Act2Install" type="Control"] layout_mode = 3 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 script = ExtResource("1_act2") [node name="Desktop" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 color = Color(0.04, 0.08, 0.18, 1) [node name="FourSquares" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 [node name="LogoText" type="Label" parent="FourSquares"] +layout_mode = 0 offset_left = 0.0 offset_top = 130.0 offset_right = 640.0 @@ -70,20 +113,22 @@ horizontal_alignment = 1 modulate = Color(0.7, 0.7, 0.7, 1) [node name="Center" type="CenterContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 [node name="Window" type="PanelContainer" parent="Center"] -custom_minimum_size = Vector2(540, 300) +custom_minimum_size = Vector2(560, 320) layout_mode = 2 +theme_override_styles/panel = SubResource("style_window") [node name="V" type="VBoxContainer" parent="Center/Window"] layout_mode = 2 [node name="TitleBar" type="PanelContainer" parent="Center/Window/V"] layout_mode = 2 +theme_override_styles/panel = SubResource("style_titlebar") [node name="Title" type="Label" parent="Center/Window/V/TitleBar"] layout_mode = 2 @@ -92,12 +137,12 @@ horizontal_alignment = 1 modulate = Color(0.94, 0.71, 0.1, 1) [node name="Body" type="RichTextLabel" parent="Center/Window/V"] -custom_minimum_size = Vector2(520, 160) +custom_minimum_size = Vector2(530, 180) layout_mode = 2 bbcode_enabled = true fit_content = true scroll_active = true -text = "" +text = "Загрузка…" [node name="Input" type="LineEdit" parent="Center/Window/V"] layout_mode = 2 @@ -108,7 +153,7 @@ max_length = 24 layout_mode = 2 text = "" autowrap_mode = 3 -modulate = Color(0.55, 0.55, 0.55, 1) +modulate = Color(0.6, 0.6, 0.6, 1) [node name="CheckBoxNoPwd" type="CheckBox" parent="Center/Window/V"] layout_mode = 2 @@ -120,7 +165,7 @@ layout_mode = 2 [node name="ErrorLabel" type="Label" parent="Center/Window/V"] layout_mode = 2 text = "" -modulate = Color(0.85, 0.16, 0.16, 1) +modulate = Color(0.95, 0.3, 0.3, 1) [node name="Progress" type="ProgressBar" parent="Center/Window/V"] layout_mode = 2 @@ -133,24 +178,26 @@ alignment = 2 [node name="BtnB" type="Button" parent="Center/Window/V/Buttons"] layout_mode = 2 +custom_minimum_size = Vector2(110, 28) text = "Читать" [node name="BtnA" type="Button" parent="Center/Window/V/Buttons"] layout_mode = 2 +custom_minimum_size = Vector2(110, 28) text = "Принять" [node name="WelcomeScreen" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 visible = false [node name="BG" type="ColorRect" parent="WelcomeScreen"] +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 640.0 -offset_bottom = 360.0 color = Color(0.04, 0.08, 0.18, 1) [node name="V" type="VBoxContainer" parent="WelcomeScreen"] @@ -168,12 +215,14 @@ modulate = Color(0.94, 0.94, 0.94, 1) [node name="Hint" type="Label" parent="WelcomeScreen/V"] layout_mode = 2 -text = "" +text = "Шиндовс 9 готов к работе." horizontal_alignment = 1 modulate = Color(0.7, 0.7, 0.7, 1) [node name="LaunchSteme" type="Button" parent="WelcomeScreen/V"] layout_mode = 2 +custom_minimum_size = Vector2(160, 32) +size_flags_horizontal = 4 text = "Запустить стеме" [connection signal="pressed" from="WelcomeScreen/V/LaunchSteme" to="." method="_on_launch_steme"] diff --git a/scripts/main_menu.gd b/scripts/main_menu.gd new file mode 100644 index 0000000..6de10e4 --- /dev/null +++ b/scripts/main_menu.gd @@ -0,0 +1,30 @@ +extends Control + +@onready var btn_new: Button = $Center/V/BtnNew +@onready var btn_continue: Button = $Center/V/BtnContinue +@onready var btn_quit: Button = $Center/V/BtnQuit + + +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + GameState.reset() + DialogManager.set_crosshair_visible(false) + DialogManager.set_controls_hint("") + DialogManager.set_date_time("", "") + DialogManager.set_objective("") + btn_new.pressed.connect(_on_new_game) + btn_quit.pressed.connect(_on_quit) + btn_new.grab_focus() + + +func _on_new_game() -> void: + SceneManager.go_room() + + +func _on_quit() -> void: + get_tree().quit() + + +func _input(event: InputEvent) -> void: + if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE: + get_tree().quit() diff --git a/scripts/prologue/act1.gd b/scripts/prologue/act1.gd index d082015..e44f226 100644 --- a/scripts/prologue/act1.gd +++ b/scripts/prologue/act1.gd @@ -19,6 +19,8 @@ func _ready() -> void: player.interactable_unfocused.connect(_on_player_unfocused) DialogManager.set_date_time(GameState.game_date, GameState.game_time) + DialogManager.set_crosshair_visible(true) + DialogManager.set_controls_hint("WASD ходить · мышь смотреть · ЛКМ взаимодействие · ESC мышь · Q выход") # Если возвращаемся из кухни — пропускаем интро if GameState.act1_father_left: @@ -137,9 +139,7 @@ func _on_note_interacted(_p: Node) -> void: state = State.FATHER_FAREWELL await DialogManager.say("ОТЕЦ", "Флешка с Шиндой на столе. Ставь сам, не маленький. Если запорешь — сам и переставляй.") - var tween: Tween = create_tween() - tween.tween_property(father, "position:x", father.position.x - 2.5, 0.8) - await tween.finished + await _walk_father_out() father.visible = false GameState.act1_father_left = true @@ -150,6 +150,47 @@ func _on_note_interacted(_p: Node) -> void: player.unlock_input() +func _walk_father_out() -> void: + # Отец поворачивается лицом к двери (восток = +X) и шагает в неё + var leg_l: Node3D = father.get_node("LegL") + var leg_r: Node3D = father.get_node("LegR") + var arm_l: Node3D = father.get_node("ArmL") + var arm_r: Node3D = father.get_node("ArmR") + + # Поворот корпуса к двери (Y rotation -90° → лицом на восток) + var turn_tween: Tween = create_tween() + turn_tween.tween_property(father, "rotation:y", -PI / 2.0, 0.3) + await turn_tween.finished + + # Шагание: 4 шага по 0.35 сек, общий путь 1.0 м на восток + var initial_x: float = father.position.x + var walk_duration: float = 1.4 + var walk_distance: float = 1.0 + var steps: int = 4 + + var walk_tween: Tween = create_tween() + walk_tween.set_parallel(true) + # Движение + walk_tween.tween_property(father, "position:x", initial_x + walk_distance, walk_duration) + # Покачивание тела + walk_tween.tween_method( + func(t: float) -> void: + father.position.y = abs(sin(t * PI * float(steps))) * 0.04, + 0.0, 1.0, walk_duration + ) + # Махание ногами + walk_tween.tween_method( + func(t: float) -> void: + var ang: float = sin(t * PI * float(steps)) * 0.4 + leg_l.rotation.x = ang + leg_r.rotation.x = -ang + arm_l.rotation.x = -ang * 0.6 + arm_r.rotation.x = ang * 0.6, + 0.0, 1.0, walk_duration + ) + await walk_tween.finished + + func _on_door_interacted(_p: Node) -> void: if state != State.SEEK_DRIVE: return diff --git a/scripts/prologue/act1_kitchen.gd b/scripts/prologue/act1_kitchen.gd index c2796a9..faa1c37 100644 --- a/scripts/prologue/act1_kitchen.gd +++ b/scripts/prologue/act1_kitchen.gd @@ -17,6 +17,8 @@ func _ready() -> void: door_back.set_interactable(true) DialogManager.set_date_time(GameState.game_date, GameState.game_time) + DialogManager.set_crosshair_visible(true) + DialogManager.set_controls_hint("WASD ходить · мышь смотреть · ЛКМ взаимодействие · ESC мышь · Q выход") if GameState.wifi_password_found: DialogManager.set_objective("Вернись в комнату — флешка ждёт") else: diff --git a/scripts/ui/dialog_manager.gd b/scripts/ui/dialog_manager.gd index b6122ad..f9fc4a4 100644 --- a/scripts/ui/dialog_manager.gd +++ b/scripts/ui/dialog_manager.gd @@ -73,7 +73,11 @@ func clear_prompt() -> void: func set_date_time(date: String, time: String) -> void: + if date == "" and time == "": + date_time_label.visible = false + return date_time_label.text = "%s · %s" % [date, time] + date_time_label.visible = true func set_objective(text: String) -> void: diff --git a/scripts/util/scene_manager.gd b/scripts/util/scene_manager.gd index a32da5d..f91def1 100644 --- a/scripts/util/scene_manager.gd +++ b/scripts/util/scene_manager.gd @@ -1,16 +1,20 @@ extends Node +const SCENE_MAIN_MENU: String = "res://scenes/main_menu.tscn" const SCENE_ACT1_ROOM: String = "res://scenes/prologue/act1_room.tscn" const SCENE_ACT1_KITCHEN: String = "res://scenes/prologue/act1_kitchen.tscn" const SCENE_ACT2_INSTALL: String = "res://scenes/prologue/act2_install.tscn" func change_scene(path: String) -> void: - # Освобождаем мышь, чтобы 2D-сцены не были в captured-mode Input.mouse_mode = Input.MOUSE_MODE_VISIBLE get_tree().change_scene_to_file.call_deferred(path) +func go_main() -> void: + change_scene(SCENE_MAIN_MENU) + + func go_room() -> void: change_scene(SCENE_ACT1_ROOM)