Правки в скрипте проверки поля; реализовано поведение бота, реализован TurnManager; Всё вышесказанное проброшено в игру

This commit is contained in:
Сергей Бондарь 2026-08-04 12:34:31 +03:00
parent c8937a239d
commit 0731921ee7
13 changed files with 663 additions and 40 deletions

View File

@ -3249,6 +3249,58 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 164597568}
m_CullTransparentMesh: 1
--- !u!1 &167531120
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 167531122}
- component: {fileID: 167531121}
m_Layer: 0
m_Name: Bot
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &167531121
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 167531120}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 53a19fde86337d440b9594d33a8ed786, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Bot
board: {fileID: 1768372455}
chipSprite: {fileID: 21300000, guid: 2194de45dbf1e8c46a827a05cdd2d905, type: 3}
<team>k__BackingField: 2
prepareSpeed: 30
moveSpeed: 10
difficultyPreset: {fileID: 11400000, guid: 1c381d73d66d6254d8e6326516732d27, type: 2}
useDummyBots: 0
minThinkingTime: 2
--- !u!4 &167531122
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 167531120}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -5.96509, y: 11.30334, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1329752847}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &172285184
GameObject:
m_ObjectHideFlags: 0
@ -4235,6 +4287,59 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 233260561}
m_CullTransparentMesh: 1
--- !u!1 &245771467
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 245771469}
- component: {fileID: 245771468}
m_Layer: 0
m_Name: Player2
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &245771468
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 245771467}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0302f7201f8ad714280dbc7ceefc55a7, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Player
board: {fileID: 1768372455}
chipSprite: {fileID: 21300000, guid: 2194de45dbf1e8c46a827a05cdd2d905, type: 3}
<team>k__BackingField: 2
chipYOffset: 5
prepareSpeed: 30
moveSpeed: 10
leftButtons: 03000000
rightButtons: 01000000
actionButtons: 04000000
--- !u!4 &245771469
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 245771467}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -3.6197202, y: 4.48496, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1329752847}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &251509681
GameObject:
m_ObjectHideFlags: 0
@ -4524,7 +4629,7 @@ MonoBehaviour:
leaderboard: {fileID: 1784614873}
CharactersConfigurator: {fileID: 141381088}
menuGameplayTransit: {fileID: 29868612}
player1: {fileID: 304437819}
turnManager: {fileID: 1329752846}
setPasswordPanel: {fileID: 131572818}
vitrinaPanel: {fileID: 61619038}
qrPanel: {fileID: 1060301113}
@ -5284,7 +5389,7 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Player
board: {fileID: 1768372455}
chipSprite: {fileID: -1055215911, guid: b196c55df50055d4cafb336e9a05b519, type: 3}
team: 1
<team>k__BackingField: 1
chipYOffset: 5
prepareSpeed: 30
moveSpeed: 10
@ -5299,12 +5404,12 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 304437818}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -5.18764, y: 2.92598, z: 0}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -3.6197202, y: 4.48496, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_Father: {fileID: 1329752847}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &325463671
GameObject:
@ -22515,6 +22620,57 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1329533185}
m_CullTransparentMesh: 1
--- !u!1 &1329752845
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1329752847}
- component: {fileID: 1329752846}
m_Layer: 0
m_Name: TurnManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1329752846
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1329752845}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c31f8116cb529434eafcc42e078c3b75, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TurnManager
player1: {fileID: 304437819}
player2: {fileID: 245771468}
bot: {fileID: 167531121}
gameMode: 0
--- !u!4 &1329752847
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1329752845}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -1.56792, y: -1.55898, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 304437820}
- {fileID: 245771469}
- {fileID: 167531122}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1330901877
GameObject:
m_ObjectHideFlags: 0
@ -38619,4 +38775,4 @@ SceneRoots:
- {fileID: 1615046716}
- {fileID: 46193421}
- {fileID: 1606109336}
- {fileID: 304437820}
- {fileID: 1329752847}

View File

@ -0,0 +1,9 @@
using UnityEngine;
public class BasePlayer : MonoBehaviour
{
[Header("Components")]
[SerializeField] protected Board board;
[SerializeField] protected Sprite chipSprite;
[field: SerializeField] public Team team { get; private set; }
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d0f846fb928268440b9664deef1bcdfa

View File

@ -64,7 +64,7 @@ public class GameManager : MonoBehaviour
[Header("Переходы")]
[SerializeField] private MenuGameplayTransit menuGameplayTransit;
[SerializeField] Player player1;
[SerializeField] TurnManager turnManager;
//public PvpPointer pvpPointer;
//public MovesAndTimeCounter movesAndTimeCounter;
@ -103,12 +103,16 @@ public class GameManager : MonoBehaviour
// return;
SetMode(mode);
menuGameplayTransit.GameplayOpened += OnGameplayOpened;
menuGameplayTransit.GotoGameplay();
ControlsPerformer.Instance.SetControlable(null);
}
void OnGameplayOpened()
{
menuGameplayTransit.GameplayOpened -= OnGameplayOpened;
OnGameStarted?.Invoke(gameMode);
player1.PrepareChip();
ControlsPerformer.Instance.SetControlable(player1);
//timerManager.SetTimersActivity(gameMode);
turnManager.StartGame(gameMode);
}
private void OnApplicationQuit() => ComNativeWrapper.Serial_CloseAll();

View File

@ -0,0 +1,298 @@
using UnityEngine;
using System.Threading;
public class Bot : BasePlayer, IGamePlayer
{
[Header("Movement Settings")]
[SerializeField] private float prepareSpeed;
[SerializeField] private float moveSpeed;
[Header("Bot Settings")]
[SerializeField] private DifficultyPreset difficultyPreset;
[SerializeField] private bool useDummyBots = false;
[SerializeField] private float minThinkingTime = 1f;
// State
private PlayerState state = PlayerState.Sleep;
private Chip currentChip;
private int[] availableColumns;
private int selectedColumnIndex;
// Movement targets
private Vector2 stickedTargetPosition;
private Vector2 dropTargetPosition;
// Thinking
private Thread calculationThread;
private int calculatedColumn = -1;
private float thinkingStartTime;
private bool isThinkingComplete = false;
// Random movement
private float randomMoveTimer;
private float randomMoveInterval = 0.3f;
public event System.Action OnChipDropped;
private int SelectedColumn => availableColumns[selectedColumnIndex];
public bool ControlsEnabled { get; set; } = true;
#region Public Methods
public void PrepareChip()
{
SetState(PlayerState.Preparing);
CacheAvailableColumns();
CreateChip();
SetInitialChipPosition();
}
public void Sleep()
{
SetState(PlayerState.Sleep);
currentChip = null;
availableColumns = null;
StopThinking();
}
public void UpdateControls()
{
switch (state)
{
case PlayerState.Preparing:
UpdatePreparing();
break;
case PlayerState.Thinking:
UpdateThinking();
break;
case PlayerState.Moving:
UpdateMoving();
break;
case PlayerState.Dropping:
UpdateDropping();
break;
case PlayerState.Sleep:
break;
}
}
#endregion
#region State Updates
private void UpdatePreparing()
{
// Движение сверху вниз к stickedTargetPosition (без оффсета)
if (currentChip.MoveToLinear(stickedTargetPosition, prepareSpeed))
{
StartThinking();
}
}
private void UpdateThinking()
{
// Случайные движения (инициируют переход в Moving)
TryRandomMovement();
// Проверяем, завершены ли вычисления и прошло ли минимальное время
if (isThinkingComplete && Time.time - thinkingStartTime >= minThinkingTime)
{
MoveToCalculatedColumn();
}
}
private void UpdateMoving()
{
// Плавное горизонтальное движение к целевой позиции (Y сохраняется)
if (currentChip.MoveToLinear(stickedTargetPosition, moveSpeed))
{
// Если условия для дропа выполнены - бросаем
if (isThinkingComplete && Time.time - thinkingStartTime >= minThinkingTime)
{
PerformDrop();
}
else
{
// Иначе возвращаемся в режим раздумий
SetState(PlayerState.Thinking);
}
}
}
private void UpdateDropping()
{
if (currentChip.MoveToAccelerated(dropTargetPosition))
{
SetState(PlayerState.Sleep);
OnChipDropped?.Invoke();
Debug.Log("Chip dropped");
}
}
#endregion
#region Bot Logic
private void StartThinking()
{
SetState(PlayerState.Thinking);
isThinkingComplete = false;
calculatedColumn = -1;
thinkingStartTime = Time.time;
randomMoveTimer = 0f;
StopThinking();
calculationThread = new Thread(CalculateBestMove);
calculationThread.Start();
}
private void StopThinking()
{
if (calculationThread != null && calculationThread.IsAlive)
{
calculationThread.Abort();
calculationThread = null;
}
}
private void CalculateBestMove()
{
try
{
DifficultyPreset currentPreset = difficultyPreset;
if (useDummyBots && DifficultyManager.Instance != null)
currentPreset = DifficultyManager.Instance.DummyPreset;
if (currentPreset != null && board != null)
{
int movesMade = board.MovesCount;
currentPreset = currentPreset.GetPreset(movesMade);
Solver.SetPreset(currentPreset);
}
GameManager gm = GameManager.instance;
if (gm != null)
{
bool onBossByScore = gm.vsBotScore == gm.botsAmount - 1;
bool isHardCommonDifficulty = SettingsManager.GetString(SettingKey.DIFFICULTY) == "Сложная";
bool isUpperCashDifficulty = SettingsManager.GetString(SettingKey.DIFFICULTY_MODE) == "Заработок";
bool needSuperPreset = onBossByScore && (isHardCommonDifficulty || isUpperCashDifficulty);
if (needSuperPreset)
calculatedColumn = SolverV2.FindBestMove(board.GridToTeam(), team);
else
calculatedColumn = Solver.FindBestMove(board.GridToTeam(), team);
}
else
{
calculatedColumn = Solver.FindBestMove(board.GridToTeam(), team);
}
isThinkingComplete = true;
}
catch (ThreadAbortException) { }
catch (System.Exception e)
{
Debug.LogError($"Bot calculation error: {e.Message}");
}
}
private void MoveToCalculatedColumn()
{
if (calculatedColumn == -1) return;
int targetIndex = System.Array.IndexOf(availableColumns, calculatedColumn);
if (targetIndex == -1)
{
Debug.LogWarning($"Column {calculatedColumn} is not available!");
return;
}
if (selectedColumnIndex == targetIndex)
{
PerformDrop();
return;
}
selectedColumnIndex = targetIndex;
UpdateTargetPositionX(board.GetStickedPosition(SelectedColumn).x);
SetState(PlayerState.Moving);
}
private void PerformDrop()
{
dropTargetPosition = board.GetTargetPosition(SelectedColumn);
board.DropChip(currentChip, SelectedColumn);
SetState(PlayerState.Dropping);
}
#endregion
#region Random Movement
private void TryRandomMovement()
{
if (availableColumns == null || availableColumns.Length <= 1) return;
randomMoveTimer += Time.deltaTime;
if (randomMoveTimer >= randomMoveInterval)
{
randomMoveTimer = 0f;
int direction = Random.Range(0, 2) * 2 - 1;
int newIndex = Mathf.Clamp(selectedColumnIndex + direction, 0, availableColumns.Length - 1);
if (newIndex != selectedColumnIndex)
{
selectedColumnIndex = newIndex;
// Сохраняем текущий Y, меняем только X
UpdateTargetPositionX(board.GetStickedPosition(SelectedColumn).x);
SetState(PlayerState.Moving);
}
}
}
#endregion
#region Helpers
private void CacheAvailableColumns()
{
availableColumns = board.GetNonFullColumns();
selectedColumnIndex = availableColumns.Length / 2;
}
private void CreateChip()
{
currentChip = ChipPool.Instance.GetConfigured(chipSprite, team);
}
private void SetInitialChipPosition()
{
// Начальная позиция – сверху с оффсетом
stickedTargetPosition = board.GetMiddleStickedPosition();
currentChip.transform.position = stickedTargetPosition + Vector2.up * 5f;
}
private void SetState(PlayerState newState) => state = newState;
// Обновляет только X целевой позиции, Y остаётся неизменным
private void UpdateTargetPositionX(float newX)
{
stickedTargetPosition = new Vector2(newX, stickedTargetPosition.y);
}
#endregion
#region Nested Types
private enum PlayerState
{
Sleep,
Preparing,
Thinking,
Moving,
Dropping
}
#endregion
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 53a19fde86337d440b9594d33a8ed786

View File

@ -12,6 +12,8 @@ public static class FieldChecker
public static int Height => Board.Instance.Rows;
public static int Width => Board.Instance.Columns;
public static int TargetLineLength = 4;
public static CheckResult lastResult;
public static CheckResult Check(Team lastPlayer)
{
@ -31,25 +33,25 @@ public static class FieldChecker
WinningIndexes.UnionWith(colsResult.winningIndexes);
WinningIndexes.UnionWith(diagonalsResult.winningIndexes);
return new CheckResult(end: true,
lastResult = new CheckResult(end: true,
isDraw: false,
WinningIndexes);
return lastResult;
}
else if (checkDraw())
{
return new CheckResult(end: true,
lastResult = new CheckResult(end: true,
isDraw: true,
WinningIndexes);
return lastResult;
}
else
{
return new CheckResult(end: false,
lastResult = new CheckResult(end: false,
isDraw: false,
WinningIndexes);
return lastResult;
}
}
private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(Team targetTeam)
{
@ -58,17 +60,15 @@ public static class FieldChecker
for (int row = 0; row < Height; row++)
{
int start = -1;
for (int col = 0; col <= Width; col++) // теперь проходим до Width включительно
for (int col = 0; col < Width; col++)
{
// Проверяем, не вышли ли за границы массива
var chip = FieldArray[col, row];
bool isMatch = col < Width && chip != null && chip.team == targetTeam;
bool isMatch = chip != null && chip.team == targetTeam;
if (isMatch && start == -1)
start = col;
if ((!isMatch || col == Width) && start != -1)
if (!isMatch && start != -1)
{
int length = col - start;
if (length >= TargetLineLength)
@ -79,6 +79,16 @@ public static class FieldChecker
start = -1;
}
}
// Проверка последовательности в конце строки
if (start != -1)
{
int length = Width - start;
if (length >= TargetLineLength)
{
for (int c = start; c < Width; c++)
winningCells.Add((row, c));
}
}
}
return (winningCells.Count > 0, winningCells);
@ -91,15 +101,15 @@ public static class FieldChecker
{
int start = -1;
for (int row = 0; row <= Height; row++)
for (int row = 0; row < Height; row++)
{
var chip = FieldArray[col, row];
bool isMatch = row < Height && chip != null && chip.team == targetTeam;
bool isMatch = chip != null && chip.team == targetTeam;
if (isMatch && start == -1)
start = row;
if ((!isMatch || row == Height) && start != -1)
if (!isMatch && start != -1)
{
int length = row - start;
if (length >= TargetLineLength)
@ -110,6 +120,17 @@ public static class FieldChecker
start = -1;
}
}
// Проверка последовательности в конце столбца
if (start != -1)
{
int length = Height - start;
if (length >= TargetLineLength)
{
for (int r = start; r < Height; r++)
winningCells.Add((r, col));
}
}
}
return (winningCells.Count > 0, winningCells);
@ -143,7 +164,7 @@ public static class FieldChecker
}
private static void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep,
Team targetCellState, HashSet<(int, int)> winningCells)
Team targetCellState, HashSet<(int, int)> winningCells)
{
int rows = Height;
int cols = Width;
@ -162,10 +183,11 @@ public static class FieldChecker
if (isMatch)
{
sequenceLength++;
}
else
{
if (sequenceLength >= TargetLineLength)
{
// Добавляем ВСЕ ячейки из текущей последовательности
for (int i = 0; i < sequenceLength; i++)
{
int r = sequenceStartRow + i * rowStep;
@ -173,9 +195,6 @@ public static class FieldChecker
winningCells.Add((r, c));
}
}
}
else
{
sequenceLength = 0;
sequenceStartRow = currentRow + rowStep;
sequenceStartCol = currentCol + colStep;
@ -184,8 +203,20 @@ public static class FieldChecker
currentRow += rowStep;
currentCol += colStep;
}
// Проверка последовательности в конце диагонали
if (sequenceLength >= TargetLineLength)
{
for (int i = 0; i < sequenceLength; i++)
{
int r = sequenceStartRow + i * rowStep;
int c = sequenceStartCol + i * colStep;
winningCells.Add((r, c));
}
}
}
public static bool checkDraw()
{
for (int col = 0; col < Width; col++)

View File

@ -1,13 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour, IControlable
public class Player : BasePlayer, IGamePlayer
{
[Header("Components")]
[SerializeField] private Board board;
[SerializeField] private Sprite chipSprite;
[SerializeField] private Team team;
[Header("Movement Settings")]
[SerializeField] private float chipYOffset = 5f;
[SerializeField] private float prepareSpeed;
@ -28,6 +24,8 @@ public class Player : MonoBehaviour, IControlable
private Vector2 stickedTargetPosition;
private Vector2 dropTargetPosition;
public event Action OnChipDropped;
private int SelectedColumn => availableColumns[selectedColumnIndex];
public bool ControlsEnabled { get; set; } = true;
@ -120,8 +118,12 @@ public class Player : MonoBehaviour, IControlable
{
if (currentChip.MoveToAccelerated(dropTargetPosition))
{
SetState(PlayerState.Sleep);
Debug.Log("Chip dropped successfully");
if (currentChip.MoveToAccelerated(dropTargetPosition))
{
SetState(PlayerState.Sleep);
OnChipDropped?.Invoke();
Debug.Log("Chip dropped");
}
}
}

View File

@ -0,0 +1,98 @@
using Cysharp.Threading.Tasks.Triggers;
using System;
using UnityEngine;
public class TurnManager : MonoBehaviour
{
[Header("Players")]
[SerializeField] private Player player1;
[SerializeField] private Player player2;
[SerializeField] private Bot bot;
[Header("Settings")]
[SerializeField] private GameMode gameMode;
private IGamePlayer currentPlayer;
private bool isGameOver = false;
public void StartGame(GameMode mode)
{
gameMode = mode;
isGameOver = false;
SetupPlayers();
StartTurn(currentPlayer);
}
private void SetupPlayers()
{
// Всегда начинаем с первого игрока
currentPlayer = player1;
}
private void StartTurn(IGamePlayer player)
{
if (isGameOver) return;
// Отписываемся, чтобы избежать дублирования подписок
player.OnChipDropped -= OnTurnCompleted;
player.OnChipDropped += OnTurnCompleted;
player.PrepareChip();
ControlsPerformer.Instance.SetControlable(player);
currentPlayer = player;
}
private void OnTurnCompleted()
{
// Отписываемся от события текущего игрока
currentPlayer.OnChipDropped -= OnTurnCompleted;
if (CheckGameOver())
{
OnGameOver();
return;
}
NextTurn();
}
private void NextTurn()
{
// Отключаем текущего игрока
currentPlayer.Sleep();
// Определяем следующего игрока в зависимости от режима
IGamePlayer nextPlayer;
if (gameMode == GameMode.pve)
{
nextPlayer = (currentPlayer == player1) ? (IGamePlayer)bot : player1;
}
else // pvp
{
nextPlayer = (currentPlayer == player1) ? (IGamePlayer)player2 : player1;
}
currentPlayer = nextPlayer;
StartTurn(currentPlayer);
}
private bool CheckGameOver()
{
if(currentPlayer is BasePlayer player)
{
var checkResult = FieldChecker.Check(player.team);
return checkResult.End;
}
else
{
throw new Exception($"Не удалось привести {currentPlayer}");
}
}
private void OnGameOver()
{
isGameOver = true;
currentPlayer.Sleep();
ControlsPerformer.Instance.SetControlable(null);
Debug.Log("Game Over!");
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c31f8116cb529434eafcc42e078c3b75

View File

@ -0,0 +1,8 @@
using System;
public interface IGamePlayer : IControlable
{
void PrepareChip();
void Sleep();
event Action OnChipDropped;
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dafb8cdd40e72cf4ba778ed003543473

View File

@ -1,4 +1,5 @@
using DG.Tweening;
using System;
using UnityEngine;
public class MenuGameplayTransit : MonoBehaviour
@ -6,6 +7,8 @@ public class MenuGameplayTransit : MonoBehaviour
[SerializeField] MenuLayoutController menu;
[SerializeField] GameplayLayoutController gameplay;
public event Action GameplayOpened;
Sequence _sequence;
bool locked = false;
private void Update()
@ -32,9 +35,15 @@ public class MenuGameplayTransit : MonoBehaviour
_sequence.Append(gameplay.GetOpenSequence());
_sequence.onComplete += Unlock;
_sequence.onComplete += NotifyGameplayOpened;
_sequence.PlayForward();
}
private void NotifyGameplayOpened()
{
GameplayOpened?.Invoke();
}
public void GotoMenu()
{
Lock();