地图系统
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user