using UnityEngine; namespace AibisDream { /// /// BlockPuzzle网格组件 /// 实现IBlockPuzzleGrid接口,管理整个游戏网格的状态和操作 /// public class BlockPuzzleGrid : MonoBehaviour, IBlockPuzzleGrid { [Header("网格设置")] [SerializeField] private int width = 10; [SerializeField] private int height = 10; [SerializeField] private float cellSize = 1f; [SerializeField] private bool initializeOnStart = true; [Header("编辑器预览设置")] [SerializeField] private bool showGizmos = true; [SerializeField] private Color gridLineColor = new Color(0.5f, 0.5f, 0.5f, 0.8f); [SerializeField] private Color emptyCellColor = new Color(0.9f, 0.9f, 0.9f, 0.2f); [SerializeField] private Color occupiedCellColor = new Color(0.2f, 0.6f, 1f, 0.5f); [SerializeField] private bool showCellStates = true; private GridCellState[,] _grid; private bool _isInitialized = false; // IBlockPuzzleGrid 接口实现 public int Width { get; private set; } public int Height { get; private set; } public float CellSize { get; private set; } public Vector3 Origin { get; private set; } private void Start() { if (initializeOnStart) { Initialize(width, height, cellSize, transform.position); } } /// /// 初始化网格 /// public void Initialize(int width, int height, float cellSize, Vector3 origin) { if (width <= 0 || height <= 0) { Debug.LogError($"BlockPuzzleGridComponent: 无效的网格尺寸 {width}x{height}"); return; } if (cellSize <= 0) { Debug.LogError($"BlockPuzzleGridComponent: 无效的单元格大小 {cellSize}"); return; } this.width = width; this.height = height; this.cellSize = cellSize; Width = width; Height = height; CellSize = cellSize; Origin = origin; _grid = new GridCellState[width, height]; _isInitialized = true; Clear(); } /// /// 使用Inspector中的参数初始化网格 /// public void Initialize() { Initialize(width, height, cellSize, transform.position); } /// /// 重新初始化网格(使用新的参数) /// public void Reinitialize(int newWidth, int newHeight, float newCellSize) { Initialize(newWidth, newHeight, newCellSize, transform.position); } public GridCellState GetCellState(int x, int y) { if (!_isInitialized) { Debug.LogWarning("BlockPuzzleGridComponent: 网格未初始化"); return GridCellState.Empty; } if (!IsValidPosition(x, y)) { Debug.LogWarning($"BlockPuzzleGridComponent: 尝试访问无效位置 ({x}, {y})"); return GridCellState.Empty; } return _grid[x, y]; } public void SetCellState(int x, int y, GridCellState state) { if (!_isInitialized) { Debug.LogWarning("BlockPuzzleGridComponent: 网格未初始化"); return; } if (!IsValidPosition(x, y)) { Debug.LogWarning($"BlockPuzzleGridComponent: 尝试设置无效位置 ({x}, {y})"); return; } _grid[x, y] = state; } public bool IsValidPosition(int x, int y) { return _isInitialized && x >= 0 && x < Width && y >= 0 && y < Height; } public bool IsCellEmpty(int x, int y) { return IsValidPosition(x, y) && GetCellState(x, y) == GridCellState.Empty; } public bool WorldToGrid(Vector3 worldPos, out int gridX, out int gridY) { if (!_isInitialized) { gridX = 0; gridY = 0; return false; } Vector3 localPos = worldPos - Origin; gridX = Mathf.FloorToInt(localPos.x / CellSize); gridY = Mathf.FloorToInt(localPos.y / CellSize); // 检查是否在有效范围内 if (!IsValidPosition(gridX, gridY)) { return false; } return true; } public Vector3 GridToWorld(int gridX, int gridY) { if (!_isInitialized) { return transform.position; } // 返回单元格中心的世界坐标 float worldX = Origin.x + (gridX + 0.5f) * CellSize; float worldY = Origin.y + (gridY + 0.5f) * CellSize; return new Vector3(worldX, worldY, Origin.z); } public Vector3[] GridVerticesToWorld(int x, int y) { if (!_isInitialized) { return new Vector3[4]; } // 先获取网格中心位置 Vector3 center = GridToWorld(x, y); // 然后获取网格四个顶点位置 Vector3[] vertices = new Vector3[4]; vertices[0] = center + new Vector3(-CellSize / 2, -CellSize / 2, 0); vertices[1] = center + new Vector3(CellSize / 2, -CellSize / 2, 0); vertices[2] = center + new Vector3(CellSize / 2, CellSize / 2, 0); vertices[3] = center + new Vector3(-CellSize / 2, CellSize / 2, 0); return vertices; } public void Clear() { if (!_isInitialized || _grid == null) return; for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { _grid[x, y] = GridCellState.Empty; } } } public int GetOccupiedCount() { if (!_isInitialized || _grid == null) return 0; int count = 0; for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (_grid[x, y] == GridCellState.Occupied) { count++; } } } return count; } public int GetTotalCellCount() { return Width * Height; } /// /// 检查网格是否已初始化 /// public bool IsInitialized() { return _isInitialized; } private void OnValidate() { // 确保参数有效 width = Mathf.Max(1, width); height = Mathf.Max(1, height); cellSize = Mathf.Max(0.1f, cellSize); } /// /// 在编辑器中绘制网格预览 /// private void OnDrawGizmos() { if (!showGizmos) return; // 使用当前Inspector中的参数或已初始化的参数 int drawWidth = _isInitialized ? Width : width; int drawHeight = _isInitialized ? Height : height; float drawCellSize = _isInitialized ? CellSize : cellSize; Vector3 drawOrigin = _isInitialized ? Origin : transform.position; if (drawWidth <= 0 || drawHeight <= 0 || drawCellSize <= 0) return; // 绘制网格线 Gizmos.color = gridLineColor; for (int x = 0; x <= drawWidth; x++) { Vector3 start = drawOrigin + new Vector3(x * drawCellSize, 0, 0); Vector3 end = drawOrigin + new Vector3(x * drawCellSize, drawHeight * drawCellSize, 0); Gizmos.DrawLine(start, end); } for (int y = 0; y <= drawHeight; y++) { Vector3 start = drawOrigin + new Vector3(0, y * drawCellSize, 0); Vector3 end = drawOrigin + new Vector3(drawWidth * drawCellSize, y * drawCellSize, 0); Gizmos.DrawLine(start, end); } // 绘制单元格状态(如果已初始化且启用) if (showCellStates && _isInitialized && _grid != null) { float cellDisplaySize = drawCellSize * 0.9f; // 稍微小一点,留出网格线空间 Vector3 cellSizeVec = new Vector3(cellDisplaySize, cellDisplaySize, 0.01f); for (int x = 0; x < drawWidth; x++) { for (int y = 0; y < drawHeight; y++) { if (IsValidPosition(x, y)) { Vector3 cellCenter = GridToWorld(x, y); GridCellState state = GetCellState(x, y); Gizmos.color = state == GridCellState.Occupied ? occupiedCellColor : emptyCellColor; Gizmos.DrawCube(cellCenter, cellSizeVec); } } } } } /// /// 选中时绘制更明显的网格边界 /// private void OnDrawGizmosSelected() { if (!showGizmos) return; // 使用当前Inspector中的参数或已初始化的参数 int drawWidth = _isInitialized ? Width : width; int drawHeight = _isInitialized ? Height : height; float drawCellSize = _isInitialized ? CellSize : cellSize; Vector3 drawOrigin = _isInitialized ? Origin : transform.position; if (drawWidth <= 0 || drawHeight <= 0 || drawCellSize <= 0) return; // 绘制网格边界(更粗的线) Gizmos.color = new Color(gridLineColor.r, gridLineColor.g, gridLineColor.b, 1f); Vector3 bottomLeft = drawOrigin; Vector3 bottomRight = drawOrigin + new Vector3(drawWidth * drawCellSize, 0, 0); Vector3 topLeft = drawOrigin + new Vector3(0, drawHeight * drawCellSize, 0); Vector3 topRight = drawOrigin + new Vector3(drawWidth * drawCellSize, drawHeight * drawCellSize, 0); // 绘制边界框 Gizmos.DrawLine(bottomLeft, bottomRight); Gizmos.DrawLine(bottomRight, topRight); Gizmos.DrawLine(topRight, topLeft); Gizmos.DrawLine(topLeft, bottomLeft); // 绘制原点标记 Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(drawOrigin, 0.1f); } } }