using System; using System.Collections.Generic; using Core.Ports; namespace Core.Domain { public class GameSession { private const string HighScoreKey = "HighScore"; private const float NpcSpawnTime = 4f; private const float PowerUpSpawnInterval = 25f; public int Score { get; private set; } public int HighScore { get; private set; } public bool IsGameOver { get; private set; } public event Action OnScoreChanged; public event Action OnOrbSpawned; public event Action OnOrbReset; public event Action OnGameOver; public event Action OnSpawnNpc; public event Action OnSpawnPowerUp; private readonly List _tiles; private readonly IPersistenceService _persistenceService; private readonly Random _rng = new(); private int _playerFloorIndex = 0; private float _timeSinceStart; private bool _npcSpawned; private float _powerUpTimer; public GameSession(List tiles, IPersistenceService persistenceService) { _tiles = tiles; _persistenceService = persistenceService; Score = 0; IsGameOver = false; HighScore = _persistenceService.Load(HighScoreKey, 0); } public void StartGame() { _timeSinceStart = 0f; _powerUpTimer = 0f; _npcSpawned = false; SpawnNextOrb(); } public void Tick(float deltaTime) { if (IsGameOver) return; _timeSinceStart += deltaTime; if (!_npcSpawned && _timeSinceStart >= NpcSpawnTime) { _npcSpawned = true; OnSpawnNpc?.Invoke(); } _powerUpTimer += deltaTime; if (_powerUpTimer >= PowerUpSpawnInterval) { _powerUpTimer = 0f; SpawnRandomPowerUp(); } } public void OrbCollected() { if (IsGameOver) return; Score += 10; OnScoreChanged?.Invoke(Score); SpawnNextOrb(); } private void SpawnNextOrb() { var validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable && t.Floor == _playerFloorIndex ); if (validTiles.Count == 0) { validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable); } if (validTiles.Count == 0) { EndGame(); return; } var pick = validTiles[_rng.Next(validTiles.Count)]; OnOrbSpawned?.Invoke(pick.Id); } public void EndGame() { if (IsGameOver) return; IsGameOver = true; if (Score > HighScore) { HighScore = Score; _persistenceService.Save(HighScoreKey, HighScore); } OnGameOver?.Invoke(); } public void SetPlayerFloor(int floorIndex) { if (_playerFloorIndex == floorIndex) return; _playerFloorIndex = floorIndex; if (IsGameOver) return; OnOrbReset?.Invoke(); SpawnNextOrb(); } private void SpawnRandomPowerUp() { var validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable); if (validTiles.Count == 0) return; var tile = validTiles[_rng.Next(validTiles.Count)]; var type = _rng.Next(0, 2) == 0 ? PowerUpType.LightFooted : PowerUpType.SpeedBoost; OnSpawnPowerUp?.Invoke(type, tile.Id); } } }