地图系统

This commit is contained in:
2026-06-05 18:41:33 +08:00
parent 613f2a4d13
commit fe4fd60083
234 changed files with 33090 additions and 4899 deletions

View File

@@ -27,6 +27,12 @@ namespace BaseGames.World.Map
[SerializeField, Min(1)] private int _viewRadiusCells = 3; // 以玩家房间中心为圆心的可视半径(格)
[SerializeField] private float _cellPixels = 16f; // 每格显示像素数
[Header("定位门控(指南针)")]
[Tooltip("勾选后未启用定位能力IMapService.IsLocatorEnabled时隐藏玩家位置点——\n" +
"设计:拿到指南针护符前能看地图但不知自己在哪。\n" +
"默认 false 保持现有\"恒显\"行为,需要该玩法时再开启。")]
[SerializeField] private bool _requireLocatorForPlayerDot;
[Header("颜色Inspector 覆盖)")]
[SerializeField] private Color _colorExplored = Color.white;
[SerializeField] private Color _colorMapped = new Color(0.45f, 0.45f, 0.45f, 1f);
@@ -53,6 +59,12 @@ namespace BaseGames.World.Map
[SerializeField] private int[] _zoomLevels = { 2, 3, 5 }; // R12-FA 可用视野半径档位(格)
private int _zoomLevelIndex;
[Header("自动贴边(可选)")]
[Tooltip("勾选后,启用时把小地图定位到所在 Canvas 的右上角(按 _screenMargin 像素留边)。\n" +
"用于父节点非 RectTransform如普通 Transform 的 HUDRoot时锚定失效的情况保证运行时正确贴边。")]
[SerializeField] private bool _autoAnchorTopRight = true;
[SerializeField] private Vector2 _screenMargin = new Vector2(16f, 16f);
private IMapService _mapSvc;
private IPlayerPositionProvider _playerProvider;
private IPinService _pinService;
@@ -90,6 +102,8 @@ namespace BaseGames.World.Map
// 启动顺序兜底
SubscribeServices();
if (_autoAnchorTopRight) AnchorToCanvasTopRight();
// R10-N1/N2 应用关闭期间累积的状态变化
if (_databaseDirty)
{
@@ -142,6 +156,7 @@ namespace BaseGames.World.Map
{
_mapSvc.OnDatabaseChanged += OnDatabaseChanged;
_mapSvc.OnExplorationChanged += OnExplorationChanged;
_mapSvc.OnLocatorChanged += OnLocatorChanged;
}
}
_pinService ??= ServiceLocator.GetOrDefault<IPinService>();
@@ -163,6 +178,7 @@ namespace BaseGames.World.Map
{
_mapSvc.OnDatabaseChanged -= OnDatabaseChanged;
_mapSvc.OnExplorationChanged -= OnExplorationChanged;
_mapSvc.OnLocatorChanged -= OnLocatorChanged;
_mapSvc = null;
}
_pinService = null;
@@ -219,6 +235,13 @@ namespace BaseGames.World.Map
if (cell != null) cell.SetVisibility(_mapSvc.GetVisibility(id));
}
/// <summary>定位能力开关变化:重置 dirty 标记强制 UpdatePlayerDot 重新评估门控。</summary>
private void OnLocatorChanged()
{
_lastDotRoomId = null; // 绕过 UpdatePlayerDot 的 roomId/normPos 脏检查,确保门控状态立即生效
if (isActiveAndEnabled) UpdatePlayerDot();
}
/// <summary>数据库结构变更时完整重建:清空所有格子,下次 RefreshView 重新实例化。</summary>
private void OnDatabaseChanged()
{
@@ -386,6 +409,13 @@ namespace BaseGames.World.Map
{
if (_playerDot == null || _playerProvider == null) return;
// 定位门控:未启用定位能力时隐藏玩家点(由指南针护符解锁)
if (_requireLocatorForPlayerDot && (_mapSvc == null || !_mapSvc.IsLocatorEnabled))
{
_playerDot.enabled = false;
return;
}
var roomId = _playerProvider.CurrentRoomId;
var normPos = _playerProvider.NormalizedPositionInRoom;
@@ -429,5 +459,26 @@ namespace BaseGames.World.Map
_viewDirty = true;
}
}
// ── 自动贴边 ──────────────────────────────────────────────────────────
/// <summary>
/// 将小地图定位到所在 Canvas 的右上角pivot 设为右上position 设到画布右上角内缩 _screenMargin
/// 不依赖父节点为 RectTransform——直接用世界坐标定位规避父节点为普通 Transform 时锚定失效的问题。
/// </summary>
private void AnchorToCanvasTopRight()
{
var canvas = GetComponentInParent<Canvas>();
if (canvas == null) return;
if (canvas.transform is not RectTransform canvasRt) return;
if (transform is not RectTransform rt) return;
var corners = new Vector3[4];
canvasRt.GetWorldCorners(corners); // 0=BL, 1=TL, 2=TR, 3=BR
rt.pivot = new Vector2(1f, 1f);
rt.position = new Vector3(corners[2].x - _screenMargin.x,
corners[2].y - _screenMargin.y,
rt.position.z);
}
}
}