[Add] UI, menu, pause and timer
This commit is contained in:
@@ -22,17 +22,23 @@ namespace Minesweeper.Commands
|
|||||||
{
|
{
|
||||||
private readonly IBoardEcsSyncService boardEcsSyncService;
|
private readonly IBoardEcsSyncService boardEcsSyncService;
|
||||||
private readonly IBoardService boardService;
|
private readonly IBoardService boardService;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
private readonly IGameStateService gameStateService;
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGameTimerService timerService;
|
||||||
|
|
||||||
public StartGameCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService)
|
public StartGameCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
|
||||||
{
|
{
|
||||||
this.boardService = boardService;
|
this.boardService = boardService;
|
||||||
this.boardEcsSyncService = boardEcsSyncService;
|
this.boardEcsSyncService = boardEcsSyncService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
this.gameStateService = gameStateService;
|
this.gameStateService = gameStateService;
|
||||||
|
this.timerService = timerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(StartGameCommand command)
|
public void Handle(StartGameCommand command)
|
||||||
{
|
{
|
||||||
|
pauseService.Resume();
|
||||||
|
timerService.Reset();
|
||||||
boardService.InitializeEmptyBoard();
|
boardService.InitializeEmptyBoard();
|
||||||
gameStateService.SetState(GameState.Preparing);
|
gameStateService.SetState(GameState.Preparing);
|
||||||
boardEcsSyncService.SyncBoard(boardService);
|
boardEcsSyncService.SyncBoard(boardService);
|
||||||
@@ -45,16 +51,23 @@ namespace Minesweeper.Commands
|
|||||||
private readonly IBoardEcsSyncService boardEcsSyncService;
|
private readonly IBoardEcsSyncService boardEcsSyncService;
|
||||||
private readonly IBoardService boardService;
|
private readonly IBoardService boardService;
|
||||||
private readonly IGameStateService gameStateService;
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
|
|
||||||
public OpenCellCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService)
|
public OpenCellCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService, IGamePauseService pauseService)
|
||||||
{
|
{
|
||||||
this.boardService = boardService;
|
this.boardService = boardService;
|
||||||
this.boardEcsSyncService = boardEcsSyncService;
|
this.boardEcsSyncService = boardEcsSyncService;
|
||||||
this.gameStateService = gameStateService;
|
this.gameStateService = gameStateService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(OpenCellCommand command)
|
public void Handle(OpenCellCommand command)
|
||||||
{
|
{
|
||||||
|
if (pauseService.IsPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var state = gameStateService.Current;
|
var state = gameStateService.Current;
|
||||||
if (state != GameState.Preparing && state != GameState.Playing)
|
if (state != GameState.Preparing && state != GameState.Playing)
|
||||||
{
|
{
|
||||||
@@ -103,16 +116,23 @@ namespace Minesweeper.Commands
|
|||||||
private readonly IBoardEcsSyncService boardEcsSyncService;
|
private readonly IBoardEcsSyncService boardEcsSyncService;
|
||||||
private readonly IBoardService boardService;
|
private readonly IBoardService boardService;
|
||||||
private readonly IGameStateService gameStateService;
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
|
|
||||||
public ToggleFlagCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService)
|
public ToggleFlagCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService, IGamePauseService pauseService)
|
||||||
{
|
{
|
||||||
this.boardService = boardService;
|
this.boardService = boardService;
|
||||||
this.boardEcsSyncService = boardEcsSyncService;
|
this.boardEcsSyncService = boardEcsSyncService;
|
||||||
this.gameStateService = gameStateService;
|
this.gameStateService = gameStateService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(ToggleFlagCommand command)
|
public void Handle(ToggleFlagCommand command)
|
||||||
{
|
{
|
||||||
|
if (pauseService.IsPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var state = gameStateService.Current;
|
var state = gameStateService.Current;
|
||||||
if (state != GameState.Preparing && state != GameState.Playing)
|
if (state != GameState.Preparing && state != GameState.Playing)
|
||||||
{
|
{
|
||||||
@@ -134,17 +154,23 @@ namespace Minesweeper.Commands
|
|||||||
{
|
{
|
||||||
private readonly IBoardEcsSyncService boardEcsSyncService;
|
private readonly IBoardEcsSyncService boardEcsSyncService;
|
||||||
private readonly IBoardService boardService;
|
private readonly IBoardService boardService;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
private readonly IGameStateService gameStateService;
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGameTimerService timerService;
|
||||||
|
|
||||||
public RestartCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService)
|
public RestartCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
|
||||||
{
|
{
|
||||||
this.boardService = boardService;
|
this.boardService = boardService;
|
||||||
this.boardEcsSyncService = boardEcsSyncService;
|
this.boardEcsSyncService = boardEcsSyncService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
this.gameStateService = gameStateService;
|
this.gameStateService = gameStateService;
|
||||||
|
this.timerService = timerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(RestartCommand command)
|
public void Handle(RestartCommand command)
|
||||||
{
|
{
|
||||||
|
pauseService.Resume();
|
||||||
|
timerService.Reset();
|
||||||
boardService.InitializeEmptyBoard();
|
boardService.InitializeEmptyBoard();
|
||||||
gameStateService.SetState(GameState.Preparing);
|
gameStateService.SetState(GameState.Preparing);
|
||||||
boardEcsSyncService.SyncBoard(boardService);
|
boardEcsSyncService.SyncBoard(boardService);
|
||||||
@@ -154,31 +180,58 @@ namespace Minesweeper.Commands
|
|||||||
|
|
||||||
public sealed class PauseCommandHandler : IGameCommandHandler<PauseCommand>
|
public sealed class PauseCommandHandler : IGameCommandHandler<PauseCommand>
|
||||||
{
|
{
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
|
private readonly IGameStateService gameStateService;
|
||||||
|
|
||||||
|
public PauseCommandHandler(IGamePauseService pauseService, IGameStateService gameStateService)
|
||||||
|
{
|
||||||
|
this.pauseService = pauseService;
|
||||||
|
this.gameStateService = gameStateService;
|
||||||
|
}
|
||||||
|
|
||||||
public void Handle(PauseCommand command)
|
public void Handle(PauseCommand command)
|
||||||
{
|
{
|
||||||
|
if (gameStateService.Current == GameState.Playing)
|
||||||
|
{
|
||||||
|
pauseService.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ResumeCommandHandler : IGameCommandHandler<ResumeCommand>
|
public sealed class ResumeCommandHandler : IGameCommandHandler<ResumeCommand>
|
||||||
{
|
{
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
|
|
||||||
|
public ResumeCommandHandler(IGamePauseService pauseService)
|
||||||
|
{
|
||||||
|
this.pauseService = pauseService;
|
||||||
|
}
|
||||||
|
|
||||||
public void Handle(ResumeCommand command)
|
public void Handle(ResumeCommand command)
|
||||||
{
|
{
|
||||||
|
pauseService.Resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class GoToMenuCommandHandler : IGameCommandHandler<GoToMenuCommand>
|
public sealed class GoToMenuCommandHandler : IGameCommandHandler<GoToMenuCommand>
|
||||||
{
|
{
|
||||||
private readonly IBoardEcsSyncService boardEcsSyncService;
|
private readonly IBoardEcsSyncService boardEcsSyncService;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
private readonly IGameStateService gameStateService;
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGameTimerService timerService;
|
||||||
|
|
||||||
public GoToMenuCommandHandler(IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService)
|
public GoToMenuCommandHandler(IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
|
||||||
{
|
{
|
||||||
this.boardEcsSyncService = boardEcsSyncService;
|
this.boardEcsSyncService = boardEcsSyncService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
this.gameStateService = gameStateService;
|
this.gameStateService = gameStateService;
|
||||||
|
this.timerService = timerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(GoToMenuCommand command)
|
public void Handle(GoToMenuCommand command)
|
||||||
{
|
{
|
||||||
|
pauseService.Resume();
|
||||||
|
timerService.Reset();
|
||||||
gameStateService.SetState(GameState.FieldSelection);
|
gameStateService.SetState(GameState.FieldSelection);
|
||||||
boardEcsSyncService.SyncGameState(gameStateService.Current, false);
|
boardEcsSyncService.SyncGameState(gameStateService.Current, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Minesweeper.Core
|
||||||
|
{
|
||||||
|
public sealed class GamePauseService : IGamePauseService
|
||||||
|
{
|
||||||
|
public event Action<bool> PauseChanged;
|
||||||
|
|
||||||
|
public bool IsPaused { get; private set; }
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
if (IsPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsPaused = true;
|
||||||
|
PauseChanged?.Invoke(IsPaused);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
if (!IsPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsPaused = false;
|
||||||
|
PauseChanged?.Invoke(IsPaused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 40441c28481279147959eafabd8a032a
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using VContainer.Unity;
|
||||||
|
|
||||||
|
namespace Minesweeper.Core
|
||||||
|
{
|
||||||
|
public sealed class GameTimerService : IGameTimerService, ITickable
|
||||||
|
{
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
|
private readonly IGameStateService gameStateService;
|
||||||
|
private int lastReportedSeconds = -1;
|
||||||
|
|
||||||
|
public GameTimerService(IGameStateService gameStateService, IGamePauseService pauseService)
|
||||||
|
{
|
||||||
|
this.gameStateService = gameStateService;
|
||||||
|
this.pauseService = pauseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<float> TimeChanged;
|
||||||
|
|
||||||
|
public float ElapsedSeconds { get; private set; }
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
if (gameStateService.Current != GameState.Playing || pauseService.IsPaused)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElapsedSeconds += Time.deltaTime;
|
||||||
|
var seconds = Mathf.FloorToInt(ElapsedSeconds);
|
||||||
|
if (seconds == lastReportedSeconds)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastReportedSeconds = seconds;
|
||||||
|
TimeChanged?.Invoke(ElapsedSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
ElapsedSeconds = 0f;
|
||||||
|
lastReportedSeconds = -1;
|
||||||
|
TimeChanged?.Invoke(ElapsedSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ed8262be24a32a04abfd5bc5ec8544bb
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Minesweeper.Core
|
||||||
|
{
|
||||||
|
public interface IGamePauseService
|
||||||
|
{
|
||||||
|
event Action<bool> PauseChanged;
|
||||||
|
|
||||||
|
bool IsPaused { get; }
|
||||||
|
|
||||||
|
void Pause();
|
||||||
|
void Resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 82dfb9fe1e7004f4f88df366f8e76b2d
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Minesweeper.Core
|
||||||
|
{
|
||||||
|
public interface IGameTimerService
|
||||||
|
{
|
||||||
|
event Action<float> TimeChanged;
|
||||||
|
|
||||||
|
float ElapsedSeconds { get; }
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 61242d395cb1d974daffd9e0815ec34c
|
||||||
@@ -16,18 +16,38 @@ namespace Minesweeper.Infrastructure
|
|||||||
public sealed class MinesweeperLifetimeScope : LifetimeScope
|
public sealed class MinesweeperLifetimeScope : LifetimeScope
|
||||||
{
|
{
|
||||||
[SerializeField] private MinesweeperGameConfig gameConfig;
|
[SerializeField] private MinesweeperGameConfig gameConfig;
|
||||||
|
[SerializeField] private MainMenuView mainMenuView;
|
||||||
|
[SerializeField] private GameView gameView;
|
||||||
|
|
||||||
protected override void Configure(IContainerBuilder builder)
|
protected override void Configure(IContainerBuilder builder)
|
||||||
{
|
{
|
||||||
builder.RegisterInstance(GetConfig());
|
builder.RegisterInstance(GetConfig());
|
||||||
builder.Register<GameStateService>(Lifetime.Singleton).As<IGameStateService>();
|
builder.Register<GameStateService>(Lifetime.Singleton).As<IGameStateService>();
|
||||||
builder.Register<BoardService>(Lifetime.Singleton).As<IBoardService>();
|
builder.Register<BoardService>(Lifetime.Singleton).As<IBoardService>();
|
||||||
|
builder.Register<GamePauseService>(Lifetime.Singleton).As<IGamePauseService>();
|
||||||
|
builder.Register<GameTimerService>(Lifetime.Singleton).As<IGameTimerService>().As<ITickable>();
|
||||||
builder.Register<BoardEcsSyncService>(Lifetime.Singleton).As<IBoardEcsSyncService>();
|
builder.Register<BoardEcsSyncService>(Lifetime.Singleton).As<IBoardEcsSyncService>();
|
||||||
builder.Register<GameReadModel>(Lifetime.Singleton).As<IGameReadModel>();
|
builder.Register<GameReadModel>(Lifetime.Singleton).As<IGameReadModel>();
|
||||||
builder.Register<GameStateViewAdapter>(Lifetime.Singleton).As<IGameStateViewAdapter>();
|
builder.Register<GameStateViewAdapter>(Lifetime.Singleton).As<IGameStateViewAdapter>();
|
||||||
builder.Register<CellViewFactory>(Lifetime.Singleton).As<ICellViewFactory>();
|
builder.Register<CellViewFactory>(Lifetime.Singleton).As<ICellViewFactory>();
|
||||||
builder.Register<NullMainMenuView>(Lifetime.Singleton).As<IMainMenuView>();
|
|
||||||
builder.Register<NullGameView>(Lifetime.Singleton).As<IGameView>();
|
if (mainMenuView != null)
|
||||||
|
{
|
||||||
|
builder.RegisterComponent(mainMenuView).As<IMainMenuView>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.Register<NullMainMenuView>(Lifetime.Singleton).As<IMainMenuView>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameView != null)
|
||||||
|
{
|
||||||
|
builder.RegisterComponent(gameView).As<IGameView>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.Register<NullGameView>(Lifetime.Singleton).As<IGameView>();
|
||||||
|
}
|
||||||
|
|
||||||
builder.Register<SelectFieldCommandHandler>(Lifetime.Singleton);
|
builder.Register<SelectFieldCommandHandler>(Lifetime.Singleton);
|
||||||
builder.Register<StartGameCommandHandler>(Lifetime.Singleton);
|
builder.Register<StartGameCommandHandler>(Lifetime.Singleton);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Minesweeper.Commands;
|
using Minesweeper.Commands;
|
||||||
|
using Minesweeper.Core;
|
||||||
using Minesweeper.Presentation.ReadModels;
|
using Minesweeper.Presentation.ReadModels;
|
||||||
using Minesweeper.Presentation.Views;
|
using Minesweeper.Presentation.Views;
|
||||||
|
|
||||||
@@ -7,24 +8,39 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
public sealed class GamePresenter : IPresenter
|
public sealed class GamePresenter : IPresenter
|
||||||
{
|
{
|
||||||
private readonly IGameCommandDispatcher commandDispatcher;
|
private readonly IGameCommandDispatcher commandDispatcher;
|
||||||
|
private readonly IGamePauseService pauseService;
|
||||||
private readonly IGameReadModel readModel;
|
private readonly IGameReadModel readModel;
|
||||||
|
private readonly IGameStateService gameStateService;
|
||||||
|
private readonly IGameTimerService timerService;
|
||||||
private readonly IGameView view;
|
private readonly IGameView view;
|
||||||
|
private bool boardBuilt;
|
||||||
|
|
||||||
public GamePresenter(IGameCommandDispatcher commandDispatcher, IGameReadModel readModel, IGameView view = null)
|
public GamePresenter(IGameCommandDispatcher commandDispatcher, IGamePauseService pauseService, IGameReadModel readModel, IGameStateService gameStateService, IGameTimerService timerService, IGameView view = null)
|
||||||
{
|
{
|
||||||
this.commandDispatcher = commandDispatcher;
|
this.commandDispatcher = commandDispatcher;
|
||||||
|
this.pauseService = pauseService;
|
||||||
this.readModel = readModel;
|
this.readModel = readModel;
|
||||||
|
this.gameStateService = gameStateService;
|
||||||
|
this.timerService = timerService;
|
||||||
this.view = view;
|
this.view = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_ = readModel.State;
|
|
||||||
|
|
||||||
if (view != null)
|
if (view != null)
|
||||||
{
|
{
|
||||||
view.RestartRequested += OnRestartRequested;
|
view.RestartRequested += OnRestartRequested;
|
||||||
view.GoToMenuRequested += OnGoToMenuRequested;
|
view.GoToMenuRequested += OnGoToMenuRequested;
|
||||||
|
view.PauseRequested += OnPauseRequested;
|
||||||
|
view.ResumeRequested += OnResumeRequested;
|
||||||
|
view.CellOpenRequested += OnCellOpenRequested;
|
||||||
|
view.CellFlagRequested += OnCellFlagRequested;
|
||||||
|
gameStateService.StateChanged += OnStateChanged;
|
||||||
|
pauseService.PauseChanged += OnPauseChanged;
|
||||||
|
timerService.TimeChanged += OnTimeChanged;
|
||||||
|
OnStateChanged(gameStateService.Current);
|
||||||
|
OnPauseChanged(pauseService.IsPaused);
|
||||||
|
OnTimeChanged(timerService.ElapsedSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,17 +50,112 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
{
|
{
|
||||||
view.RestartRequested -= OnRestartRequested;
|
view.RestartRequested -= OnRestartRequested;
|
||||||
view.GoToMenuRequested -= OnGoToMenuRequested;
|
view.GoToMenuRequested -= OnGoToMenuRequested;
|
||||||
|
view.PauseRequested -= OnPauseRequested;
|
||||||
|
view.ResumeRequested -= OnResumeRequested;
|
||||||
|
view.CellOpenRequested -= OnCellOpenRequested;
|
||||||
|
view.CellFlagRequested -= OnCellFlagRequested;
|
||||||
|
gameStateService.StateChanged -= OnStateChanged;
|
||||||
|
pauseService.PauseChanged -= OnPauseChanged;
|
||||||
|
timerService.TimeChanged -= OnTimeChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRestartRequested()
|
private void OnRestartRequested()
|
||||||
{
|
{
|
||||||
commandDispatcher.Dispatch(new RestartCommand());
|
commandDispatcher.Dispatch(new RestartCommand());
|
||||||
|
RebuildBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGoToMenuRequested()
|
private void OnGoToMenuRequested()
|
||||||
{
|
{
|
||||||
commandDispatcher.Dispatch(new GoToMenuCommand());
|
commandDispatcher.Dispatch(new GoToMenuCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnPauseRequested()
|
||||||
|
{
|
||||||
|
commandDispatcher.Dispatch(new PauseCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnResumeRequested()
|
||||||
|
{
|
||||||
|
commandDispatcher.Dispatch(new ResumeCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCellOpenRequested(int x, int y)
|
||||||
|
{
|
||||||
|
commandDispatcher.Dispatch(new OpenCellCommand(x, y));
|
||||||
|
RefreshBoard();
|
||||||
|
UpdateBoardInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCellFlagRequested(int x, int y)
|
||||||
|
{
|
||||||
|
commandDispatcher.Dispatch(new ToggleFlagCommand(x, y));
|
||||||
|
RefreshBoard();
|
||||||
|
UpdateBoardInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStateChanged(GameState state)
|
||||||
|
{
|
||||||
|
if (state == GameState.FieldSelection)
|
||||||
|
{
|
||||||
|
boardBuilt = false;
|
||||||
|
view.HideGame();
|
||||||
|
view.HidePause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.ShowGame();
|
||||||
|
|
||||||
|
if (!boardBuilt || state == GameState.Preparing)
|
||||||
|
{
|
||||||
|
RebuildBoard();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RefreshBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateBoardInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPauseChanged(bool isPaused)
|
||||||
|
{
|
||||||
|
if (isPaused)
|
||||||
|
{
|
||||||
|
view.ShowPause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
view.HidePause();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateBoardInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTimeChanged(float seconds)
|
||||||
|
{
|
||||||
|
view.SetTimer(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RebuildBoard()
|
||||||
|
{
|
||||||
|
var cells = readModel.GetCells();
|
||||||
|
view.SetMineCount(readModel.MinesCount);
|
||||||
|
view.RebuildBoard(cells, readModel.Width, readModel.Height);
|
||||||
|
boardBuilt = true;
|
||||||
|
UpdateBoardInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshBoard()
|
||||||
|
{
|
||||||
|
view.RefreshBoard(readModel.GetCells());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBoardInput()
|
||||||
|
{
|
||||||
|
var state = gameStateService.Current;
|
||||||
|
view.SetBoardInputEnabled(!pauseService.IsPaused && (state == GameState.Preparing || state == GameState.Playing));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Minesweeper.Commands;
|
using Minesweeper.Commands;
|
||||||
|
using Minesweeper.Core;
|
||||||
using Minesweeper.Presentation.Views;
|
using Minesweeper.Presentation.Views;
|
||||||
|
|
||||||
namespace Minesweeper.Presentation.Presenters
|
namespace Minesweeper.Presentation.Presenters
|
||||||
@@ -6,11 +7,13 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
public sealed class MainMenuPresenter : IPresenter
|
public sealed class MainMenuPresenter : IPresenter
|
||||||
{
|
{
|
||||||
private readonly IGameCommandDispatcher commandDispatcher;
|
private readonly IGameCommandDispatcher commandDispatcher;
|
||||||
|
private readonly IGameStateService gameStateService;
|
||||||
private readonly IMainMenuView view;
|
private readonly IMainMenuView view;
|
||||||
|
|
||||||
public MainMenuPresenter(IGameCommandDispatcher commandDispatcher, IMainMenuView view = null)
|
public MainMenuPresenter(IGameCommandDispatcher commandDispatcher, IGameStateService gameStateService, IMainMenuView view = null)
|
||||||
{
|
{
|
||||||
this.commandDispatcher = commandDispatcher;
|
this.commandDispatcher = commandDispatcher;
|
||||||
|
this.gameStateService = gameStateService;
|
||||||
this.view = view;
|
this.view = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,6 +22,8 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
if (view != null)
|
if (view != null)
|
||||||
{
|
{
|
||||||
view.StartClicked += OnStartClicked;
|
view.StartClicked += OnStartClicked;
|
||||||
|
gameStateService.StateChanged += OnStateChanged;
|
||||||
|
OnStateChanged(gameStateService.Current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +32,7 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
if (view != null)
|
if (view != null)
|
||||||
{
|
{
|
||||||
view.StartClicked -= OnStartClicked;
|
view.StartClicked -= OnStartClicked;
|
||||||
|
gameStateService.StateChanged -= OnStateChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,5 +40,17 @@ namespace Minesweeper.Presentation.Presenters
|
|||||||
{
|
{
|
||||||
commandDispatcher.Dispatch(new StartGameCommand());
|
commandDispatcher.Dispatch(new StartGameCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStateChanged(GameState state)
|
||||||
|
{
|
||||||
|
if (state == GameState.FieldSelection)
|
||||||
|
{
|
||||||
|
view.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
view.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using Minesweeper.Core;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Minesweeper.Presentation.Views
|
||||||
|
{
|
||||||
|
public sealed class CellView : MonoBehaviour, IPointerClickHandler
|
||||||
|
{
|
||||||
|
[SerializeField] private Button button;
|
||||||
|
[SerializeField] private Image image;
|
||||||
|
[SerializeField] private TMP_Text label;
|
||||||
|
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
private bool inputEnabled = true;
|
||||||
|
|
||||||
|
public event Action<int, int> OpenRequested;
|
||||||
|
public event Action<int, int> FlagRequested;
|
||||||
|
|
||||||
|
public void Bind(Button button, Image image, TMP_Text label)
|
||||||
|
{
|
||||||
|
this.button = button;
|
||||||
|
this.image = image;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(int x, int y)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInputEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
inputEnabled = enabled;
|
||||||
|
if (button != null)
|
||||||
|
{
|
||||||
|
button.interactable = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(BoardCellData cell, float pixelsPerUnitMultiplier)
|
||||||
|
{
|
||||||
|
gameObject.name = $"bt_{cell.X}_{cell.Y}_{cell.DisplayValue}";
|
||||||
|
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
image.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
|
||||||
|
image.color = cell.IsOpened ? new Color(0.78f, 0.78f, 0.78f) : Color.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
{
|
||||||
|
if (cell.IsFlagged)
|
||||||
|
{
|
||||||
|
label.text = "F";
|
||||||
|
}
|
||||||
|
else if (!cell.IsOpened)
|
||||||
|
{
|
||||||
|
label.text = string.Empty;
|
||||||
|
}
|
||||||
|
else if (cell.IsMine)
|
||||||
|
{
|
||||||
|
label.text = "M";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label.text = cell.NeighborMines == 0 ? string.Empty : cell.NeighborMines.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPointerClick(PointerEventData eventData)
|
||||||
|
{
|
||||||
|
if (!inputEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventData.button == PointerEventData.InputButton.Left)
|
||||||
|
{
|
||||||
|
OpenRequested?.Invoke(x, y);
|
||||||
|
}
|
||||||
|
else if (eventData.button == PointerEventData.InputButton.Right)
|
||||||
|
{
|
||||||
|
FlagRequested?.Invoke(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2904d462d22809c499afe1842f6e6239
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Minesweeper.Core;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Minesweeper.Presentation.Views
|
||||||
|
{
|
||||||
|
public sealed class GameView : MonoBehaviour, IGameView
|
||||||
|
{
|
||||||
|
[SerializeField] private GameObject gameRoot;
|
||||||
|
[SerializeField] private GameObject pauseRoot;
|
||||||
|
[SerializeField] private RectTransform boardPanel;
|
||||||
|
[SerializeField] private GridLayoutGroup gridLayoutGroup;
|
||||||
|
[SerializeField] private Button pauseButton;
|
||||||
|
[SerializeField] private Button restartButton;
|
||||||
|
[SerializeField] private Button resumeButton;
|
||||||
|
[SerializeField] private Button mainMenuButton;
|
||||||
|
[SerializeField] private TMP_Text timerText;
|
||||||
|
[SerializeField] private TMP_Text mineText;
|
||||||
|
[SerializeField] private float spacing = 2f;
|
||||||
|
[SerializeField] private float basePixelsPerUnitCellSize = 32f;
|
||||||
|
|
||||||
|
private readonly Dictionary<int, CellView> cellsByCoordinate = new Dictionary<int, CellView>();
|
||||||
|
private bool boardInputEnabled = true;
|
||||||
|
private float currentPixelsPerUnitMultiplier = 1f;
|
||||||
|
|
||||||
|
public event Action RestartRequested;
|
||||||
|
public event Action GoToMenuRequested;
|
||||||
|
public event Action PauseRequested;
|
||||||
|
public event Action ResumeRequested;
|
||||||
|
public event Action<int, int> CellOpenRequested;
|
||||||
|
public event Action<int, int> CellFlagRequested;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (gameRoot == null)
|
||||||
|
{
|
||||||
|
gameRoot = gameObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
AddButtonListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
RemoveButtonListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowGame()
|
||||||
|
{
|
||||||
|
gameRoot.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideGame()
|
||||||
|
{
|
||||||
|
gameRoot.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowPause()
|
||||||
|
{
|
||||||
|
if (pauseRoot != null)
|
||||||
|
{
|
||||||
|
pauseRoot.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HidePause()
|
||||||
|
{
|
||||||
|
if (pauseRoot != null)
|
||||||
|
{
|
||||||
|
pauseRoot.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTimer(float seconds)
|
||||||
|
{
|
||||||
|
if (timerText != null)
|
||||||
|
{
|
||||||
|
timerText.text = Mathf.FloorToInt(seconds).ToString("000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMineCount(int minesCount)
|
||||||
|
{
|
||||||
|
if (mineText != null)
|
||||||
|
{
|
||||||
|
mineText.text = minesCount.ToString("000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RebuildBoard(IReadOnlyList<BoardCellData> cells, int width, int height)
|
||||||
|
{
|
||||||
|
ClearBoard();
|
||||||
|
ConfigureGrid(width, height);
|
||||||
|
|
||||||
|
for (var i = 0; i < cells.Count; i++)
|
||||||
|
{
|
||||||
|
CreateCell(cells[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshBoard(cells);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshBoard(IReadOnlyList<BoardCellData> cells)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < cells.Count; i++)
|
||||||
|
{
|
||||||
|
var cell = cells[i];
|
||||||
|
if (cellsByCoordinate.TryGetValue(ToKey(cell.X, cell.Y), out var view))
|
||||||
|
{
|
||||||
|
view.Render(cell, currentPixelsPerUnitMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBoardInputEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
boardInputEnabled = enabled;
|
||||||
|
foreach (var cell in cellsByCoordinate.Values)
|
||||||
|
{
|
||||||
|
cell.SetInputEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddButtonListeners()
|
||||||
|
{
|
||||||
|
if (pauseButton != null)
|
||||||
|
{
|
||||||
|
pauseButton.onClick.AddListener(OnPauseClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restartButton != null)
|
||||||
|
{
|
||||||
|
restartButton.onClick.AddListener(OnRestartClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resumeButton != null)
|
||||||
|
{
|
||||||
|
resumeButton.onClick.AddListener(OnResumeClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainMenuButton != null)
|
||||||
|
{
|
||||||
|
mainMenuButton.onClick.AddListener(OnMainMenuClicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveButtonListeners()
|
||||||
|
{
|
||||||
|
if (pauseButton != null)
|
||||||
|
{
|
||||||
|
pauseButton.onClick.RemoveListener(OnPauseClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restartButton != null)
|
||||||
|
{
|
||||||
|
restartButton.onClick.RemoveListener(OnRestartClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resumeButton != null)
|
||||||
|
{
|
||||||
|
resumeButton.onClick.RemoveListener(OnResumeClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainMenuButton != null)
|
||||||
|
{
|
||||||
|
mainMenuButton.onClick.RemoveListener(OnMainMenuClicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureGrid(int width, int height)
|
||||||
|
{
|
||||||
|
if (gridLayoutGroup == null || boardPanel == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas.ForceUpdateCanvases();
|
||||||
|
|
||||||
|
var rect = boardPanel.rect;
|
||||||
|
var panelWidth = rect.width > 0f ? rect.width : 512f;
|
||||||
|
var panelHeight = rect.height > 0f ? rect.height : 512f;
|
||||||
|
var padding = gridLayoutGroup.padding;
|
||||||
|
var availableWidth = panelWidth - padding.left - padding.right - spacing * Mathf.Max(0, width - 1);
|
||||||
|
var availableHeight = panelHeight - padding.top - padding.bottom - spacing * Mathf.Max(0, height - 1);
|
||||||
|
var cellSize = Mathf.Floor(Mathf.Min(availableWidth / width, availableHeight / height));
|
||||||
|
cellSize = Mathf.Max(8f, cellSize);
|
||||||
|
|
||||||
|
gridLayoutGroup.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
||||||
|
gridLayoutGroup.constraintCount = width;
|
||||||
|
gridLayoutGroup.spacing = new Vector2(spacing, spacing);
|
||||||
|
gridLayoutGroup.cellSize = new Vector2(cellSize, cellSize);
|
||||||
|
currentPixelsPerUnitMultiplier = Mathf.Clamp(basePixelsPerUnitCellSize / cellSize, 0.25f, 4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCell(BoardCellData cell)
|
||||||
|
{
|
||||||
|
var go = new GameObject($"bt_{cell.X}_{cell.Y}_{cell.DisplayValue}", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button));
|
||||||
|
go.transform.SetParent(gridLayoutGroup.transform, false);
|
||||||
|
|
||||||
|
var labelGo = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI));
|
||||||
|
labelGo.transform.SetParent(go.transform, false);
|
||||||
|
var labelRect = (RectTransform)labelGo.transform;
|
||||||
|
labelRect.anchorMin = Vector2.zero;
|
||||||
|
labelRect.anchorMax = Vector2.one;
|
||||||
|
labelRect.offsetMin = Vector2.zero;
|
||||||
|
labelRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
|
var label = labelGo.GetComponent<TextMeshProUGUI>();
|
||||||
|
label.alignment = TextAlignmentOptions.Center;
|
||||||
|
label.enableAutoSizing = true;
|
||||||
|
label.fontSizeMin = 6f;
|
||||||
|
label.fontSizeMax = 32f;
|
||||||
|
label.color = Color.black;
|
||||||
|
|
||||||
|
var view = go.AddComponent<CellView>();
|
||||||
|
view.Bind(go.GetComponent<Button>(), go.GetComponent<Image>(), label);
|
||||||
|
view.Initialize(cell.X, cell.Y);
|
||||||
|
view.SetInputEnabled(boardInputEnabled);
|
||||||
|
view.OpenRequested += OnCellOpenRequested;
|
||||||
|
view.FlagRequested += OnCellFlagRequested;
|
||||||
|
cellsByCoordinate[ToKey(cell.X, cell.Y)] = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearBoard()
|
||||||
|
{
|
||||||
|
foreach (var cell in cellsByCoordinate.Values)
|
||||||
|
{
|
||||||
|
if (cell != null)
|
||||||
|
{
|
||||||
|
cell.OpenRequested -= OnCellOpenRequested;
|
||||||
|
cell.FlagRequested -= OnCellFlagRequested;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cellsByCoordinate.Clear();
|
||||||
|
|
||||||
|
if (gridLayoutGroup == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = gridLayoutGroup.transform.childCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Destroy(gridLayoutGroup.transform.GetChild(i).gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCellOpenRequested(int x, int y)
|
||||||
|
{
|
||||||
|
CellOpenRequested?.Invoke(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCellFlagRequested(int x, int y)
|
||||||
|
{
|
||||||
|
CellFlagRequested?.Invoke(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPauseClicked()
|
||||||
|
{
|
||||||
|
PauseRequested?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRestartClicked()
|
||||||
|
{
|
||||||
|
RestartRequested?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnResumeClicked()
|
||||||
|
{
|
||||||
|
ResumeRequested?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMainMenuClicked()
|
||||||
|
{
|
||||||
|
GoToMenuRequested?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ToKey(int x, int y)
|
||||||
|
{
|
||||||
|
return (y << 16) ^ x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1c906a10872edd04480e534703fc4fea
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Minesweeper.Core;
|
||||||
|
|
||||||
namespace Minesweeper.Presentation.Views
|
namespace Minesweeper.Presentation.Views
|
||||||
{
|
{
|
||||||
@@ -6,5 +8,19 @@ namespace Minesweeper.Presentation.Views
|
|||||||
{
|
{
|
||||||
event Action RestartRequested;
|
event Action RestartRequested;
|
||||||
event Action GoToMenuRequested;
|
event Action GoToMenuRequested;
|
||||||
|
event Action PauseRequested;
|
||||||
|
event Action ResumeRequested;
|
||||||
|
event Action<int, int> CellOpenRequested;
|
||||||
|
event Action<int, int> CellFlagRequested;
|
||||||
|
|
||||||
|
void ShowGame();
|
||||||
|
void HideGame();
|
||||||
|
void ShowPause();
|
||||||
|
void HidePause();
|
||||||
|
void SetMineCount(int minesCount);
|
||||||
|
void SetTimer(float seconds);
|
||||||
|
void RebuildBoard(IReadOnlyList<BoardCellData> cells, int width, int height);
|
||||||
|
void RefreshBoard(IReadOnlyList<BoardCellData> cells);
|
||||||
|
void SetBoardInputEnabled(bool enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,8 @@ namespace Minesweeper.Presentation.Views
|
|||||||
public interface IMainMenuView : IView
|
public interface IMainMenuView : IView
|
||||||
{
|
{
|
||||||
event Action StartClicked;
|
event Action StartClicked;
|
||||||
|
|
||||||
|
void Show();
|
||||||
|
void Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Minesweeper.Presentation.Views
|
||||||
|
{
|
||||||
|
public sealed class MainMenuView : MonoBehaviour, IMainMenuView
|
||||||
|
{
|
||||||
|
[SerializeField] private GameObject root;
|
||||||
|
[SerializeField] private Button startButton;
|
||||||
|
|
||||||
|
public event Action StartClicked;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
root = gameObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
if (startButton != null)
|
||||||
|
{
|
||||||
|
startButton.onClick.AddListener(OnStartClicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
if (startButton != null)
|
||||||
|
{
|
||||||
|
startButton.onClick.RemoveListener(OnStartClicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
root.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Hide()
|
||||||
|
{
|
||||||
|
root.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartClicked()
|
||||||
|
{
|
||||||
|
StartClicked?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bb899c7e47cd4e341b0258dac3f7a238
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Minesweeper.Core;
|
||||||
|
|
||||||
namespace Minesweeper.Presentation.Views
|
namespace Minesweeper.Presentation.Views
|
||||||
{
|
{
|
||||||
@@ -15,5 +17,65 @@ namespace Minesweeper.Presentation.Views
|
|||||||
add { }
|
add { }
|
||||||
remove { }
|
remove { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event Action PauseRequested
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action ResumeRequested
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<int, int> CellOpenRequested
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<int, int> CellFlagRequested
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowPause()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HidePause()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMineCount(int minesCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTimer(float seconds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RebuildBoard(IReadOnlyList<BoardCellData> cells, int width, int height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshBoard(IReadOnlyList<BoardCellData> cells)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBoardInputEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,13 @@ namespace Minesweeper.Presentation.Views
|
|||||||
add { }
|
add { }
|
||||||
remove { }
|
remove { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Hide()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user