Подземелье: телепорт внутри тёмной шахты (fade исчезновение/появление)

Персонаж доходит до тёмной шахты, плавно исчезает (alpha 1->0), переносится
в шахту на случайном другом этаже и плавно появляется (0->1). Без вертикального прохода.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-08-03 17:30:35 +03:00
co-authored by Claude Opus 4.8
parent 085cf3e5fa
commit a254309ec9
+20 -12
View File
@@ -30,7 +30,7 @@ public partial class RoomMap : Node2D
private PanelContainer _infoPanel; private PanelContainer _infoPanel;
private Label _infoLabel; private Label _infoLabel;
private enum PState { Idle, Walk, GoShaft, Climb, Held } private enum PState { Idle, Walk, GoShaft, Teleport, Held }
private class Pawn private class Pawn
{ {
@@ -38,7 +38,8 @@ public partial class RoomMap : Node2D
public AnimationPlayer Ap; public AnimationPlayer Ap;
public string Name; public string Name;
public int Row, TargetRow; public int Row, TargetRow;
public float X, TargetX, TargetY, Speed, MinX, MaxX, IdleTimer; public float X, TargetX, Speed, MinX, MaxX, IdleTimer, FadeT;
public bool Swapped;
public PState State; public PState State;
public string WalkAnim, IdleAnim; public string WalkAnim, IdleAnim;
} }
@@ -251,29 +252,35 @@ public partial class RoomMap : Node2D
{ {
p.X = _shaftX; p.X = _shaftX;
do { p.TargetRow = _rng.Next(Rows); } while (p.TargetRow == p.Row); do { p.TargetRow = _rng.Next(Rows); } while (p.TargetRow == p.Row);
p.TargetY = FloorY(p.TargetRow); p.State = PState.Teleport;
p.State = PState.Climb; p.FadeT = 0f; p.Swapped = false;
PlayWalk(p); // движение по шахте — боевой walk PlayIdle(p);
} }
else { p.State = PState.Idle; p.IdleTimer = 0.8f + (float)_rng.NextDouble() * 2.2f; PlayIdle(p); } else { p.State = PState.Idle; p.IdleTimer = 0.8f + (float)_rng.NextDouble() * 2.2f; PlayIdle(p); }
} }
break; break;
} }
case PState.Climb: // вертикальное движение сквозь тёмную шахту case PState.Teleport: // исчезнуть в шахте на одном этаже и появиться на другом
{ {
float cy = p.Node.Position.Y; const float dur = 0.5f;
cy += Mathf.Sign(p.TargetY - cy) * p.Speed * dt; p.FadeT += dt / dur;
p.Node.Position = new Vector2(_shaftX, cy); if (!p.Swapped && p.FadeT >= 0.5f)
p.Node.Scale = new Vector2(1f, 1f);
if (Mathf.Abs(p.TargetY - cy) < 4f)
{ {
p.Swapped = true;
p.Row = p.TargetRow; p.Row = p.TargetRow;
p.X = _shaftX;
p.Node.Position = new Vector2(_shaftX, FloorY(p.Row)); p.Node.Position = new Vector2(_shaftX, FloorY(p.Row));
if (_selected == p) ShowInfo(p);
}
float a = p.FadeT < 0.5f ? 1f - p.FadeT * 2f : (p.FadeT - 0.5f) * 2f;
p.Node.Modulate = new Color(1f, 1f, 1f, Mathf.Clamp(a, 0f, 1f));
if (p.FadeT >= 1f)
{
p.Node.Modulate = Colors.White;
p.State = PState.Idle; p.State = PState.Idle;
p.IdleTimer = 0.4f + (float)_rng.NextDouble() * 1.5f; p.IdleTimer = 0.4f + (float)_rng.NextDouble() * 1.5f;
PlayIdle(p); PlayIdle(p);
if (_selected == p) ShowInfo(p);
} }
break; break;
} }
@@ -305,6 +312,7 @@ public partial class RoomMap : Node2D
p.Row = row; p.Row = row;
p.X = Mathf.Clamp(col * Cell + Cell * 0.5f, p.MinX, p.MaxX); p.X = Mathf.Clamp(col * Cell + Cell * 0.5f, p.MinX, p.MaxX);
p.Node.Position = new Vector2(p.X, FloorY(row)); p.Node.Position = new Vector2(p.X, FloorY(row));
p.Node.Modulate = Colors.White;
p.State = PState.Idle; p.IdleTimer = 0.5f; PlayIdle(p); p.State = PState.Idle; p.IdleTimer = 0.5f; PlayIdle(p);
if (_selected == p) ShowInfo(p); if (_selected == p) ShowInfo(p);
} }