using System; using System.Collections.Generic; using DG.Tweening; using UnityEngine; [RequireComponent(typeof(BoardFitter))] public class Board : MonoBehaviour { [SerializeField] private ChipPointer pointer; [SerializeField] private AudioClip _clearSound; [Header("PvP colors")] [SerializeField] private Color _pvpInnerColor = new Color(0.2f, 0.65f, 1f, 1f); [SerializeField] private Color _pvpOutlineColor = new Color(1f, 0.5f, 0.1f, 1f); [SerializeField] private Color _pvpCellsColor = new Color(0.65f, 0.2f, 1f, 1f); private BoardFitter fitter; private BoardConfiguration config; public static Board Instance { get; private set; } public Chip[,] Grid { get; private set; } public int Columns { get; private set; } public int Rows { get; private set; } public int MovesCount { get; private set; } public void Init() { if (TryGetComponent(out BoardFitter fitter)) this.fitter = fitter; else throw new InvalidOperationException("Не найден fitter на доске"); Instance = this; ApplySettings(); SettingsManager.OnSettingsChanged += ApplySettings; } public Sequence GetColorSequence(Color innerColor, Color outlineColor, Color cellsColor, float duration) => fitter.GetColorSequence(innerColor, outlineColor, cellsColor, duration); public void SetColorsImmediately(Color innerColor, Color outlineColor, Color cellsColor) => fitter.SetColorsImmediately(innerColor, outlineColor, cellsColor); public void ApplyPvpColors() => SetColorsImmediately(_pvpInnerColor, _pvpOutlineColor, _pvpCellsColor); public Vector2 GetStickedPosition(int column) => new Vector2(GetXPosition(column), config.topLeftCell.position.y + config.stickedYOffset); public Vector2 GetTargetPosition(int column) => new Vector2(GetXPosition(column), GetYPosition(column)); public void MakeClearField() { PerformChipsClear(); MovesCount = 0; Grid = new Chip[Columns, Rows]; } public bool CanDrop(int column) => Grid[column, 0] == null; public void DropChip(Chip chip, int column) { int row = GetLowestEmptyRow(column); if (column < 0 || column >= Columns) { Debug.LogError($"Попытка поставить фишку в колонку {column}. Колонок: {Columns}"); return; } if (row < 0 || row >= Rows) { Debug.LogError($"Попытка поставить фишку в ряд {row}. Рядов: {Rows}"); return; } Grid[column, row] = chip; MovesCount++; } public int[] GetNonFullColumns() { List temp = new(); for (int column = 0; column < Columns; column++) if (CanDrop(column)) temp.Add(column); return temp.ToArray(); } public int GetLowestEmptyRow(int colIndex) { if (colIndex < 0 || colIndex >= Columns) throw new ArgumentOutOfRangeException($"Попытка проверить колонку {colIndex}. Колонок: {Columns}"); for (int row = Rows - 1; row >= 0; row--) if (Grid[colIndex, row] == null) return row; return -1; } public Team[,] GridToTeam() { Team[,] res = new Team[Rows, Columns]; for (int row = 0; row < Rows; row++) { for (int col = 0; col < Columns; col++) { var chip = Grid[col, row]; res[row, col] = chip == null ? Team.None : chip.team; } } return res; } private float GetXPosition(int column) => config.topLeftCell.position.x + config.cellOffset.x * column; private float GetYPosition(int column) => config.topLeftCell.position.y + GetLowestEmptyRow(column) * config.cellOffset.y; private void PerformChipsClear() { GameManager.Instance.currentChip?.RemoveFromField(); if (Grid == null) return; bool fieldHadChips = false; foreach (Chip chip in Grid) { if (chip == null) continue; fieldHadChips = true; chip.RemoveFromField(); } if (fieldHadChips) SoundManager.instance.PlaySfx(_clearSound); } //todo: реализовать private void ApplySettings() { int columns = SettingsManager.GetInt(SettingKey.BOARD_COLUMNS); int rows = SettingsManager.GetInt(SettingKey.BOARD_ROWS); RebuildBoard(columns, rows); } private void RebuildBoard(int columns, int rows) { Columns = columns; Rows = rows; fitter.FitBoard(columns, rows); config = fitter.GetConfiguration(); MakeClearField(); } }