/
karachi
/
KPO_CP_CrossyRoad
Обзор
Документация
Войти
/
karachi
/
KPO_CP_CrossyRoad
Код
Запросы
5
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
base
Model/Game/Map.cs
238 строк
7 KB
karachi-23
base
10 янв 2025, 23:55
10 янв 2025, 23:55
f5bd4ec
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; using Model.MathModel; namespace Model.Game { /// <summary> /// Игровое поле /// </summary> public class Map { /// <summary> /// Событие создания машины /// </summary> public event Action<Car>? CarCreated; /// <summary> /// Событие удаления машины /// </summary> public event Action<Car, Player?>? CarDeleted; /// <summary> /// Событие создания нового игрока /// </summary> public event Action<Player>? PlayerCreated; /// <summary> /// Событие смерти игрока /// </summary> public event Action<Player>? PlayerDead; /// <summary> /// Генератор случайных чисел /// </summary> private readonly Random _random = new(); /// <summary> /// Время с последнего обновления максимального рейтинга /// </summary> private float _maxScoreUpdateElapsedTime = 0; /// <summary> /// Ширина /// </summary> public float Width { get; set; } /// <summary> /// Высота /// </summary> public float Height { get; set; } /// <summary> /// Игрок /// </summary> public Player Player { get; set; } = null!; /// <summary> /// Список машин /// </summary> public List<Car> Cars { get; private set; } = new(); /// <summary> /// Прошедшее время /// </summary> public float ElapsedTime { get; private set; } = 0; /// <summary> /// Время сохранения максимального рейтинга (в секундах) /// </summary> private const int MAX_SCORE_UPDATE_TIME = 1; /// <summary> /// Конструктор игрового поля /// </summary> public Map() { } /// <summary> /// Добавление игрока в начало дороги /// </summary> /// <param name="parPlayer">Добавляемый игрок</param> public void AddPlayerOnRoadStart(Player parPlayer) { ResetPlayer(parPlayer); PlayerCreated?.Invoke(parPlayer); } /// <summary> /// Обновление положения машин /// </summary> /// <param name="parCar">Обновляемый игрок</param> /// <param name="parDeltaTime">Временной интервал, на который надо сделать интерполяцию</param> private static void UpdateCarPosition(Car parCar, float parDeltaTime) { Vector2 accelerationPerFrame = new Vector2(parCar.Acceleration.X * parDeltaTime, 0); Vector2 halfSpeedDeltaPerFrame = new Vector2(parCar.Speed.X * parDeltaTime + accelerationPerFrame.X / 2, 0); parCar.Position = new Vector2(parCar.Position.X + halfSpeedDeltaPerFrame.X, parCar.Position.Y); parCar.Speed = new Vector2(parCar.Speed.X + accelerationPerFrame.X, parCar.Speed.Y); } /// <summary> /// Обновление состояния машин /// </summary> /// <param name="parDeltaTime">Изменение внутреннего игрового времени в секундах</param> private void UpdateCars(float parDeltaTime) { foreach (Car elCar in Cars) { UpdateCarPosition(elCar, parDeltaTime); } } /// <summary> /// Создание новых машин /// </summary> private void CreateNewCars() { const int MAX_CARS_COUNT = 6; const int CAR_LENGTH = 7; const float VIEW_HEIGHT = 40; float laneHeight = CAR_LENGTH; HashSet<float> usedLanes = new(); while (Cars.Count < MAX_CARS_COUNT) { Car.CarType type = _random.Next(0, 2) == 0 ? Car.CarType.NormalCar : Car.CarType.ReverseCar; Car car = Car.CreateCar(type); if (!car.IsReverse) { MathFunc.SetRandomPosition(this, car, laneHeight, VIEW_HEIGHT, usedLanes); } else { MathFunc.SetRandomNegativePosition(this, car, laneHeight, VIEW_HEIGHT, usedLanes); } if (car.Position != Vector2.Zero) { Cars.Add(car); CarCreated?.Invoke(car); } } } /// <summary> /// Удаление проехавших машин /// </summary> private void DeletePassedCars() { for (int i = Cars.Count - 1; i >= 0; i--) { Car car = Cars[i]; if (car.Position.X > Width || car.Position.X < 0 ) { Cars.RemoveAt(i); CarDeleted?.Invoke(car, Player); } if (Player.Position.Y < car.Position.Y) { Player.Score += 1; Cars.RemoveAt(i); CarDeleted?.Invoke(car, Player); } } } /// <summary> /// Обновление состояния игры /// </summary> /// <param name="parDeltaTime">Изменение внутреннего игрового времени в секундах</param> public void Update(float parDeltaTime) { DeletePassedCars(); CreateNewCars(); UpdateMaxScore(parDeltaTime); ProcessCrashing(); UpdateCars(parDeltaTime); } /// <summary> /// Обновление счета игрока /// </summary> /// <param name="parDeltaTime">Изменение внутреннего игрового времени в секундах</param> private void UpdateMaxScore(float parDeltaTime) { _maxScoreUpdateElapsedTime += parDeltaTime; if (_maxScoreUpdateElapsedTime >= MAX_SCORE_UPDATE_TIME) { _maxScoreUpdateElapsedTime = 0; if (Player.Score > Player.MaxScore) Player.MaxScore = Player.Score; } } /// <summary> /// Сброс состояния машин /// </summary> private void ResetCars() { for (int i = Cars.Count - 1; i >= 0; i--) { Car car = Cars[i]; Cars.RemoveAt(i); CarDeleted?.Invoke(car, Player); } } /// <summary> /// Сброс игрока /// </summary> private void ResetPlayer(Player parPlayer) { parPlayer.Score = 0; parPlayer.MaxScore = 0; parPlayer.Position = new(Width / 2, Height - parPlayer.Length/3f); } /// <summary> /// Сброс состояния игрового поля /// </summary> public void Reset() { ElapsedTime = 0; ResetCars(); ResetPlayer(Player); } /// <summary> /// Установка позиции игрока /// </summary> /// <param name="parPlayer">Игрок</param> /// <param name="parPosition">Позиция игрока</param> public void SetPositionToPlayer(Player parPlayer, Vector2 parPosition) { parPlayer.Position = new(parPosition.X, parPosition.Y); } /// <summary> /// Обработка аварий /// </summary> private void ProcessCrashing() { for (int i = Cars.Count - 1; i >= 0; i--) { Car car = Cars[i]; if (MathFunc.IsIntersect(Player, car)) { PlayerDead?.Invoke(Player); Reset(); break; } } } } }