Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/BlockPuzzleGrid.cs
T
2025-12-16 20:08:11 +08:00

280 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AibisDream
{
/// <summary>
/// BlockPuzzle网格组件
/// 实现IBlockPuzzleGrid接口,管理整个游戏网格的状态和操作
/// </summary>
public class BlockPuzzleGrid : MonoBehaviour, IBlockPuzzleGrid
{
[Header("编辑器预览设置")]
[SerializeField] public int width = 10;
[SerializeField] public int height = 10;
[SerializeField] public float cellSize = 1f;
[SerializeField] private bool showCellStates = true;
private GridCellState[,] _grid;
private GridCellState[,] _previewGrid;
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 => transform.position;
public GridVisualizer GridVisualizer { get; private set; }
public Dictionary<BlockShape, GridShapeData> ShapeDict { get; private set; }
public event Action OnShapePlaced;
/// <summary>
/// 初始化编辑器预览
/// </summary>
public void InitializeInEditor(int newWidth, int newHeight, float newCellSize)
{
width = newWidth;
height = newHeight;
cellSize = newCellSize;
Width = width;
Height = height;
CellSize = cellSize;
_grid = new GridCellState[width, height];
_isInitialized = true;
ShapeDict = new Dictionary<BlockShape, GridShapeData>();
GridVisualizer = GetComponent<GridVisualizer>();
Debug.Log($"BlockPuzzleGridComponent: 初始化编辑器预览 {Width}x{Height} {CellSize}");
}
/// <summary>
/// 初始化网格
/// </summary>
public void Initialize(int width, int height, float cellSize)
{
if (width <= 0 || height <= 0)
{
Debug.LogError($"BlockPuzzleGridComponent: 无效的网格尺寸 {width}x{height}");
return;
}
if (cellSize <= 0)
{
Debug.LogError($"BlockPuzzleGridComponent: 无效的单元格大小 {cellSize}");
return;
}
Width = width;
Height = height;
CellSize = cellSize;
_grid = new GridCellState[width, height];
_previewGrid = new GridCellState[width, height];
_isInitialized = true;
ShapeDict = new Dictionary<BlockShape, GridShapeData>();
GridVisualizer = GetComponent<GridVisualizer>();
GridVisualizer.Init(this);
}
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.OutOfBounds;
}
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 GridCellState GetPreviewCellState(int x, int y)
{
if (!_isInitialized)
{
Debug.LogWarning("BlockPuzzleGridComponent: 网格未初始化");
return GridCellState.Empty;
}
if (!IsValidPosition(x, y))
{
Debug.LogWarning($"BlockPuzzleGridComponent: 尝试访问无效位置 ({x}, {y})");
return GridCellState.OutOfBounds;
}
return _previewGrid[x, y];
}
public void SetPreviewCellState(int x, int y, GridCellState state)
{
if (!_isInitialized)
{
Debug.LogWarning("BlockPuzzleGridComponent: 网格未初始化");
return;
}
if (!IsValidPosition(x, y))
{
Debug.LogWarning($"BlockPuzzleGridComponent: 尝试设置无效位置 ({x}, {y})");
return;
}
_previewGrid[x, y] = state;
}
public void ResetPreviewGrid()
{
Array.Clear(_previewGrid, 0, _previewGrid.Length);
}
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 CanPlace(Vector2Int[] gridCells)
{
for (int i = 0; i < gridCells.Length; i++)
{
// 先验证是否在有效范围内
if (!IsValidPosition(gridCells[i].x, gridCells[i].y))
{
return false;
}
// 再验证是否为空
else if (GetCellState(gridCells[i].x, gridCells[i].y) == GridCellState.Occupied)
{
return false;
}
}
return true;
}
public bool WorldToGrid(Vector3 worldPos, out int gridX, out int gridY)
{
Vector3 localPos = worldPos - Origin;
gridX = Mathf.FloorToInt(localPos.x / CellSize);
gridY = Mathf.FloorToInt(localPos.y / CellSize);
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()
{
_grid = new GridCellState[Width, Height];
_isInitialized = false;
ShapeDict?.Clear();
}
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;
}
/// <summary>
/// 检查网格是否已初始化
/// </summary>
public bool IsInitialized()
{
return _isInitialized;
}
public List<BlockShape> GetShapes()
{
return ShapeDict.Keys.ToList();
}
private void OnDestroy()
{
OnShapePlaced = null;
}
}
}