/
d4nil
/
Konenkov_2413_Course_Work
Обзор
Документация
Войти
/
d4nil
/
Konenkov_2413_Course_Work
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
Game
TapTapDash.Core/Controllers/GameController.cs
186 строк
7 KB
Konenkov Daniel
feat: добавлена пауза
09 янв 2026, 20:33
09 янв 2026, 20:33
d2e4b4f
Код
Авторство
О чём код?
using System; using System.Threading; using System.Threading.Tasks; using TapTapDash.Core.Models; using TapTapDash.Core.Views; namespace TapTapDash.Core.Controllers; /// <summary> /// Контроллер игры /// Обрабатывает действия пользователя и связывает модель с представлением /// Общая логика для консольной и графической версий /// </summary> public class GameController { private readonly GameModel _model; private readonly IGameView _view; private CancellationTokenSource? _gameLoopCancellationToken; private Task? _gameLoopTask; private const double TargetFps = 30.0; // Целевой FPS (снижено для более плавного обновления) private const double FrameTime = 1.0 / TargetFps; // Время одного кадра /// <summary> /// Событие завершения игры (поражение) /// </summary> public event Action<int>? OnGameOver; // Передает счет /// <summary> /// Событие нажатия кнопки "Главное меню" /// </summary> public event Action? OnBackToMenuPressed; /// <summary> /// Конструктор контроллера /// </summary> /// <param name="model">Модель игры</param> /// <param name="view">Представление игры (любая реализация IGameView)</param> public GameController(GameModel model, IGameView view) { _model = model; _view = view; // Подписываемся на событие нажатия кнопки "Главное меню" _view.OnBackToMenuPressed += () => { OnBackToMenuPressed?.Invoke(); }; } /// <summary> /// Инициализация контроллера и запуск игрового цикла /// </summary> public void Initialize() { // Первоначальное обновление представления _view.UpdateView(); // Запускаем игровой цикл StartGameLoop(); } /// <summary> /// Запуск игрового цикла /// </summary> private void StartGameLoop() { _gameLoopCancellationToken = new CancellationTokenSource(); _gameLoopTask = Task.Run(() => GameLoop(_gameLoopCancellationToken.Token)); } /// <summary> /// Игровой цикл /// </summary> private void GameLoop(CancellationToken cancellationToken) { var lastTime = DateTime.Now; while (!cancellationToken.IsCancellationRequested && _model.Status == GameStatus.Playing) { var currentTime = DateTime.Now; var deltaTime = (currentTime - lastTime).TotalSeconds; lastTime = currentTime; // Ограничиваем максимальное время кадра if (deltaTime > 0.1) { deltaTime = 0.1; } // Обновляем модель игры _model.Update(deltaTime); // Рендеринг теперь происходит в отдельном потоке // _view.UpdateView(); // Убрано - рендеринг в отдельном потоке // Проверяем, не завершилась ли игра if (_model.Status == GameStatus.GameOver) { // Игра завершена, отправляем событие OnGameOver?.Invoke(_model.Score); break; } // Задержка для поддержания целевого FPS var sleepTime = FrameTime - deltaTime; if (sleepTime > 0) { Thread.Sleep((int)(sleepTime * 1000)); } } } /// <summary> /// Обработка выполнения маневра (нажатие пробела) /// </summary> public void HandleManeuver() { if (_model.Status == GameStatus.Playing) { _model.PerformManeuver(); // Рендеринг происходит в отдельном потоке } } /// <summary> /// Обработка паузы (нажатие P) /// </summary> public void HandlePause() { if (_model.Status == GameStatus.Playing) { _model.Pause(); // Останавливаем игровой цикл при паузе Stop(); // Не вызываем _view.UpdateView() здесь, так как рендеринг происходит в отдельном потоке // RenderLoop сам обнаружит изменение статуса и отрисует меню паузы } } /// <summary> /// Обработка продолжения игры (из меню паузы) /// </summary> public void HandleResume() { if (_model.Status == GameStatus.Paused) { _model.Resume(); // Перезапускаем игровой цикл StartGameLoop(); // Рендеринг происходит в отдельном потоке } } /// <summary> /// Обработка возврата в главное меню /// </summary> public void HandleBackToMenu() { // Останавливаем игровой цикл (если еще не остановлен) Stop(); // Вызываем событие возврата в меню OnBackToMenuPressed?.Invoke(); } /// <summary> /// Остановка игры и очистка ресурсов /// </summary> public void Stop() { if (_gameLoopCancellationToken != null && !_gameLoopCancellationToken.IsCancellationRequested) { _gameLoopCancellationToken.Cancel(); _gameLoopTask?.Wait(); // Ждем завершения игрового цикла } _gameLoopCancellationToken?.Dispose(); _gameLoopCancellationToken = null; } /// <summary> /// Получение модели (для доступа из представления) /// </summary> public GameModel GetModel() { return _model; } }