1413 lines
51 KiB
C#
1413 lines
51 KiB
C#
// 渲染游戏板
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using asap.core;
|
||
using asap.core.common;
|
||
using DG.Tweening;
|
||
using EventBlocks.UI;
|
||
using EventCubeMelt.Data;
|
||
using EventCubeMelt.UI;
|
||
using EventCubeMelt.Utils;
|
||
using Game;
|
||
using UnityEngine;
|
||
using UnityEngine.Serialization;
|
||
using UnityEngine.UI;
|
||
using Debug = UnityEngine.Debug;
|
||
using Quaternion = UnityEngine.Quaternion;
|
||
using Vector2 = UnityEngine.Vector2;
|
||
using Vector3 = UnityEngine.Vector3;
|
||
|
||
namespace EventCubeMelt
|
||
{
|
||
/// <summary>
|
||
/// 新手引导「落子判定」在棋盘上的 Ghost 格(行/列与 <see cref="TetrisBoardData"/> 一致)。
|
||
/// </summary>
|
||
[Serializable]
|
||
public struct NewGuideGhostCheckCell
|
||
{
|
||
public int row;
|
||
public int col;
|
||
}
|
||
|
||
public class BoardRenderer : MonoBehaviour
|
||
{
|
||
#region 组件引用
|
||
|
||
[Header("预制体")] [SerializeField] private GameObject _cellPrefab;
|
||
[SerializeField] private GameObject _ghostCellPrefab;
|
||
[SerializeField] private GameObject _emptyCellPrefab;
|
||
|
||
//-
|
||
[SerializeField] private RectTransform bgTransform;
|
||
|
||
|
||
[SerializeField] private float boardPadding = 35f;
|
||
// [SerializeField] private float cellSpacing = 0.1f;
|
||
[SerializeField] private Transform _boardContainer;
|
||
[SerializeField] private Transform _ghostContainer;
|
||
|
||
[SerializeField] private PieceRenderer[] cellPiece; // 当前的Piece
|
||
|
||
[SerializeField]
|
||
private float putBeforeDisappearDuration = 0.2f;
|
||
|
||
|
||
//- 消除特效
|
||
[SerializeField] private Transform fxUIEventCubemeltEliminatable;
|
||
// 整行消除特效
|
||
[SerializeField] private Transform fxUIEventCubeMeltDisappear;
|
||
[SerializeField] private Transform fxUIEventCubeMeltColDisappear;
|
||
|
||
[SerializeField] private Transform fxUIEventCubeMeltDisappear6;
|
||
[SerializeField] private Transform fxUIEventCubeMeltColDisappear6;
|
||
|
||
[SerializeField] private Transform fxUIEventCubeMeltDisappear7;
|
||
[SerializeField] private Transform fxUIEventCubeMeltColDisappear7;
|
||
|
||
|
||
[Header("三行和三列消除特效")]
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorful;
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorfulVertical;
|
||
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorful6;
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorfulVertical6;
|
||
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorful7;
|
||
[SerializeField] private Transform fxUIEventCubemeltDisappearColorfulVertical7;
|
||
|
||
|
||
[Header("跳字特效")]
|
||
[SerializeField] private Transform fxInfoPiercing;
|
||
|
||
|
||
// 飞行的对象Controller
|
||
[Header("飞行特效")]
|
||
[SerializeField]
|
||
private RewardFlyBatchController _rewardFlyBatchCtrl;
|
||
//
|
||
[SerializeField]
|
||
private BatchedRewardFly _rewardFly;
|
||
|
||
|
||
|
||
[Header("延时")]
|
||
[SerializeField]
|
||
private float bombStartDelay = 0.2f;
|
||
[SerializeField]
|
||
private float bombFlyDelay = 0.2f;
|
||
|
||
// [SerializeField] private Transform fxUIEventCubemeltBroke;
|
||
|
||
[Header("新手引导")]
|
||
[Tooltip("NewGuide1:放手时需被 Ghost 覆盖的棋盘格;在 Inspector 中填写行/列,长度 0 则判定始终失败")]
|
||
[SerializeField]
|
||
private NewGuideGhostCheckCell[] _newGuide1GhostCheckCells =
|
||
{
|
||
new NewGuideGhostCheckCell { row = 0, col = 3 },
|
||
new NewGuideGhostCheckCell { row = 1, col = 3 },
|
||
new NewGuideGhostCheckCell { row = 1, col = 2 },
|
||
new NewGuideGhostCheckCell { row = 0, col = 2 },
|
||
};
|
||
|
||
#endregion
|
||
|
||
#region 私有成员
|
||
|
||
private TetrisBoardData _boardData;
|
||
private CellRenderer[,] _cellRenderers;
|
||
private GameObject[,] _emptyCellObjs;
|
||
private Dictionary<CellType, Material> _materialCache = new();
|
||
|
||
// 特效Trans
|
||
private Transform effectTrans;
|
||
|
||
// 对象池
|
||
//
|
||
// private readonly Queue<CellRenderer> _cellPool = new();
|
||
|
||
// 当前活跃的Cell
|
||
private readonly List<CellRenderer> _activeCells = new();
|
||
|
||
// 特效对象池
|
||
private IObjectPoolService _objectPoolService;
|
||
|
||
private IObjectPool _lineEffectPool;
|
||
|
||
// 特效消除池
|
||
private IObjectPool _disappearEffectRowPool;
|
||
private IObjectPool _disappearEffectColPool;
|
||
|
||
// 当前渲染隐藏
|
||
private readonly List<CellRenderer> _ghostCells = new();
|
||
private EventCubeMeltManager _thisEventManager;
|
||
private EventCubeMeltData _thisEventData;
|
||
|
||
|
||
public float TargetCellSize { get; set; } = 100;
|
||
|
||
// private Vector2 _cellSize;
|
||
// private Vector2 _cellSpace;
|
||
|
||
private float _contentWidth;
|
||
private float _contentHeight;
|
||
private Vector2 _contentZero;
|
||
|
||
|
||
|
||
// private float TargetCellSpace { get; set; } = 3f;
|
||
|
||
|
||
#endregion
|
||
|
||
#region 周期函数
|
||
|
||
private void Awake()
|
||
{
|
||
effectTrans = transform.Find("EffectPanel");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 初始化
|
||
|
||
//
|
||
public void Initialize(int height, int width, List<int> boardData)
|
||
{
|
||
ELog($"Initialize -> {height} {width}");
|
||
|
||
_objectPoolService = GContext.container.Resolve<IObjectPoolService>();
|
||
_lineEffectPool = _objectPoolService.CreatePool(fxUIEventCubemeltEliminatable, 0, 32);
|
||
_disappearEffectRowPool = _objectPoolService.CreatePool(fxUIEventCubeMeltDisappear, 0, 32);
|
||
_disappearEffectColPool = _objectPoolService.CreatePool(fxUIEventCubeMeltColDisappear, 0, 32);
|
||
|
||
_thisEventManager = GContext.container.Resolve<EventCubeMeltManager>();
|
||
_thisEventData = _thisEventManager.EventData;
|
||
_boardData = new TetrisBoardData(height, width);
|
||
_boardData.LoadData(boardData);
|
||
CreateGrid();
|
||
UpdateBgSize(height, width);
|
||
}
|
||
|
||
|
||
private void UpdateBgSize(int height, int width)
|
||
{
|
||
ELog("UpdateBgSize -> ");
|
||
var layoutGroup = _boardContainer.GetComponent<GridLayoutGroup>();
|
||
var cellSize = layoutGroup.cellSize;
|
||
var spacing = layoutGroup.spacing;
|
||
|
||
// _cellSize = cellSize;
|
||
// _cellSpace = spacing;
|
||
|
||
// var topLeft = -(cellSize.x + spacing.x) * width * 0.5;
|
||
_contentWidth = cellSize.x * width + spacing.x * (width - 1);
|
||
_contentHeight = cellSize.y * height + spacing.y * (height - 1);
|
||
_contentZero = new Vector2(-_contentWidth * 0.5f, _contentHeight* 0.5f);
|
||
|
||
bgTransform.sizeDelta = new Vector2(width * (cellSize.x + spacing.x) + boardPadding * 2 , height * (cellSize.y + spacing.y) + boardPadding * 2);
|
||
}
|
||
|
||
private void CreateGrid()
|
||
{
|
||
ELog("CreateGrid -> ");
|
||
// 清空现有网格
|
||
foreach (Transform child in _boardContainer)
|
||
Destroy(child.gameObject);
|
||
foreach (Transform child in _ghostContainer)
|
||
Destroy(child.gameObject);
|
||
|
||
// 创建网格单元
|
||
_cellRenderers = new CellRenderer[_boardData.Height, _boardData.Width];
|
||
_emptyCellObjs = new GameObject[_boardData.Height, _boardData.Width];
|
||
|
||
for (var row = 0; row < _boardData.Height; row++)
|
||
{
|
||
for (var col = 0; col < _boardData.Width; col++)
|
||
{
|
||
var position = Vector3.zero;
|
||
CreateCell(row, col, position);
|
||
// 创建影子单元格
|
||
CreateEmptyCell(row, col, position);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CreateCell(int row, int col, Vector3 position)
|
||
{
|
||
// var parent = isGhost ? _ghostContainer : _boardContainer;
|
||
// var cellName = isGhost ? $"GhostCell_{row}_{col}" : $"Cell_{row}_{col}";
|
||
var parent = _boardContainer;
|
||
var cellName = $"Cell_{row}_{col}";
|
||
|
||
GameObject cellObj;
|
||
// if (_cellPool.Count > 0)
|
||
// {
|
||
// cellObj = _cellPool.Dequeue().gameObject;
|
||
// cellObj.name = cellName;
|
||
// cellObj.transform.position = position;
|
||
// cellObj.transform.parent = parent;
|
||
// cellObj.SetActive(true);
|
||
// }
|
||
// else
|
||
{
|
||
cellObj = Instantiate(_cellPrefab, position, Quaternion.identity, parent);
|
||
cellObj.name = cellName;
|
||
}
|
||
|
||
var cellRenderer = cellObj.GetComponent<CellRenderer>();
|
||
if (!cellRenderer)
|
||
cellRenderer = cellObj.AddComponent<CellRenderer>();
|
||
|
||
// 没什么用
|
||
// 初始化单元格大小
|
||
// cellRenderer.SetSize(_cellSize);
|
||
// if (isGhost)
|
||
// {
|
||
// _ghostRenderers[row, col] = cellRenderer;
|
||
// // cellRenderer.SetMaterial(_materialCache[CellType.Ghost]);
|
||
// }
|
||
// else
|
||
// {
|
||
// _cellRenderers[row, col] = cellRenderer;
|
||
// // cellRenderer.SetMaterial(_gridMaterial);
|
||
// // cellRenderer.SetColor(_gridColor);
|
||
// }
|
||
|
||
_cellRenderers[row, col] = cellRenderer;
|
||
cellRenderer.Row = row;
|
||
cellRenderer.Col = col;
|
||
|
||
// _activeCells.Add(cellRenderer);
|
||
}
|
||
|
||
private void CreateEmptyCell(int row, int col, Vector3 position)
|
||
{
|
||
var parent = _ghostContainer;
|
||
var cellName = $"Empty_{row}_{col}";
|
||
|
||
var cellObj = Instantiate(_emptyCellPrefab, position, Quaternion.identity, parent);
|
||
cellObj.name = cellName;
|
||
|
||
_emptyCellObjs[row, col] = cellObj;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 更新渲染
|
||
|
||
public void UpdateBoard()
|
||
{
|
||
ELog("UpdateBoard-> ");
|
||
|
||
if (_boardData.ReSizeWithData(_thisEventData.BoardViewSize.y , _thisEventData.BoardViewSize.x , _thisEventData.BoardData))
|
||
{
|
||
RemakeBoard();
|
||
}
|
||
UpdateGridCells();
|
||
|
||
}
|
||
|
||
private void RemakeBoard()
|
||
{
|
||
ELog("ReMakeBoard-> ");
|
||
UpdateBgSize(_boardData.Height, _boardData.Width);
|
||
CreateGrid();
|
||
}
|
||
|
||
public void ClearBoard()
|
||
{
|
||
for (var row = 0; row < _boardData.Height; row++)
|
||
{
|
||
for (var col = 0; col < _boardData.Width; col++)
|
||
{
|
||
var cellRenderer = _cellRenderers[row, col];
|
||
cellRenderer.UpdateVisual(CellType.Empty);
|
||
}
|
||
}
|
||
}
|
||
|
||
//-
|
||
public void UpdateBoardWithAnim(Sequence sequence,float scaleDuration,float delayBetweenCells,out float delay)
|
||
{
|
||
ELog("UpdateBoardWithAnim");
|
||
|
||
UpdateBoard();
|
||
|
||
// _boardData.SetSize();
|
||
// _boardData.LoadData(_thisEventData?.BoardData);
|
||
// UpdateGridCells();
|
||
|
||
delay = 0;
|
||
|
||
|
||
var animationSequence = sequence;
|
||
var hasIndex = 0;
|
||
for (var row = 0; row < _boardData.Height; row++)
|
||
{
|
||
var has = false;
|
||
for (var col = 0; col < _boardData.Width; col++)
|
||
{
|
||
var cellType = _boardData[row, col];
|
||
var cell = _cellRenderers[row, col];
|
||
if (cellType != CellType.Empty)
|
||
{
|
||
cell.transform.localScale = Vector3.zero;
|
||
animationSequence.Insert(delay, cell.transform.DOScale(1.0f, scaleDuration)
|
||
.SetEase(Ease.OutBack)); // 使用弹性缓动效果,看起来更自然
|
||
has = true;
|
||
}
|
||
}
|
||
if (has)
|
||
{
|
||
hasIndex++;
|
||
delay = (hasIndex)* delayBetweenCells;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void UpdateGridCells()
|
||
{
|
||
ELog("UpdateGridCells-> ");
|
||
// _activeCells.Clear();
|
||
for (var row = 0; row < _boardData.Height; row++)
|
||
{
|
||
for (var col = 0; col < _boardData.Width; col++)
|
||
{
|
||
var cellType = _boardData[row, col];
|
||
var cellRenderer = _cellRenderers[row, col];
|
||
cellRenderer.UpdateVisual(cellType,_boardData.GetGridValue(row,col-1),_boardData.GetGridValue(row +1,col - 1) ,_boardData.GetGridValue(row +1,col ));
|
||
}
|
||
}
|
||
}
|
||
//
|
||
[Header("清除特效时长")]
|
||
[SerializeField]
|
||
private float disappearTimeDuration = 1f;
|
||
private async Task DoGridClearAndAnims(List<int> rows,
|
||
List<int> cols,
|
||
List<(int row,int col,int value,int newRow,int newCol)> listBombs)
|
||
{
|
||
ELog("DoGridClearAndAnims-> ");
|
||
|
||
var list = new List<Task>();
|
||
|
||
var countClear = rows.Count + cols.Count;
|
||
|
||
foreach (var row in rows)
|
||
{
|
||
list.Add(DoRowDisappearEffect(row,countClear,listBombs));
|
||
}
|
||
//ClearCol
|
||
foreach (var col in cols)
|
||
{
|
||
list.Add(DoColDisappearEffect(col,countClear,listBombs));
|
||
}
|
||
|
||
if (rows.Count + cols.Count > 0)
|
||
{
|
||
GContext.Publish(new EventUISound("audio_ui_block_cube_clear"));
|
||
}
|
||
await Task.WhenAll(list);
|
||
RemoveDisappearEffect();
|
||
}
|
||
|
||
private async Task DoColDisappearEffect(int col,int count,List<(int row,int col,int value,int newRow,int newCol)> listBombs)
|
||
{
|
||
await Awaiters.NextFrame;
|
||
var list = new List<Task>();
|
||
list.Add(AddColDisappearEffect(col, count ));
|
||
|
||
var ls = listBombs.Select(item => (item.row, item.col)).ToList();
|
||
for (var i = 0; i< _boardData.Height; i++)
|
||
{
|
||
var cellRenderer = _cellRenderers[i,col];
|
||
// _ = cellRenderer.RunClearAnimation(_boardData.Height - i ,count >= 3);
|
||
if (!ls.Contains((i, col)))
|
||
{
|
||
// list.Add(cellRenderer.RunBombAnimation(_boardData.Height - i,true,2f));
|
||
// }
|
||
// else
|
||
// {
|
||
list.Add(cellRenderer.RunClearAnimation(_boardData.Height - i ,count >= 3));
|
||
}
|
||
}
|
||
|
||
|
||
await Task.WhenAll(list);
|
||
}
|
||
|
||
private async Task DoRowDisappearEffect(int row,int count,List<(int row,int col,int value,int newRow,int newCol)> listBombs)
|
||
{
|
||
await Awaiters.NextFrame;
|
||
var list = new List<Task>();
|
||
|
||
list.Add(AddRowDisappearEffect(row, count));
|
||
var ls = listBombs.Select(item => (item.row, item.col)).ToList();
|
||
for (var i = 0; i< _boardData.Width; i++)
|
||
{
|
||
var cellRenderer = _cellRenderers[row, i];
|
||
if (!ls.Contains((row, i)))
|
||
{
|
||
list.Add(cellRenderer.RunClearAnimation(i, count >= 3));
|
||
}
|
||
}
|
||
|
||
await Task.WhenAll(list);
|
||
}
|
||
|
||
|
||
private bool TryScreenToGrid(Vector2 screenPos, out Vector2Int grid)
|
||
{
|
||
|
||
var canvas = GetComponentInParent<Canvas>();
|
||
var boardRT = (RectTransform)_boardContainer;
|
||
var cam = canvas.worldCamera;
|
||
|
||
grid = default;
|
||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(boardRT, screenPos, cam, out var local))
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (visualCell)
|
||
visualCell.SetActive(false);
|
||
#endif
|
||
return false;
|
||
}
|
||
|
||
// RectTransformUtility.ScreenPointToLocalPointInRectangle(boardRT, new Vector2(0,0), cam,out var p2);
|
||
// RectTransformUtility.ScreenPointToLocalPointInRectangle(boardRT, new Vector2(100,100), cam,out var p3);
|
||
|
||
ELog($"TryScreenToGrid -> {screenPos} {local}");
|
||
|
||
// var rect = boardRT.rect;
|
||
// ELog($"rect -> {rect.width}x{rect.height}");
|
||
// /var topLeft = new Vector2(-rect.width * 0.5f, rect.height * 0.5f);
|
||
var topLeft = _contentZero;
|
||
// 将 local 改为以左上为原点、向右向下为正的坐标
|
||
var p = new Vector2(local.x - topLeft.x, topLeft.y - local.y);
|
||
|
||
|
||
|
||
|
||
#if UNITY_EDITOR
|
||
if (visualCell != null)
|
||
{
|
||
// var localFromP = new Vector2(topLeft.x + p.x, topLeft.y - p.y);
|
||
// visualCell.transform.localPosition = local;
|
||
// visualCell.SetActive(true);
|
||
}
|
||
#endif
|
||
|
||
// var px = rect.width / _boardData.Width;
|
||
// var py = rect.height / _boardData.Height;
|
||
|
||
// var cellSize = new Vector2(100,100);
|
||
var cellSize = new Vector2(_contentWidth / _boardData.Width, _contentHeight / _boardData.Height);
|
||
var px = p.x / cellSize.x ;
|
||
var py = p.y / cellSize.y;
|
||
|
||
var x = Mathf.FloorToInt(px);
|
||
var y = Mathf.FloorToInt(py);
|
||
|
||
// ELog($"TryScreenToGrid -> zero = {p.x } {p.y} : {px} {py} : {x} {y}");
|
||
|
||
grid = new Vector2Int(x, y);
|
||
|
||
// return x >= 0 && x < _boardData.Width && y >= 0 && y < _boardData.Height;
|
||
return true;
|
||
}
|
||
|
||
public void UpdateVisual(PieceRenderer pieceRenderer, Vector2 screenPos)
|
||
{
|
||
// ELog($"UpdateVisual -> {pieceRenderer}");
|
||
var bRet = CanGetNewGhostGrid(pieceRenderer);
|
||
// ELog($"UpdateVisual ->{bRet}");
|
||
if (!bRet)
|
||
{
|
||
return;
|
||
}
|
||
// 显示
|
||
RemoveLineEffect();
|
||
RemoveDisappearEffect();
|
||
if (IsCanPlaceDown(pieceRenderer))
|
||
{
|
||
foreach (var cell in _ghostCells)
|
||
{
|
||
cell.UpdateGhostVisual();
|
||
}
|
||
AddClearEffects();
|
||
}
|
||
ELog($"UpdateVisual ->End");
|
||
}
|
||
|
||
public void ClearGhostGrid(bool placed = false)
|
||
{
|
||
if (_ghostCells is not { Count: > 0 })
|
||
{
|
||
return;
|
||
}
|
||
|
||
foreach (var cell in _ghostCells)
|
||
{
|
||
cell.UpdateVisual(CellType.Empty);
|
||
}
|
||
|
||
|
||
|
||
_ghostCells.Clear();
|
||
_boardData.ClearGhostGrid();
|
||
}
|
||
|
||
public GameObject visualCell;
|
||
|
||
|
||
private bool CanGetNewGhostGrid(PieceRenderer pieceRenderer)
|
||
{
|
||
//
|
||
var zeroPos = pieceRenderer.GetPiecePosition();
|
||
if (!TryScreenToGrid(zeroPos, out var grid))
|
||
{
|
||
ClearGhostGrid();
|
||
RemoveLineEffect();
|
||
RemoveDisappearEffect();
|
||
SavePieceGridPos(Vector2Int.zero);
|
||
ELog("CanGetNewGhostGrid TryScreenToGrid Failed");
|
||
return false;
|
||
}
|
||
|
||
if (IsPieceGridNotChange(grid))
|
||
{
|
||
return false;
|
||
}
|
||
this.SetCurrentPos($"row:{grid.y },col:{grid.x}");
|
||
|
||
ELog($"CanGetNewGhostGrid-> {_lastGrid} => {grid} ");
|
||
|
||
SavePieceGridPos(grid);
|
||
ClearGhostGrid();
|
||
var tetrominoData = pieceRenderer.Data;
|
||
// 计算影子方块在网格中的位置
|
||
for (var row = 0; row < tetrominoData.Height; row++)
|
||
{
|
||
for (var col = 0; col < tetrominoData.Width; col++)
|
||
{
|
||
if (tetrominoData[row, col] != CellType.Empty)
|
||
{
|
||
var gridRow = grid.y + row;
|
||
var gridCol = grid.x + col;
|
||
if (gridCol >= 0 && gridCol < _boardData.Width && gridRow >= 0 &&
|
||
gridRow < _boardData.Height)
|
||
{
|
||
if (_boardData[gridRow, gridCol] == CellType.Empty)
|
||
{
|
||
_cellRenderers[gridRow, gridCol].CellGhostTypeValue = tetrominoData[row, col];
|
||
_ghostCells.Add(_cellRenderers[gridRow, gridCol]);
|
||
_boardData.SetGhostValue(gridRow, gridCol, tetrominoData[row, col]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
private void SavePieceGridPos(Vector2Int grid)
|
||
{
|
||
_lastGrid = grid;
|
||
}
|
||
|
||
private Vector2Int _lastGrid = Vector2Int.zero;
|
||
private bool IsPieceGridNotChange(Vector2Int grid)
|
||
{
|
||
return _lastGrid.Equals(grid);
|
||
}
|
||
|
||
// 检测是否显示可消除的行列
|
||
public void AddClearEffects()
|
||
{
|
||
var rows = _boardData.GetClearRows(withGhostCheck: true);
|
||
if (rows.Count > 0)
|
||
{
|
||
foreach (var row in rows)
|
||
{
|
||
AddRowEffect(row);
|
||
}
|
||
}
|
||
|
||
var cols = _boardData.GetClearCols(withGhostCheck: true);
|
||
if (cols.Count > 0)
|
||
{
|
||
foreach (var col in cols)
|
||
{
|
||
AddColEffect(col);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void ClearGridAndCollectItems(int pieceId,out List<int> rows ,out List<int> cols,
|
||
out List<(int,int,int,int)> list,
|
||
out List<(int row,int col,int value,int newR,int newC)> listBomb)
|
||
{
|
||
rows = _boardData.GetClearRows();
|
||
cols = _boardData.GetClearCols();
|
||
// 清空和收集道具
|
||
ClearAddCollectItems(pieceId,rows, cols, out list,out listBomb);
|
||
|
||
if (ShouldBuildELog())
|
||
{
|
||
var valList = list.Select(item => $"({item.Item1} : {item.Item2}) => {item.Item3}").ToList();
|
||
if (valList is { Count: > 0 } || rows is { Count: > 0 } || cols is { Count: > 0 })
|
||
ELog(
|
||
$"LCM-> CheckLineClears -> rows : {string.Join(", ", rows)} cols {string.Join(", ", cols)} {string.Join(", ", valList)}");
|
||
}
|
||
}
|
||
|
||
private void ClearAddCollectItems(int pieceId, List<int> rows, List<int> cols,
|
||
out List<(int row ,int col ,int value ,int count)> list,
|
||
out List<(int row,int col,int value,int newR,int newC)> listBomb2)
|
||
{
|
||
_boardData.ClearRowsAndCols(rows, cols, out var myList );
|
||
list = DoCollectTransFilter(myList,out var listBomb);
|
||
|
||
var bombValues =_thisEventManager.GetBombValues(listBomb.Select(item => item.value).ToList());
|
||
listBomb2 = _boardData.UpdateBombValue(listBomb,bombValues);
|
||
|
||
var items = list
|
||
.GroupBy(x => x.Item3) // 按第三个值分组
|
||
.ToDictionary(
|
||
g => g.Key, // Key是第三个值
|
||
g => g.Sum(x => x.count) // 取每个组最后一个的第四个值
|
||
);
|
||
|
||
var itemCount = items.Sum(item => item.Value);
|
||
|
||
switch (itemCount)
|
||
{
|
||
case > 3:
|
||
GContext.Publish(new VibrationData(HapticTypes.Success));
|
||
break;
|
||
case > 0:
|
||
GContext.Publish(new VibrationData(HapticTypes.MediumImpact));
|
||
break;
|
||
default:
|
||
GContext.Publish(new VibrationData(HapticTypes.LightImpact));
|
||
break;
|
||
}
|
||
|
||
#if AGG
|
||
using (var e = GEvent.GameEvent("event_cubemelt"))
|
||
{
|
||
e.AddContent("piece_id",pieceId);
|
||
e.AddContent("clear_count", rows.Count + cols.Count);
|
||
e.AddContent("collection_count", itemCount);
|
||
e.AddContent("stage_id",_thisEventData.CurrentStagetId);
|
||
}
|
||
#else
|
||
ELog($"event_cubemelt -> {pieceId} {rows.Count + cols.Count} {itemCount} {_thisEventData.CurrentStagetId}");
|
||
#endif
|
||
|
||
_thisEventManager.AddCollect(items);
|
||
}
|
||
|
||
private string IconNameFromCellType(int cellType)
|
||
{
|
||
var items = _thisEventManager.GetCollectionItems();
|
||
if (items != null && items.TryGetValue(cellType, out var info))
|
||
return _thisEventManager.GetCollectIconById(info.TrueId);
|
||
return _thisEventManager.GetCollectIconByType(cellType);
|
||
}
|
||
|
||
|
||
//- 清理
|
||
// private async Task RunCollectItems(List<(int,int,int,int)> listItems)
|
||
// {
|
||
// ELog("RunCollectItems");
|
||
//
|
||
// if (listItems.Count <= 0)
|
||
// return;
|
||
//
|
||
// PlayFxInfoPiercing(listItems.Count);
|
||
// var tasks = new List<Task>();
|
||
// if (ShouldBuildELog())
|
||
// {
|
||
// var valList = listItems.Select(item => $"({item.Item1} : {item.Item2}) => {item.Item3} {item.Item4}").ToList();
|
||
// ELog($"LCM-> RunCollectItems ->newListItems {string.Join(", ", valList)}");
|
||
// }
|
||
// foreach (var item in listItems)
|
||
// {
|
||
// var cell = _cellRenderers[item.Item1, item.Item2];
|
||
// var req = new BatchedRewardFlyRequest
|
||
// {
|
||
// Icon = new BatchedRewardFlyRequestIcon { iconName = IconNameFromCellType(item.Item3) },
|
||
// StartPoint = new BatchedRewardFlyStartPoint((RectTransform)cell.transform),
|
||
// EndPoint = new BatchedRewardFlyEndPoint(GetComponentInParent<EventBlockPanel>().GetEndRectTransform(item.Item3)),
|
||
// IsDestinationRewardStash = false,
|
||
// AnimationParamIndex = 0,
|
||
// Quantity = item.Item4
|
||
// };
|
||
// tasks.Add(_rewardFlyBatchCtrl.OnRewardFlyRequestAsync(req));
|
||
// }
|
||
// await Task.WhenAll(tasks);
|
||
//
|
||
// var list = new HashSet<int>(listItems.Select(item => item.Item3)).ToList();
|
||
// var bRet = _thisEventManager.CheckCollectFinish(list);
|
||
// GContext.Publish(new EventUISound("audio_ui_cubemelt_cube_collect"));
|
||
// GContext.Publish(bRet ? new VibrationData(HapticTypes.Success) : new VibrationData(HapticTypes.SoftImpact));
|
||
// }
|
||
|
||
private List<(int row ,int col ,int value ,int count )> DoCollectTransFilter(
|
||
List<(int row , int col, int value )> listItems,
|
||
out List<(int row,int col,int value)> listBomb)
|
||
{
|
||
// var list = _thisEventManager.GetRepValue();
|
||
var collectionItems = _thisEventManager.GetCollectionItems();
|
||
var list = new List<(int, int, int )>();
|
||
listBomb = new List<(int row, int col, int value)>();
|
||
foreach (var (row, col, value) in listItems)
|
||
{
|
||
if (_thisEventManager.IsUnCollectValue(value))
|
||
{
|
||
listBomb.Add((row,col,value));
|
||
}
|
||
else
|
||
{
|
||
var newValues = _thisEventManager.ReplaceValue(value);
|
||
list.AddRange(newValues
|
||
.Where(nv => collectionItems.ContainsKey(nv)) // 过滤出被集合包含的值
|
||
.Select(nv => (row, col, nv)));
|
||
}
|
||
}
|
||
return list.GroupBy(t => t)
|
||
.Select(g => (g.Key.Item1, g.Key.Item2, g.Key.Item3, g.Count()))
|
||
.ToList();
|
||
// return list;
|
||
}
|
||
|
||
private bool IsCanPlaceDown(PieceRenderer pieceRenderer)
|
||
{
|
||
if (!pieceRenderer)
|
||
return false;
|
||
|
||
var num = _ghostCells?.Count;
|
||
return num == pieceRenderer.Data.UsableCount;
|
||
}
|
||
|
||
#region 时间调试
|
||
// private Stopwatch sw;
|
||
// private string scopeName;
|
||
// private static Dictionary<string,long> s_accum = new Dictionary<string,long>();
|
||
|
||
// private ProfileScope ps = new ();
|
||
|
||
// public void L_ProfileScope(string sectionName)
|
||
// {
|
||
// scopeName = sectionName;
|
||
// sw = Stopwatch.StartNew();
|
||
// }
|
||
// public void L_ProfileScopeEnd()
|
||
// {
|
||
// sw.Stop();
|
||
// long el = sw.ElapsedMilliseconds;
|
||
// s_accum.TryGetValue(scopeName, out long old);
|
||
// s_accum[scopeName] = old + el;
|
||
// Log($"{scopeName} 本次 {el} ms 累计 {s_accum[scopeName]} ms");
|
||
// }
|
||
|
||
#endregion
|
||
|
||
public bool TryPlaceDown(PieceRenderer pieceRenderer)
|
||
{
|
||
//-
|
||
if (_thisEventData.IsFinished )
|
||
{
|
||
ClearGhostGrid(true);
|
||
RemoveLineEffect();
|
||
RemoveDisappearEffect();
|
||
return false;
|
||
}
|
||
|
||
if (_thisEventData.TicketCount <= 0)
|
||
{
|
||
// GContext.Publish(new EventCubeMeltShowNeoNormalPack());
|
||
ClearGhostGrid(true);
|
||
RemoveLineEffect();
|
||
RemoveDisappearEffect();
|
||
return false;
|
||
}
|
||
|
||
//
|
||
if (!IsCanPlaceDown(pieceRenderer))
|
||
return false;
|
||
|
||
#if UNITY_EDITOR
|
||
_thisEventManager.SaveDataForPrev();
|
||
#endif
|
||
|
||
// ps.L_ProfileScope("ClearGhostGrid");
|
||
// 移除Ghost
|
||
ClearGhostGrid(true);
|
||
// ps.L_ProfileScopeEnd();
|
||
// 删除特效
|
||
// ps.L_ProfileScope("RemoveLineEffect");
|
||
RemoveLineEffect();
|
||
RemoveDisappearEffect();
|
||
// ps.L_ProfileScopeEnd();
|
||
|
||
// ps.L_ProfileScope("UpdateCellData");
|
||
// 更新数值
|
||
UpdateCellData(pieceRenderer);
|
||
// 更新显示
|
||
UpdateGridCells();
|
||
//
|
||
// ps.L_ProfileScopeEnd();
|
||
return true;
|
||
}
|
||
|
||
public async Task OnGridAnimation(int pieceId, List<int> rows,
|
||
List<int> cols,
|
||
List<(int, int, int, int)> list,
|
||
List<(int row, int col, int value, int newRow, int newCol)> listBomb,
|
||
bool ignoreReqDelay)
|
||
{
|
||
// ELog($"OnGridAnimation-> {elapsedMilliseconds}");
|
||
|
||
// ps.L_ProfileScope("UpdateGridClearData");
|
||
UpdateGridClearData(pieceId);
|
||
// ps.L_ProfileScopeEnd();
|
||
// ps.L_ProfileScope("Awaiters");
|
||
if (!ignoreReqDelay)
|
||
{
|
||
ELog("OnGridAnimation awaitPutBeforeDisappear");
|
||
await Awaiters.Seconds(putBeforeDisappearDuration );
|
||
}
|
||
|
||
// ps.L_ProfileScopeEnd();
|
||
// ps.L_ProfileScope("RunGridClearAnimation");
|
||
await RunGridClearAnimation(rows,cols,list,listBomb);
|
||
// ps.L_ProfileScopeEnd();
|
||
|
||
// ps.L_ProfileScope("UpdateGridCells");
|
||
UpdateGridCells();
|
||
// ps.L_ProfileScopeEnd();
|
||
|
||
_thisEventManager.SaveDataForNow();
|
||
}
|
||
|
||
//更新格子数据
|
||
public void UpdateGridClearData(int pieceId
|
||
// ,out List<int> rows,out List<int> cols,
|
||
// out List<(int,int,int,int)> list,
|
||
// out List<(int row,int col,int value,int newRow,int newCol)> listBomb
|
||
)
|
||
{
|
||
// ClearGridAndCollectItems( pieceId,out rows,out cols, out list,out listBomb);
|
||
_thisEventManager.UpdateGridData(_boardData.GetBoardData());
|
||
|
||
if (_thisEventManager.IsThisCollectFinished())
|
||
{
|
||
// GetComponentInParent<CanvasGroup>().blocksRaycasts = false;
|
||
GContext.Publish(new EventCubeMeltStageFinish());
|
||
}
|
||
|
||
}
|
||
|
||
// 执行格子清理动画
|
||
private async Task RunGridClearAnimation(List<int> rows,List<int> cols,
|
||
List<(int,int,int,int)> list,
|
||
List<(int row,int col,int value,int newRow,int newCol)> listBomb)
|
||
{
|
||
if (rows is { Count: <= 0 } && cols is { Count: <= 0 } && list is { Count: <= 0 })
|
||
return;
|
||
|
||
RemoveDisappearEffect();
|
||
// 在EmptyCell 上添加 播放特效
|
||
_ = DoGridClearAndAnims(rows,cols,listBomb);
|
||
_ = RunCollectItemsAndBombs(list, listBomb);
|
||
_ = DoGridBombAnims(listBomb,bombStartDelay);
|
||
await RunBombAnims(listBomb,bombFlyDelay);
|
||
|
||
// //TODO:LCM
|
||
// if (true)
|
||
// {
|
||
// // await RunCollectItemsAndBombs(list, listBomb);
|
||
// }
|
||
// else
|
||
// {
|
||
// await RunCollectItems(list);
|
||
// }
|
||
//
|
||
// 全部完成之后,刷新数据
|
||
if(list is {Count: > 0})
|
||
GContext.Publish(new EventForUpdateCollect() );
|
||
}
|
||
|
||
private async Task RunBombAnims(List<(int row, int col, int value, int newRow, int newCol)> listBomb,float delay)
|
||
{
|
||
await Awaiters.Seconds(delay);
|
||
|
||
var tasks = new List<Task>();
|
||
foreach (var bomb in listBomb)
|
||
{
|
||
var cell = _cellRenderers[bomb.row, bomb.col];
|
||
if (bomb.newRow == -1 || bomb.newCol == -1)
|
||
continue;
|
||
|
||
var endCell = _cellRenderers[bomb.newRow, bomb.newCol];
|
||
var req = new BatchedRewardFlyRequest
|
||
{
|
||
Icon = new BatchedRewardFlyRequestIcon { iconName = IconNameFromCellType(bomb.value) },
|
||
StartPoint = new BatchedRewardFlyStartPoint((RectTransform)cell.transform),
|
||
EndPoint = new BatchedRewardFlyEndPoint(endCell.GetAniTransform()),
|
||
IsDestinationRewardStash = false,
|
||
AnimationParamIndex = 1,
|
||
};
|
||
tasks.Add(RunBombTask(req, endCell, bomb));
|
||
}
|
||
await Task.WhenAll(tasks);
|
||
async Task RunBombTask (BatchedRewardFlyRequest req, CellRenderer endCell,
|
||
(int row, int col, int value, int endRow, int endCol) bomb)
|
||
{
|
||
await _rewardFlyBatchCtrl.OnRewardFlyRequestAsync(req);
|
||
await endCell.RunBombAni(bomb.value);
|
||
}
|
||
}
|
||
|
||
private async Task DoGridBombAnims(List<(int row, int col, int value, int newRow, int newCol)> listBombs,float delayTime)
|
||
{
|
||
await Awaiters.Seconds(delayTime);
|
||
var list2 = new List<Task>();
|
||
foreach (var bomb in listBombs)
|
||
{
|
||
var cellRenderer = _cellRenderers[bomb.row ,bomb.col];
|
||
list2.Add(cellRenderer.RunBombAnimation(0));
|
||
}
|
||
await Task.WhenAll(list2);
|
||
}
|
||
|
||
private async Task RunCollectItemsAndBombs(
|
||
List<(int, int, int, int)> listItems,
|
||
List<(int row,int col,int value,int newRow ,int newCol)> listBomb)
|
||
{
|
||
ELog("RunCollectItemsAndBombs");
|
||
|
||
var iCount = listItems.Count + listBomb.Count;
|
||
if (iCount <= 0) return;
|
||
|
||
// if (listItems.Count <= 0)
|
||
// return;
|
||
RectTransform GetEndRectTransform(int cellTypeValue)
|
||
{
|
||
var rootPanel = GetComponentInParent<EventBlockPanel>();
|
||
var root2Panel = GetComponentInParent<EventCubeMeltPanel>();
|
||
if (rootPanel)
|
||
{
|
||
return rootPanel.GetEndRectTransform(cellTypeValue);
|
||
}
|
||
return root2Panel ? root2Panel.GetEndRectTransform(cellTypeValue) : null;
|
||
}
|
||
|
||
|
||
|
||
|
||
PlayFxInfoPiercing(iCount);
|
||
var tasks = new List<Task>();
|
||
var valList = listItems.Select(item => $"({item.Item1} : {item.Item2}) => {item.Item3} {item.Item4}").ToList();
|
||
ELog($"LCM-> RunCollectItems ->newListItems {string.Join(", ",valList)}" );
|
||
foreach (var item in listItems)
|
||
{
|
||
var cell = _cellRenderers[item.Item1, item.Item2];
|
||
var req = new BatchedRewardFlyRequest
|
||
{
|
||
Icon = new BatchedRewardFlyRequestIcon { iconName = IconNameFromCellType(item.Item3) },
|
||
StartPoint = new BatchedRewardFlyStartPoint((RectTransform)cell.transform),
|
||
EndPoint = new BatchedRewardFlyEndPoint(GetEndRectTransform(item.Item3)),
|
||
IsDestinationRewardStash = false,
|
||
AnimationParamIndex = 0,
|
||
Quantity = item.Item4
|
||
};
|
||
tasks.Add(_rewardFlyBatchCtrl.OnRewardFlyRequestAsync(req));
|
||
}
|
||
|
||
// // var listBombRepValues = GetBombEndPoint(listBomb);
|
||
// foreach (var bomb in listBomb)
|
||
// {
|
||
// var cell = _cellRenderers[bomb.row, bomb.col];
|
||
// var endCell = _cellRenderers[bomb.newRow, bomb.newCol];
|
||
// var req = new BatchedRewardFlyRequest
|
||
// {
|
||
// Icon = new BatchedRewardFlyRequestIcon { iconName = IconNameFromCellType(bomb.value) },
|
||
// StartPoint = new BatchedRewardFlyStartPoint((RectTransform)cell.transform),
|
||
// EndPoint = new BatchedRewardFlyEndPoint(endCell.GetAniTransform()),
|
||
// IsDestinationRewardStash = false,
|
||
// AnimationParamIndex = 0,
|
||
// };
|
||
// tasks.Add(RunBombTask(req, endCell, bomb));
|
||
// // tasks.Add(_rewardFlyBatchCtrl.OnRewardFlyRequestAsync(req));
|
||
// }
|
||
await Task.WhenAll(tasks);
|
||
var list = new HashSet<int>(listItems.Select(item => item.Item3)).ToList();
|
||
var bRet = _thisEventManager.CheckCollectFinish(list);
|
||
|
||
// var list2 = new HashSet<int>(listBomb.Select(item => ))
|
||
// var bRet2 = _thisEventManager.CheckBombFinsh(listBomb);
|
||
|
||
// GContext.Publish(new EventUISound("audio_ui_cubemelt_cube_collect"));
|
||
GContext.Publish(bRet ? new VibrationData(HapticTypes.Success) : new VibrationData(HapticTypes.SoftImpact));
|
||
|
||
|
||
}
|
||
|
||
private List<(int row, int col,int value,int endRow,int endCol)> GetBombEndPoint(List<(int row, int col, int value)> listBomb)
|
||
{
|
||
ELog("GetBombEndPoint");
|
||
|
||
var ls = new List<(int, int, int, int, int)>();
|
||
int m = _boardData.Height;
|
||
int n = _boardData.Width;
|
||
// 1. 先扫一遍,把所有 99 的坐标收集起来
|
||
var list = new List<(int, int)>();
|
||
for (int i = 0; i < m; i++)
|
||
{
|
||
for (int j = 0; j < n; j++)
|
||
{
|
||
if (_boardData[i, j] == CellType.Ct99)
|
||
list.Add((i, j));
|
||
}
|
||
}
|
||
|
||
// 2. 如果没有 99,返回无效坐标
|
||
if (list.Count == 0)
|
||
return ls;
|
||
|
||
var finder = new UniqueRandom99(_boardData.GetGrid());
|
||
foreach (var bomb in listBomb)
|
||
{
|
||
for (var i = 0; i < 4; ++i)
|
||
{
|
||
var (r, c) = finder.Next();
|
||
if (r >= 0 && r < m && c >= 0 && c < n)
|
||
{
|
||
ls.Add(new ValueTuple<int, int, int, int, int>(bomb.row,bomb.col,bomb.value,r,c));
|
||
}
|
||
}
|
||
}
|
||
return ls;
|
||
// var randomValue = UnityEngine.Random.Range(0, list.Count);
|
||
// var (newRow,newCol) = list[randomValue];
|
||
// ls.Add(new ValueTuple<int, int, int, int, int>(1,2,3,newRow,newCol))
|
||
}
|
||
|
||
|
||
private async void PlayFxInfoPiercing(int iCount)
|
||
{
|
||
if(iCount < 1)
|
||
return;
|
||
|
||
const string baseStr = "piercing_0";
|
||
var str = iCount > 5 ? $"{baseStr}5" : $"{baseStr}{iCount -1}";
|
||
|
||
foreach (Transform child in fxInfoPiercing)
|
||
{
|
||
child.gameObject.SetActive(false);
|
||
}
|
||
var p = fxInfoPiercing.Find(str);
|
||
if (p)
|
||
{
|
||
p.gameObject?.SetActive(true);
|
||
await Awaiters.Seconds(1f);
|
||
p.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
//- 上一步
|
||
public void OnPrevStep()
|
||
{
|
||
_thisEventManager.LoadPrevData();
|
||
GContext.Publish(new EventForRefreshCubeMeltPanel());
|
||
}
|
||
|
||
public void OnRestoreStep()
|
||
{
|
||
#if UNITY_EDITOR
|
||
_thisEventManager.RestoreData();
|
||
GContext.Publish(new EventForRefreshCubeMeltPanel());
|
||
#endif
|
||
}
|
||
|
||
private void UpdateCellData(PieceRenderer piece)
|
||
{
|
||
var ghostPosition = piece.GetPiecePosition();
|
||
TryScreenToGrid(ghostPosition, out var ghostPos);
|
||
_boardData.UpdateDataByPiece(piece.Data,ghostPos);
|
||
_thisEventManager.UpdateGridData(_boardData.GetBoardData());
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Log
|
||
|
||
private static bool ShouldBuildELog()
|
||
{
|
||
#if UNITY_EDITOR
|
||
return EventCubeMeltLogPolicy.EnableELog;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
|
||
private static void ELog(string message)
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (!EventCubeMeltLogPolicy.EnableELog) return;
|
||
Debug.Log($"<color=orange>BoardRenderer => {message}</color>");
|
||
#endif
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 动画效果
|
||
|
||
private readonly List<Transform> _disappearEffectList = new();
|
||
|
||
private async Task AddRowDisappearEffect(int row,int count)
|
||
{
|
||
if (_disappearEffectRowPool == null)
|
||
return;
|
||
|
||
var fx = GetSingleDisappearFx();
|
||
|
||
if (count >= 3)
|
||
{
|
||
fx = fxUIEventCubemeltDisappearColorful;
|
||
if (_boardData.Width == 6)
|
||
fx = fxUIEventCubemeltDisappearColorful6;
|
||
else if (_boardData.Height == 7)
|
||
fx = fxUIEventCubemeltDisappearColorful7;
|
||
}
|
||
|
||
var fxClone = Instantiate(fx.gameObject, effectTrans).transform;
|
||
if (fxClone)
|
||
{
|
||
_disappearEffectList.Add(fxClone);
|
||
fxClone.name = $"disappear_effect_row";
|
||
fxClone.localScale = Vector3.one;
|
||
//* (1.05F * _boardData.Height / 8F);
|
||
var cell = _cellRenderers[row, 0];
|
||
// 默认位置 x = 0;
|
||
var position = new Vector3(0, cell.transform.position.y, cell.transform.position.z);
|
||
var localPosition = new Vector3(0, cell.transform.localPosition.y, cell.transform.localPosition.z);
|
||
fxClone.transform.localPosition = localPosition;
|
||
if (ShouldBuildELog())
|
||
ELog($"AddRowDisappearEffect -> {cell.transform.position} {position} {fxClone.transform.localPosition}");
|
||
await Awaiters.Seconds(1F);
|
||
}
|
||
}
|
||
|
||
private Transform GetSingleDisappearFx()
|
||
{
|
||
var fx = fxUIEventCubeMeltDisappear;
|
||
if (_boardData.Width == 6)
|
||
fx = fxUIEventCubeMeltDisappear6;
|
||
else if(_boardData.Width == 7)
|
||
fx = fxUIEventCubeMeltDisappear7;
|
||
return fx;
|
||
}
|
||
|
||
private async Task AddColDisappearEffect(int col,int count)
|
||
{
|
||
if (_disappearEffectColPool == null)
|
||
return;
|
||
|
||
var fx = fxUIEventCubeMeltColDisappear;
|
||
if (_boardData.Width == 6)
|
||
fx = fxUIEventCubeMeltColDisappear6;
|
||
else if(_boardData.Width == 7)
|
||
fx = fxUIEventCubeMeltColDisappear7;
|
||
|
||
|
||
if (count >= 3)
|
||
{
|
||
fx = fxUIEventCubemeltDisappearColorfulVertical;
|
||
if (_boardData.Width == 6)
|
||
fx = fxUIEventCubemeltDisappearColorfulVertical6;
|
||
else if(_boardData.Width == 7)
|
||
fx = fxUIEventCubemeltDisappearColorfulVertical7;
|
||
}
|
||
|
||
var fxClone = Instantiate(fx.gameObject, effectTrans).transform;
|
||
if (fxClone)
|
||
{
|
||
_disappearEffectList.Add(fxClone);
|
||
// fxClone.SetParent( transform);
|
||
fxClone.name = $"disappear_effect_col";
|
||
fxClone.localScale = Vector3.one;
|
||
//* (1.05F * _boardData.Height / 8F);
|
||
// 1.1f;
|
||
var cell = _cellRenderers[0,col];
|
||
var position = new Vector3(cell.transform.position.x, 0, cell.transform.position.z);
|
||
var localPosition = new Vector3(cell.transform.localPosition.x, 0, cell.transform.localPosition.z);
|
||
fxClone.transform.localPosition = localPosition;
|
||
if (ShouldBuildELog())
|
||
ELog($"AddColDisappearEffect -> {cell.transform.position} {position} {fxClone.transform.localPosition}");
|
||
|
||
await Awaiters.Seconds(1F);
|
||
}
|
||
}
|
||
public async void RemoveDisappearEffect()
|
||
{
|
||
ELog("RemoveDisappearEffect-> ");
|
||
await Awaiters.NextFrame;
|
||
foreach (var trans in _disappearEffectList)
|
||
{
|
||
Destroy(trans.gameObject);
|
||
}
|
||
_disappearEffectList.Clear();
|
||
}
|
||
private async void AddRowEffect(int row)
|
||
{
|
||
if (_lineEffectPool == null)
|
||
return;
|
||
await Awaiters.NextFrame;
|
||
// var fxClone = _lineEffectPool.SpawnObject() as Transform;
|
||
var fx = fxUIEventCubemeltEliminatable;
|
||
var fxClone = Instantiate(fx.gameObject,effectTrans).transform;
|
||
if (fxClone)
|
||
{
|
||
_lineEffectList.Add(fxClone);
|
||
fxClone.name = $"effect_row";
|
||
// fxClone.localScale = Vector3.one * 1.1f * (_boardData.Width / 8F);
|
||
fxClone.localScale = new Vector3(1.12f * (_boardData.Height / 8F),1.1f,1 );
|
||
var cell = _cellRenderers[row, 0];
|
||
// 默认位置 x = 0;
|
||
var position = new Vector3(0, cell.transform.position.y, cell.transform.position.z);
|
||
// var localPosition = new Vector3(0, cell.transform.localPosition.y, cell.transform.localPosition.z);
|
||
// fxClone.transform.localPosition = localPosition;
|
||
if (ShouldBuildELog())
|
||
ELog($"AddRowEffect -> {cell.transform.position} {position} {fxClone.transform.localPosition}");
|
||
fxClone.transform.position = position;
|
||
var pr = fxClone.transform.Find("1/fx_mat_ui_event_cubemelt_eliminatable_01")
|
||
.GetComponent<ParticleSystem>();
|
||
var main = pr.main;
|
||
main.startRotation = 0;
|
||
}
|
||
}
|
||
|
||
// 可以加个内存池子
|
||
private async void AddColEffect(int col)
|
||
{
|
||
if (_lineEffectPool == null)
|
||
return;
|
||
await Awaiters.NextFrame;
|
||
|
||
var fx = fxUIEventCubemeltEliminatable;
|
||
var fxClone = Instantiate(fx.gameObject, effectTrans).transform;
|
||
if (fxClone)
|
||
{
|
||
_lineEffectList.Add(fxClone);
|
||
// fxClone.SetParent(transform);
|
||
fxClone.name = "effect_col";
|
||
fxClone.localScale = new Vector3(1.2f,1.12f * (_boardData.Height / 8F),1f );
|
||
|
||
var cell = _cellRenderers[0, col];
|
||
// 默认位置 x = 0;
|
||
var position = new Vector3(cell.transform.position.x, 0, cell.transform.position.z);
|
||
// fxClone.transform.position = position;
|
||
// fxClone.transform.localRotation = Quaternion.Euler(0, 0, 90);
|
||
|
||
var localPosition = new Vector3(cell.transform.localPosition.x, 0, cell.transform.localPosition.z);
|
||
fxClone.transform.localPosition = localPosition;
|
||
// fxClone.transform.position = position;
|
||
if (ShouldBuildELog())
|
||
ELog($"AddColEffect -> {cell.transform.position} {position} {fxClone.transform.localPosition}");
|
||
|
||
|
||
var pr = fxClone.transform.Find("1/fx_mat_ui_event_cubemelt_eliminatable_01")
|
||
.GetComponent<ParticleSystem>();
|
||
var main = pr.main;
|
||
main.startRotation = Mathf.Deg2Rad * 90f;
|
||
// 第二组
|
||
var pr2 = fxClone.transform.Find("1/fx_mat_ui_event_cubemelt_eliminatable_02")?.GetComponent<ParticleSystem>();
|
||
if (pr2?.main != null)
|
||
{
|
||
var main2 = pr2.main;
|
||
main2.startRotation = Mathf.Deg2Rad * 90f;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
private readonly List<Transform> _lineEffectList = new();
|
||
public async void RemoveLineEffect()
|
||
{
|
||
ELog("RemoveLineEffect-> ");
|
||
await Awaiters.NextFrame;
|
||
foreach (var trans in _lineEffectList)
|
||
{
|
||
Destroy(trans.gameObject);
|
||
}
|
||
|
||
_lineEffectList.Clear();
|
||
}
|
||
|
||
#endregion
|
||
public bool SatisfyNewGuide1(PieceRenderer dragPiece)
|
||
{
|
||
ELog($"SatisfyNewGuide1 -> GetPiecePosition -> {dragPiece.GetPiecePosition()}");
|
||
|
||
if (_newGuide1GhostCheckCells == null || _newGuide1GhostCheckCells.Length == 0)
|
||
{
|
||
ELog("SatisfyNewGuide1: _newGuide1GhostCheckCells 未配置");
|
||
return false;
|
||
}
|
||
|
||
foreach (var cell in _newGuide1GhostCheckCells)
|
||
{
|
||
var v = _boardData.GetGhostValue(cell.row, cell.col);
|
||
if (v == CellType.Empty || v == CellType.Illegal)
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
|
||
private string _currentPosStr = string.Empty;
|
||
private bool isShow = false;
|
||
//
|
||
|
||
|
||
private void OnGUI()
|
||
{
|
||
if (!isShow)
|
||
{
|
||
return;
|
||
}
|
||
int fontSize = 40;
|
||
|
||
GUI.skin.label.fontSize = fontSize;
|
||
GUILayout.Space(220);
|
||
GUILayout.Label($" CurrentPosStr: {_currentPosStr}");
|
||
}
|
||
#endif
|
||
private void Update()
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (Input.GetKeyDown(KeyCode.K))
|
||
{
|
||
isShow = !isShow;
|
||
}
|
||
#endif
|
||
}
|
||
public void SetCurrentPos(string posStr)
|
||
{
|
||
#if UNITY_EDITOR
|
||
_currentPosStr = posStr;
|
||
#endif
|
||
}
|
||
}
|
||
|
||
} |