Files
2025-11-09 23:36:29 +08:00

244 lines
7.4 KiB
C#
Raw Permalink 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.
// PuzzleManager.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class PuzzleManager : MonoBehaviour
{
[Header("拼图设置")]
public Texture2D puzzleImage; // 拼图原图
public int gridSize = 3; // 网格大小3x3
public float spacing = 5f; // 拼图块间距
[Header("UI引用")]
public RectTransform puzzleArea; // 拼图区域
public Transform piecesContainer; // 拼图块容器
public TMP_Text completedText; // 完成提示文本
private List<PuzzlePiece> pieces = new List<PuzzlePiece>();
private PuzzlePiece emptyPiece; // 空白拼图块
private Vector2 pieceSize; // 拼图块尺寸
void Start()
{
CreatePuzzle();
ShufflePieces();
}
// 创建拼图
void CreatePuzzle()
{
// 计算拼图块尺寸
float areaWidth = puzzleArea.rect.width;
float areaHeight = puzzleArea.rect.height;
pieceSize = new Vector2(areaWidth / gridSize, areaHeight / gridSize);
// 创建拼图块
for (int row = 0; row < gridSize; row++)
{
for (int col = 0; col < gridSize; col++)
{
// 跳过最后一个位置(作为空白)
if (row == gridSize - 1 && col == gridSize - 1)
{
CreateEmptyPiece(row, col);
continue;
}
// 创建拼图块GameObject
GameObject pieceObj = new GameObject($"Piece_{row}_{col}");
pieceObj.transform.SetParent(piecesContainer);
// 添加Image组件
Image img = pieceObj.AddComponent<Image>();
// 设置拼图块纹理
Sprite sprite = CreateSpriteForPiece(row, col);
img.sprite = sprite;
// 设置位置和大小
RectTransform rt = pieceObj.GetComponent<RectTransform>();
rt.sizeDelta = pieceSize - Vector2.one * spacing;
rt.anchoredPosition = GetPiecePosition(row, col);
// 添加拼图块组件
PuzzlePiece piece = pieceObj.AddComponent<PuzzlePiece>();
piece.Initialize(this, row, col);
pieces.Add(piece);
// 添加按钮组件用于点击
Button btn = pieceObj.AddComponent<Button>();
btn.onClick.AddListener(() => OnPieceClick(piece));
}
}
completedText.gameObject.SetActive(false);
}
// 创建空白拼图块
void CreateEmptyPiece(int row, int col)
{
GameObject emptyObj = new GameObject("EmptyPiece");
emptyObj.transform.SetParent(piecesContainer);
// 设置位置
RectTransform rt = emptyObj.AddComponent<RectTransform>();
rt.sizeDelta = pieceSize - Vector2.one * spacing;
rt.anchoredPosition = GetPiecePosition(row, col);
emptyPiece = emptyObj.AddComponent<PuzzlePiece>();
emptyPiece.Initialize(this, row, col);
emptyPiece.isEmpty = true;
}
// 创建拼图块的Sprite
Sprite CreateSpriteForPiece(int row, int col)
{
// 计算在原图中的位置
int texWidth = puzzleImage.width / gridSize;
int texHeight = puzzleImage.height / gridSize;
// 创建纹理
Texture2D pieceTex = new Texture2D(texWidth, texHeight);
Color[] pixels = puzzleImage.GetPixels(
col * texWidth,
(gridSize - 1 - row) * texHeight,
texWidth,
texHeight
);
pieceTex.SetPixels(pixels);
pieceTex.Apply();
return Sprite.Create(
pieceTex,
new Rect(0, 0, texWidth, texHeight),
new Vector2(0.5f, 0.5f)
);
}
// 获取拼图块位置
Vector2 GetPiecePosition(int row, int col)
{
float startX = -puzzleArea.rect.width / 2 + pieceSize.x / 2;
float startY = puzzleArea.rect.height / 2 - pieceSize.y / 2;
return new Vector2(
startX + col * pieceSize.x,
startY - row * pieceSize.y
);
}
// 打乱拼图
void ShufflePieces()
{
int shuffleCount = 100;
for (int i = 0; i < shuffleCount; i++)
{
var adjacentPieces = GetAdjacentPieces(emptyPiece);
if (adjacentPieces.Count > 0)
{
int randomIndex = Random.Range(0, adjacentPieces.Count);
var targetPiece = adjacentPieces[randomIndex];
// 只交换空白块与相邻块
SwapPieces(targetPiece, emptyPiece);
}
}
}
// 获取相邻的拼图块
List<PuzzlePiece> GetAdjacentPieces(PuzzlePiece piece)
{
List<PuzzlePiece> adjacent = new List<PuzzlePiece>();
Vector2[] directions = { Vector2.up, Vector2.down, Vector2.left, Vector2.right };
foreach (Vector2 dir in directions)
{
PuzzlePiece adjacentPiece = GetPieceAtPosition(
piece.currentRow + (int)dir.y,
piece.currentCol + (int)dir.x
);
if (adjacentPiece != null)
{
adjacent.Add(adjacentPiece);
}
}
return adjacent;
}
// 点击拼图块
public void OnPieceClick(PuzzlePiece piece)
{
if (IsAdjacentToEmpty(piece))
{
SwapPieces(piece, emptyPiece);
if (CheckPuzzleComplete())
{
completedText.gameObject.SetActive(true);
}
}
}
// 检查是否与空白块相邻
bool IsAdjacentToEmpty(PuzzlePiece piece)
{
int rowDiff = Mathf.Abs(piece.currentRow - emptyPiece.currentRow);
int colDiff = Mathf.Abs(piece.currentCol - emptyPiece.currentCol);
return (rowDiff == 1 && colDiff == 0) || (rowDiff == 0 && colDiff == 1);
}
// 交换两个拼图块
void SwapPieces(PuzzlePiece piece1, PuzzlePiece piece2)
{
// 交换位置
Vector2 tempPos = piece1.GetComponent<RectTransform>().anchoredPosition;
piece1.GetComponent<RectTransform>().anchoredPosition =
piece2.GetComponent<RectTransform>().anchoredPosition;
piece2.GetComponent<RectTransform>().anchoredPosition = tempPos;
// 交换行列信息
int tempRow = piece1.currentRow;
int tempCol = piece1.currentCol;
piece1.currentRow = piece2.currentRow;
piece1.currentCol = piece2.currentCol;
piece2.currentRow = tempRow;
piece2.currentCol = tempCol;
}
// 获取指定位置的拼图块
PuzzlePiece GetPieceAtPosition(int row, int col)
{
if (row < 0 || row >= gridSize || col < 0 || col >= gridSize)
return null;
foreach (PuzzlePiece piece in pieces)
{
if (piece.currentRow == row && piece.currentCol == col)
return piece;
}
return emptyPiece.currentRow == row && emptyPiece.currentCol == col ? emptyPiece : null;
}
// 检查拼图是否完成
bool CheckPuzzleComplete()
{
foreach (PuzzlePiece piece in pieces)
{
if (piece.currentRow != piece.correctRow || piece.currentCol != piece.correctCol)
return false;
}
return emptyPiece.currentRow == gridSize - 1 && emptyPiece.currentCol == gridSize - 1;
}
}