diff --git a/CLAUDE.md b/CLAUDE.md index f67f8f1..ba7a943 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,10 @@ G-WORLD — **2D-симулятор убежища с видом сбоку** (референс Fallout Shelter): порода, вырытые шахты, комнаты на сетке, жители, время/погода/климат. -Godot **4.7**, GDScript, рендер Forward+, целевая платформа — Windows. +Godot **4.7**, GDScript, рендер Mobile, целевая платформа — Windows. + +Главная сцена — `src/main/main.tscn`: `Main (Node2D)` → `World (Node2D)` + +`UI (CanvasLayer)`. `main.gd` только собирает игру, игровых правил в нём нет. Игра двумерная. Если в задаче или в коде появляется 3D-нода (`Node3D`, `CharacterBody3D`, `Camera3D`) — это ошибка, а не задумка: уточнить у @@ -15,9 +18,9 @@ Godot **4.7**, GDScript, рендер Forward+, целевая платформ ## Где что лежит -- `src/main/` — точка входа. -- `src/autoload/` — синглтоны. Новую автозагрузку регистрировать через настройки - проекта и описывать в `docs/ARCHITECTURE.md`. +- `src/main/` — точка входа (`main.tscn` + `main.gd`). +- `src/autoload/` — синглтоны; сейчас только `EventBus`. Новую автозагрузку + регистрировать через `autoload_manage` и описывать в `docs/ARCHITECTURE.md`. - `src/core/` — утилиты и типы без знания о геймплее. - `src/data/resources/` — схемы контента (наследники `Resource`), `src/data/tables/` — сами `.tres`. @@ -64,6 +67,10 @@ Godot-редактор, скорее всего, открыт, и он влад `project_manage`, `resource_manage`) — они работают через живой редактор. - `.gd`-файлы править обычными Edit/Write — это нормально, редактор их перечитает. +- Исключение: ключи, влияющие на старт проекта (`application/run/main_scene`), + MCP ставить отказывается. Их правим прямо в `project.godot` и просим + пользователя перезагрузить проект (*Project → Reload Current Project*) — + иначе редактор перезапишет файл из своей памяти. - Проверять результат: `project_run` + `logs_read` (ошибки парсера и рантайма), `editor_screenshot` — чтобы увидеть сцену глазами. - `addons/` — вендорный код плагина, его не трогаем. @@ -71,8 +78,8 @@ Godot-редактор, скорее всего, открыт, и он влад ## Чего не делать - Не коммитить и не пушить без явной просьбы. -- Не добавлять C#: в `project.godot` есть секция `[dotnet]`, но проект на - GDScript. Не заводить `.cs`, не обсудив. +- Не добавлять C#: проект на GDScript, секция `[dotnet]` из `project.godot` + убрана намеренно. Не заводить `.cs`, не обсудив. - Не класть тяжёлое сырьё в `assets/` — для него есть игнорируемые `kits/` и `ai-input/`. - Не удалять `.gitkeep` из ещё пустых папок — они держат структуру в git. diff --git a/README.md b/README.md index ea7c1dc..e909537 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ | | | | --- | --- | -| Движок | Godot **4.7**, рендер Forward+ | +| Движок | Godot **4.7**, рендер Mobile (игра двумерная, Forward+ не нужен) | | Язык | GDScript (типизированный) | | Платформа | Windows (desktop), рендер-драйвер D3D12 | @@ -13,7 +13,7 @@ 1. Установить Godot 4.7. 2. Открыть папку проекта из Project Manager (`project.godot` в корне). -3. `F5` — запуск. Главная сцена задаётся в *Project → Project Settings → Run*. +3. `F5` — запуск. Главная сцена: `src/main/main.tscn`. Плагин `addons/godot_ai` (MCP-мост для агентов) включается в *Project → Project Settings → Plugins*. @@ -31,8 +31,8 @@ assets/ # Сырьё: то, что рисуется и звучит. shaders/ # .gdshader, переиспользуемые между сценами src/ # Весь код и сцены. Сцена лежит рядом со своим скриптом. - main/ # точка входа: bootstrap-сцена, сборка автозагрузок - autoload/ # синглтоны (EventBus, SaveManager, GameState) + main/ # точка входа: main.tscn (Main → World, UI) и её скрипт + autoload/ # синглтоны: event_bus.gd, дальше SaveManager, GameState core/ # инфраструктура без знания о геймплее: утилиты, типы data/resources/ # схемы данных — наследники Resource (RoomDef, ItemDef) data/tables/ # экземпляры схем — .tres-«база данных» контента diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 51c53d5..acea0c6 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,8 +68,25 @@ main ──→ autoload ──→ core автозагрузка регистрируется через *Project Settings → Autoload* и упоминается здесь. -Сейчас в проекте: `_mcp_game_helper` — служебная, часть плагина `godot_ai`, -к игровой логике отношения не имеет. +Сейчас в проекте: + +| Автозагрузка | Что делает | +| --- | --- | +| `EventBus` (`src/autoload/event_bus.gd`) | Глобальная шина событий, пока пустая | +| `_mcp_game_helper` | Служебная, часть плагина `godot_ai`; к игре отношения не имеет | + +## Точка входа + +`src/main/main.tscn` — главная сцена проекта: + +``` +Main (Node2D) # main.gd: только сборка, никаких игровых правил +├── World (Node2D) # убежище: порода, сетка, комнаты, жители +└── UI (CanvasLayer) # интерфейс поверх мира, не зависит от камеры +``` + +`World` и `UI` разделены слоями сразу, чтобы интерфейс не ездил вместе с +камерой убежища и не масштабировался вместе с зумом. ## Решения diff --git a/project.godot b/project.godot index a94de2f..ead8c3a 100644 --- a/project.godot +++ b/project.godot @@ -11,30 +11,25 @@ config_version=5 [application] config/name="g-world" -config/features=PackedStringArray("4.7", "Forward Plus") +run/main_scene="res://src/main/main.tscn" +config/features=PackedStringArray("4.7", "Mobile") config/icon="res://icon.svg" [autoload] _mcp_game_helper="*res://addons/godot_ai/runtime/game_helper.gd" +EventBus="*res://src/autoload/event_bus.gd" [display] window/stretch/mode="canvas_items" window/stretch/aspect="expand" -[dotnet] - -project/assembly_name="g-world" - [editor_plugins] enabled=PackedStringArray("res://addons/godot_ai/plugin.cfg") -[physics] - -3d/physics_engine="Jolt Physics" - [rendering] rendering_device/driver.windows="d3d12" +renderer/rendering_method="mobile" diff --git a/src/autoload/event_bus.gd b/src/autoload/event_bus.gd new file mode 100644 index 0000000..695768b --- /dev/null +++ b/src/autoload/event_bus.gd @@ -0,0 +1,10 @@ +extends Node +## Глобальная шина событий. +## +## Сюда попадают только те события, которые слушают несколько несвязанных +## слоёв — например «время перескочило» или «погода сменилась». Связь между +## родителем и ребёнком в одной сцене делается обычными сигналами, а не через +## шину: иначе шина превращается в свалку, по которой невозможно проследить, +## кто на что реагирует. +## +## Каждый сигнал документируем: кто испускает, когда и что означают аргументы. diff --git a/src/autoload/event_bus.gd.uid b/src/autoload/event_bus.gd.uid new file mode 100644 index 0000000..297d792 --- /dev/null +++ b/src/autoload/event_bus.gd.uid @@ -0,0 +1 @@ +uid://d2yx4s6r8loj6 diff --git a/src/main/main.gd b/src/main/main.gd new file mode 100644 index 0000000..a451a2a --- /dev/null +++ b/src/main/main.gd @@ -0,0 +1,13 @@ +extends Node2D +## Точка входа в игру. +## +## Здесь только сборка: подключить слои, создать системы и связать их между +## собой. Игровых правил в этом файле быть не должно — они живут в [code]src/systems[/code]. +## +## Слои сцены: +## [br]— [code]World[/code] ([Node2D]) — убежище: порода, сетка, комнаты, жители. +## [br]— [code]UI[/code] ([CanvasLayer]) — интерфейс поверх мира, не зависит от камеры. + + +func _ready() -> void: + print_rich("[color=gray]G-WORLD: bootstrap готов[/color]") diff --git a/src/main/main.gd.uid b/src/main/main.gd.uid new file mode 100644 index 0000000..21344fa --- /dev/null +++ b/src/main/main.gd.uid @@ -0,0 +1 @@ +uid://636vmin1w6l5 diff --git a/src/main/main.tscn b/src/main/main.tscn new file mode 100644 index 0000000..b7c790f --- /dev/null +++ b/src/main/main.tscn @@ -0,0 +1,10 @@ +[gd_scene format=3 uid="uid://cjpxn8oisiqtv"] + +[ext_resource type="Script" path="res://src/main/main.gd" id="1_3eh75"] + +[node name="Main" type="Node2D" unique_id=282763988] +script = ExtResource("1_3eh75") + +[node name="World" type="Node2D" parent="." unique_id=783773345] + +[node name="UI" type="CanvasLayer" parent="." unique_id=2492053]