[Add] GameLoop base

This commit is contained in:
2026-03-18 09:13:48 +07:00
parent c819c0d045
commit 537ae1ce5c
28 changed files with 997 additions and 40 deletions
+138 -36
View File
@@ -2,58 +2,105 @@ using System;
using UnityEngine;
using VContainer;
using YachtDice.Categories;
using YachtDice.Run;
using YachtDice.Scoring;
namespace YachtDice.Game
{
public class GameLoopController : MonoBehaviour
{
[Header("Settings")]
[SerializeField] private int maxRollsPerTurn = 3;
private DiceManager _diceManager;
private RunLoopService _runLoopService;
private ScoringSystem _scoringSystem;
public int CurrentRoll { get; private set; }
public int CurrentTurn { get; private set; }
public int MaxRollsPerTurn => maxRollsPerTurn;
public int CurrentRoll => _runLoopService != null ? _runLoopService.State.CurrentRoll : 0;
public int CurrentTurn => _runLoopService != null ? _runLoopService.State.StageNumber : 0;
public int CurrentBet => _runLoopService != null ? _runLoopService.State.BetIndex : 0;
public int CurrentStage => _runLoopService != null ? _runLoopService.State.StageNumber : 0;
public int CurrentStageTarget => _runLoopService != null ? _runLoopService.State.CurrentStageTarget : 0;
public int CurrentBaseQuota => _runLoopService != null ? _runLoopService.State.BaseQuota : 0;
public int StoredRolls => _runLoopService != null ? _runLoopService.State.StoredRolls : 0;
public int MaxRollsPerTurn => _runLoopService != null ? _runLoopService.State.CurrentStageRollBudget : 0;
public RunPhase CurrentPhase => _runLoopService != null ? _runLoopService.State.Phase : RunPhase.None;
public bool CanRoll => CurrentRoll < maxRollsPerTurn && !_diceManager.IsAnyRolling;
public bool CanScore => CurrentRoll > 0 && !_diceManager.IsAnyRolling;
public bool IsGameOver => _scoringSystem.IsComplete;
public bool CanRoll => _runLoopService != null && _runLoopService.CanRoll() && !_diceManager.IsAnyRolling;
public bool CanScore => _runLoopService != null && CurrentPhase == RunPhase.CategorySelection && !_diceManager.IsAnyRolling;
public bool IsGameOver => _runLoopService != null && _runLoopService.State.IsFailed;
public bool IsShopOpen => CurrentPhase == RunPhase.Shop;
public event Action<int> OnTurnStarted;
public event Action<int> OnRollComplete;
public event Action<CategoryDefinition, int> OnScored;
public event Action<int> OnGameOver;
public event Action<int> OnBetStarted;
public event Action OnShopOpened;
public event Action OnShopClosed;
public event Action<int> OnStoredRollsChanged;
public event Action<int> OnCurrencyChanged;
public event Action<int> OnQuotaChanged;
public event Action<int, int> OnCycleCompleted;
public event Action<RunPhase> OnPhaseChanged;
[Inject]
public void Construct(DiceManager diceManager, ScoringSystem scoringSystem)
public void Construct(DiceManager diceManager, RunLoopService runLoopService, ScoringSystem scoringSystem)
{
this._diceManager = diceManager;
this._scoringSystem = scoringSystem;
_diceManager = diceManager;
_runLoopService = runLoopService;
_scoringSystem = scoringSystem;
_runLoopService.OnStageStarted += HandleStageStarted;
_runLoopService.OnStageCleared += HandleStageCleared;
_runLoopService.OnRunFailed += HandleRunFailed;
_runLoopService.OnBetStarted += HandleBetStarted;
_runLoopService.OnShopOpened += HandleShopOpened;
_runLoopService.OnStoredRollsChanged += HandleStoredRollsChanged;
_runLoopService.OnCurrencyChanged += HandleCurrencyChanged;
_runLoopService.OnQuotaChanged += HandleQuotaChanged;
_runLoopService.OnCycleCompleted += HandleCycleCompleted;
_runLoopService.OnPhaseChanged += HandlePhaseChanged;
}
private void OnDestroy()
{
if (_runLoopService == null)
return;
_runLoopService.OnStageStarted -= HandleStageStarted;
_runLoopService.OnStageCleared -= HandleStageCleared;
_runLoopService.OnRunFailed -= HandleRunFailed;
_runLoopService.OnBetStarted -= HandleBetStarted;
_runLoopService.OnShopOpened -= HandleShopOpened;
_runLoopService.OnStoredRollsChanged -= HandleStoredRollsChanged;
_runLoopService.OnCurrencyChanged -= HandleCurrencyChanged;
_runLoopService.OnQuotaChanged -= HandleQuotaChanged;
_runLoopService.OnCycleCompleted -= HandleCycleCompleted;
_runLoopService.OnPhaseChanged -= HandlePhaseChanged;
}
public void StartNewGame()
{
_scoringSystem.ResetScorecard();
CurrentTurn = 0;
StartNewTurn();
_diceManager.UnlockAll();
_runLoopService.StartNewRun();
}
private void StartNewTurn()
public void CompleteShop()
{
CurrentTurn++;
CurrentRoll = 0;
_diceManager.UnlockAll();
OnTurnStarted?.Invoke(CurrentTurn);
if (!IsShopOpen)
return;
_runLoopService.CompleteShop();
OnShopClosed?.Invoke();
}
public void Roll()
{
if (!CanRoll) return;
if (!CanRoll)
return;
if (!_runLoopService.TryBeginRoll())
return;
CurrentRoll++;
_diceManager.OnAllDiceSettled += HandleAllDiceSettled;
_diceManager.RollUnlocked();
}
@@ -61,6 +108,7 @@ namespace YachtDice.Game
private void HandleAllDiceSettled()
{
_diceManager.OnAllDiceSettled -= HandleAllDiceSettled;
_runLoopService.NotifyRollResolved(_diceManager.GetDice());
OnRollComplete?.Invoke(CurrentRoll);
}
@@ -71,25 +119,79 @@ namespace YachtDice.Game
_diceManager.ToggleLock(index);
}
public void ScoreInCategory(CategoryDefinition category)
public bool CanScoreCategory(CategoryDefinition category)
{
if (!CanScore) return;
if (_scoringSystem.IsCategoryUsed(category)) return;
return _runLoopService != null && _runLoopService.CanScoreCategory(_diceManager.GetDice(), category);
}
var dice = _diceManager.GetDice();
var result = _scoringSystem.ScoreCategory(dice, category);
public ScoreResult PreviewCategory(CategoryDefinition category)
{
return _runLoopService.PreviewScore(_diceManager.GetDice(), category);
}
public async void ScoreInCategory(CategoryDefinition category)
{
if (!CanScore)
return;
await _runLoopService.TryScoreCategoryAsync(_diceManager.GetDice(), category);
}
public bool CanOpenShopManually()
{
return IsShopOpen;
}
private void HandleStageStarted(RunStageState stage)
{
_diceManager.UnlockAll();
OnTurnStarted?.Invoke(stage.Index + 1);
}
private void HandleStageCleared(RunStageState stage, CategoryDefinition category, ScoreResult result)
{
_diceManager.UnlockAll();
OnScored?.Invoke(category, result.FinalScore);
}
if (_scoringSystem.IsComplete)
{
var total = _scoringSystem.TotalScore;
OnGameOver?.Invoke(total);
}
else
{
StartNewTurn();
}
private void HandleRunFailed(RunState state)
{
OnGameOver?.Invoke(_scoringSystem != null ? _scoringSystem.TotalScore : 0);
}
private void HandleBetStarted(RunState state)
{
OnBetStarted?.Invoke(state.BetIndex);
}
private void HandleShopOpened(RunState state)
{
OnShopOpened?.Invoke();
}
private void HandleStoredRollsChanged(int value)
{
OnStoredRollsChanged?.Invoke(value);
}
private void HandleCurrencyChanged(int value)
{
OnCurrencyChanged?.Invoke(value);
}
private void HandleQuotaChanged(int value)
{
OnQuotaChanged?.Invoke(value);
}
private void HandleCycleCompleted(int bonus, int storedRolls)
{
OnCycleCompleted?.Invoke(bonus, storedRolls);
}
private void HandlePhaseChanged(RunPhase phase)
{
OnPhaseChanged?.Invoke(phase);
}
}
}