Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/PlacementValidator.cs
T
2025-11-27 18:14:24 +08:00

113 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}