113 lines
4.6 KiB
C#
113 lines
4.6 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace AibisDream
|
||
{
|
||
/// <summary>
|
||
/// 放置验证器实现
|
||
/// 负责验证形状是否可以放置在指定位置
|
||
/// </summary>
|
||
public class PlacementValidator : IPlacementValidator
|
||
{
|
||
/// <summary>
|
||
/// 检查形状是否可以放置在指定位置
|
||
/// </summary>
|
||
/// <param name="grid">网格系统</param>
|
||
/// <param name="shape">要放置的形状</param>
|
||
/// <param name="gridX">网格X坐标(形状左下角位置)</param>
|
||
/// <param name="gridY">网格Y坐标(形状左下角位置)</param>
|
||
/// <returns>放置验证结果</returns>
|
||
public PlacementResult CanPlace(IBlockPuzzleGrid grid, IBlockShape shape, int gridX, int gridY)
|
||
{
|
||
if (grid == null || shape == null)
|
||
{
|
||
return PlacementResult.InvalidPosition;
|
||
}
|
||
|
||
// 获取形状的所有格子位置(相对坐标,基于形状的本地坐标系)
|
||
Vector2Int[] blockPositions = shape.GetBlockPositions();
|
||
if (blockPositions == null || blockPositions.Length == 0)
|
||
{
|
||
return PlacementResult.InvalidPosition;
|
||
}
|
||
|
||
// 形状的坐标系统:
|
||
// - GetBlockPositions() 返回的坐标中,(0, 0) 是形状的左上角(在pattern数组中)
|
||
// - pattern[i, j] 中,i 是 x(从左到右),j 是 y(从上到下,j=0 是顶部)
|
||
// - gridX, gridY 是形状左下角在网格中的位置
|
||
// - 需要将形状的相对坐标转换为网格坐标
|
||
foreach (var blockPos in blockPositions)
|
||
{
|
||
// 将形状的相对坐标转换为网格坐标
|
||
// 形状的 (0, 0) 对应网格的 (gridX, gridY + shape.Height - 1)
|
||
// 形状的 (i, j) 对应网格的 (gridX + i, gridY + shape.Height - 1 - j)
|
||
int gridCellX = gridX + blockPos.x;
|
||
int gridCellY = gridY + shape.Height - 1 - blockPos.y;
|
||
|
||
// 检查是否超出边界
|
||
if (!grid.IsValidPosition(gridCellX, gridCellY))
|
||
{
|
||
return PlacementResult.OutOfBounds;
|
||
}
|
||
|
||
// 检查是否与已有块重叠
|
||
if (!grid.IsCellEmpty(gridCellX, gridCellY))
|
||
{
|
||
return PlacementResult.Overlap;
|
||
}
|
||
}
|
||
|
||
return PlacementResult.Success;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查形状是否可以放置在指定位置(详细版本)
|
||
/// </summary>
|
||
/// <param name="grid">网格系统</param>
|
||
/// <param name="shape">要放置的形状</param>
|
||
/// <param name="gridX">网格X坐标(形状左下角位置)</param>
|
||
/// <param name="gridY">网格Y坐标(形状左下角位置)</param>
|
||
/// <param name="failureReason">失败原因(如果返回false)</param>
|
||
/// <returns>是否可以放置</returns>
|
||
public bool CanPlaceDetailed(IBlockPuzzleGrid grid, IBlockShape shape, int gridX, int gridY, out PlacementResult failureReason)
|
||
{
|
||
failureReason = CanPlace(grid, shape, gridX, gridY);
|
||
return failureReason == PlacementResult.Success;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取形状在指定位置的所有占用格子坐标
|
||
/// </summary>
|
||
/// <param name="shape">形状</param>
|
||
/// <param name="gridX">网格X坐标(形状左下角位置)</param>
|
||
/// <param name="gridY">网格Y坐标(形状左下角位置)</param>
|
||
/// <returns>占用格子的网格坐标数组</returns>
|
||
public (int x, int y)[] GetOccupiedCells(IBlockShape shape, int gridX, int gridY)
|
||
{
|
||
if (shape == null)
|
||
{
|
||
return new (int x, int y)[0];
|
||
}
|
||
|
||
Vector2Int[] blockPositions = shape.GetBlockPositions();
|
||
if (blockPositions == null || blockPositions.Length == 0)
|
||
{
|
||
return new (int x, int y)[0];
|
||
}
|
||
|
||
List<(int x, int y)> occupiedCells = new List<(int x, int y)>();
|
||
|
||
foreach (var blockPos in blockPositions)
|
||
{
|
||
// 将形状的相对坐标转换为网格坐标(左下角为基准)
|
||
int gridCellX = gridX + blockPos.x;
|
||
int gridCellY = gridY + shape.Height - 1 - blockPos.y;
|
||
occupiedCells.Add((gridCellX, gridCellY));
|
||
}
|
||
|
||
return occupiedCells.ToArray();
|
||
}
|
||
}
|
||
}
|
||
|