From 2a629adf2c8daff44b3704bdf9d74a747459434b Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Mon, 3 Aug 2026 17:17:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B7=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=B5:=20=D1=82=D1=91=D0=BC=D0=BD=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=BD=D0=B0=D1=82=D1=8B-=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=BF=D0=BE=D1=80=D1=82=D1=8B=20=D0=B2=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BE=20=D0=BB=D0=B5=D1=81=D1=82=D0=BD=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Убраны процедурные лестницы - По одной тёмной комнате на этаж (затемнение + фиолетовое портальное свечение) - Персонаж идёт в тёмную комнату своего этажа и телепортируется в тёмную комнату случайного другого этажа Co-Authored-By: Claude Opus 4.8 --- README.md | 8 +++-- src/RoomMap.cs | 98 ++++++++++++++++++++++---------------------------- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 5b082d4..c3ec2c9 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,11 @@ D:\Godot_v4.7.1\Godot_v4.7.1-stable_mono_win64.exe Главное меню (`scenes/MainMenu.tscn`) ведёт на три сцены (назад в меню — `Esc`): 1. **Подземелье** (`scenes/Dungeon.tscn`) — разрез убежища à la Fallout Shelter: сетка 6×5 - комнат, **лестницы** между этажами, **объекты** (фонари/свет) и **несколько персонажей**, - которые ходят по этажам (нативные сцены с анимацией `walk_0`/`idle_0`). - ЛКМ/WASD — панорама, колесо — зум, `R` — сброс. + комнат, **тёмные комнаты-телепорты** (по одной на этаж — персонаж заходит и + переносится на другой этаж), **объекты** (фонари/свет) и **несколько персонажей**, + которые ходят по этажам (нативные сцены, `walk_0`/`idle_0`). + ЛКМ по персонажу — выбрать/тащить (перенос в комнату), ЛКМ по фону/WASD — панорама, + колесо — зум, `R` — сброс. 2. **Просмотр спрайтов** (`scenes/SpriteViewer.tscn`) — галерея вытащенных изображений (UI, фоны, эффекты, нарезанные спрайты). `A/D` — картинка, `W/S` — категория, колесо — зум. 3. **Нативные анимации** (`scenes/NativeViewer.tscn`) — браузер всех 38 персонажей нативно: diff --git a/src/RoomMap.cs b/src/RoomMap.cs index d91b180..e740581 100644 --- a/src/RoomMap.cs +++ b/src/RoomMap.cs @@ -19,8 +19,8 @@ public partial class RoomMap : Node2D private float _viewZoom = 1f; private Vector2 _homePos; - private static readonly float[] LadderXs = { 2f * Cell, 4f * Cell }; private static float FloorY(int row) => row * Cell + Cell * 0.9f; + private float[] _darkX; // X центра тёмной комнаты-телепорта на каждом этаже private readonly List _pawns = new(); private System.Random _rng; @@ -30,15 +30,15 @@ public partial class RoomMap : Node2D private PanelContainer _infoPanel; private Label _infoLabel; - private enum PState { Idle, Walk, GoLadder, Climb, Held } + private enum PState { Idle, Walk, GoDark, Held } private class Pawn { public Node2D Node; public AnimationPlayer Ap; public string Name; - public int Row, TargetRow; - public float X, TargetX, TargetY, Speed, MinX, MaxX, IdleTimer, LadderX; + public int Row; + public float X, TargetX, Speed, MinX, MaxX, IdleTimer; public PState State; public string WalkAnim, IdleAnim; } @@ -113,28 +113,27 @@ public partial class RoomMap : Node2D for (int c = 0; c < Cols; c++) AddCell("res://assets/room_sliced/Frame.png", c, r, 1, 1, new Color(1, 1, 1, 0.5f)); - BuildStairs(); + BuildDarkRooms(); BuildObjects(); BuildPawns(); } - // ---------- лестницы (вертикальные шахты с перекладинами) ---------- - private void BuildStairs() + // ---------- тёмные комнаты-телепорты (по одной на этаж) ---------- + private void BuildDarkRooms() { - AddLadder(2 * Cell); - AddLadder(4 * Cell); - } - - private void AddLadder(float centerX) - { - const float w = 48f; - float x = centerX - w / 2f; - float h = Rows * Cell; - AddRect(new Rect2(x, 0, w, h), new Color(0.10f, 0.08f, 0.06f, 0.9f)); // шахта - AddRect(new Rect2(x + 3, 0, 7, h), new Color(0.45f, 0.30f, 0.17f)); // рельс слева - AddRect(new Rect2(x + w - 10, 0, 7, h), new Color(0.45f, 0.30f, 0.17f)); // рельс справа - for (float ry = 22; ry < h; ry += 40) - AddRect(new Rect2(x + 6, ry, w - 12, 8), new Color(0.55f, 0.38f, 0.20f)); // ступени + int[] cols = { 5, 0, 5, 0, 5 }; // столбец тёмной комнаты для каждого этажа (в шахматку по бокам) + _darkX = new float[Rows]; + for (int r = 0; r < Rows; r++) + { + int c = cols[r % cols.Length]; + _darkX[r] = c * Cell + Cell * 0.5f; + // затемнение интерьера ячейки + AddRect(new Rect2(c * Cell + 8, r * Cell + 8, Cell - 16, Cell - 16), new Color(0.02f, 0.02f, 0.05f, 0.93f)); + // портальное свечение по центру + AddTex("res://assets/room_sliced/Light.png", + new Rect2(c * Cell + Cell * 0.28f, r * Cell + Cell * 0.28f, Cell * 0.44f, Cell * 0.44f), + _world, new Color(0.5f, 0.4f, 1f, 0.55f)); + } } private void AddRect(Rect2 r, Color c) @@ -215,17 +214,13 @@ public partial class RoomMap : Node2D private void PlayWalk(Pawn p) { if (p.Ap != null && p.WalkAnim != null) p.Ap.Play(p.WalkAnim); } private void PlayIdle(Pawn p) { if (p.Ap != null && p.IdleAnim != null) p.Ap.Play(p.IdleAnim); } - // решить, что делать после простоя: гулять по этажу или лезть на другой этаж + // решить, что делать после простоя: гулять по этажу или уйти в тёмную комнату (телепорт) private void Decide(Pawn p) { - bool canUp = p.Row > 0, canDown = p.Row < Rows - 1; - if (_rng.NextDouble() < 0.5 && (canUp || canDown)) + if (Rows > 1 && _rng.NextDouble() < 0.45) { - p.LadderX = LadderXs[_rng.Next(LadderXs.Length)]; - int dir = (canUp && canDown) ? (_rng.NextDouble() < 0.5 ? -1 : 1) : (canUp ? -1 : 1); - p.TargetRow = p.Row + dir; - p.TargetX = p.LadderX; - p.State = PState.GoLadder; + p.TargetX = _darkX[p.Row]; + p.State = PState.GoDark; PlayWalk(p); } else @@ -246,41 +241,20 @@ public partial class RoomMap : Node2D break; case PState.Walk: - case PState.GoLadder: + case PState.GoDark: { - float tx = p.State == PState.GoLadder ? p.LadderX : p.TargetX; - float d = Mathf.Sign(tx - p.X); + float d = Mathf.Sign(p.TargetX - p.X); p.X += d * p.Speed * dt; p.Node.Scale = new Vector2(d >= 0 ? 1f : -1f, 1f); p.Node.Position = new Vector2(p.X, FloorY(p.Row)); - if (Mathf.Abs(tx - p.X) < 4f) + if (Mathf.Abs(p.TargetX - p.X) < 4f) { - if (p.State == PState.GoLadder) - { - p.X = p.LadderX; - p.TargetY = FloorY(p.TargetRow); - p.State = PState.Climb; - } + if (p.State == PState.GoDark) Teleport(p); else { p.State = PState.Idle; p.IdleTimer = 0.8f + (float)_rng.NextDouble() * 2.2f; PlayIdle(p); } } break; } - case PState.Climb: - { - float cy = p.Node.Position.Y; - cy += Mathf.Sign(p.TargetY - cy) * p.Speed * dt; - p.Node.Position = new Vector2(p.LadderX, cy); - p.Node.Scale = new Vector2(1f, 1f); - if (Mathf.Abs(p.TargetY - cy) < 4f) - { - p.Row = p.TargetRow; - p.Node.Position = new Vector2(p.LadderX, FloorY(p.Row)); - p.State = PState.Idle; p.IdleTimer = 0.4f + (float)_rng.NextDouble() * 1.5f; PlayIdle(p); - } - break; - } - case PState.Idle: p.IdleTimer -= dt; if (p.IdleTimer <= 0f) Decide(p); @@ -289,6 +263,20 @@ public partial class RoomMap : Node2D } } + // телепорт: из тёмной комнаты своего этажа — в тёмную комнату случайного другого этажа + private void Teleport(Pawn p) + { + int dest = p.Row; + if (Rows > 1) do { dest = _rng.Next(Rows); } while (dest == p.Row); + p.Row = dest; + p.X = _darkX[dest]; + p.Node.Position = new Vector2(p.X, FloorY(dest)); + p.State = PState.Idle; + p.IdleTimer = 0.5f + (float)_rng.NextDouble() * 1.2f; + PlayIdle(p); + if (_selected == p) ShowInfo(p); + } + private Pawn PawnAt(Vector2 worldPos) { float w = Cell * 0.5f, h = Cell * 0.85f; @@ -359,7 +347,7 @@ public partial class RoomMap : Node2D private void UpdateLabel() { _label.Text = - $"Карта убежища — {Cols}×{Rows} комнат, лестницы, {_pawns.Count} персонажа (ходят по этажам)\n" + + $"Карта убежища — {Cols}×{Rows} комнат, тёмные комнаты-телепорты, {_pawns.Count} персонажа\n" + $"ЛКМ по персонажу — выбрать/тащить · ЛКМ по фону/WASD — панорама · колесо — зум · R — сброс · Esc — меню"; }