/
Vagabond132
/
TerrariaCourse
Обзор
Документация
Войти
/
Vagabond132
/
TerrariaCourse
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
Windows
Model/GameComponents/GameModel.cs
434 строки
13 KB
Vagabond132
Соглашение
13 янв 2025, 13:34
13 янв 2025, 13:34
8528b00
Код
Авторство
О чём код?
using Model.Blocks; using Model.GameComponents.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Runtime.Intrinsics.X86; using System.Text; using System.Threading.Tasks; namespace Model.GameComponents { /// <summary> /// Модель игры /// </summary> public class GameModel { /// <summary> /// Карта /// </summary> private MapModel _map; /// <summary> /// Игрок /// </summary> private PlayerModel _player; /// <summary> /// Делегат на изменение модели /// </summary> public delegate void dOnChange(); /// <summary> /// Событие изменения модели /// </summary> public event dOnChange OnChange; /// <summary> /// Приватный конструктор для предотвращения создания экземпляров извне /// </summary> public GameModel(string parPlayerName) { Player = new PlayerModel(parPlayerName, new Vector2(370, 100), 1, 1, 3, 3); Map = new MapModel(); } /// <summary>ф /// Модель игрока /// </summary> public PlayerModel Player { get => _player; set => _player = value; } /// <summary> /// Модель карты /// </summary> public MapModel Map { get => _map; set => _map = value; } /// <summary> /// Движение вверх /// </summary> public void GoUp() { if (Player.Pos.Y > 0) { Player.DecreaseYPos(1); OnChange?.Invoke(); //_display.findDisplayPosition(_player.Pos); } } /// <summary> /// Движение вниз /// </summary> /// <param name="parAmout">Насколько сдвинуться вниз</param> public void GoUp(float parAmout) { //if (Player.Pos.Y > 0 && (_map.GetBlock((int)Player.Pos.Y/*(int)(_player.Pos.X)*/, (int)Player.Pos.X) is null)) if (!IsBlockDirectlyAbovePlayer()) { Player.DecreaseYPos(parAmout); OnChange?.Invoke(); //_display.findDisplayPosition(_player.Pos); } } /// <summary> /// Движение вниз /// </summary> public void GoDown() { if (Player.Pos.Y < _map.Height && (_map.GetBlock((int)Player.Pos.Y + Player.PlayerHeight/*(int)(_player.Pos.X)*/, (int)Player.Pos.X + 1) is null)) { Player.IncreaseYPos(1); OnChange?.Invoke(); //_display.findDisplayPosition(_player.Pos); //Console.WriteLine("AAAA = " + _player.Pos.ToString()); } } /// <summary> /// Количество, на которое нужно спускаться /// </summary> /// <param name="parAmount"></param> public void GoDown(float parAmount) { if ((int)(Player.Pos.Y + Player.PlayerHeight) < _map.GetMap.GetLength(0) && (_map.GetBlock((int)Player.Pos.Y + Player.PlayerHeight, (int)Player.Pos.X) is null) && (_map.GetBlock((int)Player.Pos.Y + Player.PlayerHeight, (int)Player.Pos.X + Player.PlayerWidth - 1) is null) ) { Player.IncreaseYPos(parAmount); OnChange?.Invoke(); } } /// <summary> /// Начать производить прыжок /// </summary> public void StartJump() { if (!Player.IsJumping && Player.OnGround && !IsBlockDirectlyAbovePlayer()) { Player.IsJumping = true; Player.OnGround = false; Player.JumpProgress = 0; } } /// <summary> /// Выполнить прыжок /// </summary> /// <param name="parDeltaTime"></param> public void PerformJump(float parDeltaTime) { if (Player.IsJumping && !Player.OnGround) { Player.VerticalVelocity -= (Player.JumpSpeed * parDeltaTime); // Подъем вверх GoUp(Player.JumpSpeed * parDeltaTime); Player.JumpProgress += (Player.JumpSpeed * parDeltaTime); if (Player.JumpProgress >= Player.JumpHeight || IsBlockDirectlyAbovePlayer()) { Player.IsJumping = false; Player.VerticalVelocity = 0; // Обнуляем скорость после завершения прыжка } } } /// <summary> /// Применяет гравитацию к игроку /// </summary> public void ApplyGravity(float parDeltaTime) { if (!Player.IsJumping) { int belowX = (int)Player.Pos.X; int belowY = (int)Player.Pos.Y + Player.PlayerHeight; if (belowY < _map.Height && Map.GetBlock(belowY, belowX) == null && Map.GetBlock(belowY, belowX + 1) == null && Map.GetBlock(belowY, belowX + 2) == null ) { GoDown((_player.GravitySpeed * parDeltaTime)); } else { Player.OnGround = true; } } } /// <summary> /// Прыгнуть /// </summary> public void Jump() { //if (!IsBlockDirectlyAbovePlayer()) //{ StartJump(); //} } /// <summary> /// Обновить позицию игрока /// </summary> public void UpdatePlayerPosition(float parDeltaTime) { if (Player.IsJumping) { PerformJump(parDeltaTime); } else { ApplyGravity(parDeltaTime); } //if (_map.GetBlock((int)(Player.Pos.Y + Player.PlayerHeight - 0.5f), (int)Player.Pos.X+1) != null) // Проверяем справа //{ // GoUp(); //} OnChange?.Invoke(); } /// <summary> /// Движение налево /// </summary> public void GoLeft(float parDeltaTime) { float scaledSpeed = Player.Speed * parDeltaTime; Player.Direction = Direction.LEFT; if (!AreBlocksUnderPlayer()) { Player.OnGround = false; } if (!AreBlocksToLeftOfPlayer() && Player.Pos.X > 0) { Player.DecreaseXPos(scaledSpeed); OnChange?.Invoke(); } } /// <summary> /// Движение направо /// </summary> public void GoRight(float parDeltaTime) { float scaledSpeed = Player.Speed * parDeltaTime; Player.Direction = Direction.RIGHT; if (!AreBlocksUnderPlayer()) { Player.OnGround = false; } if (!AreBlocksToRightOfPlayer() && Player.Pos.X < Map.Width - Player.PlayerWidth - 1) { Player.IncreaseXPos(scaledSpeed); OnChange?.Invoke(); } } /// <summary> /// Сломать блок слева или справо /// </summary> public void BreakBlock() { // Определяем направление игрока int directionOffset = Player.Direction == Direction.RIGHT ? 1 : -1; // Координаты начальной точки разрушения int startX = (int)Player.Pos.X + (directionOffset == 1 ? Player.PlayerWidth : -1); int startY = (int)Player.Pos.Y; if (startX <= 0) { return; } // Ломаем три блока вертикально перед персонажем for (int i = 0; i < 3; i++) { int blockY = startY + i; // Смещаем координаты по вертикали if (_map.GetBlock(blockY, startX) != null) Player.Score += ((AbstractBlock)_map.GetBlock(blockY, startX)).Value; _map.SetAirBlock(blockY, startX); } } /// <summary> /// Сломать блоки снизу /// </summary> public void BreakBlocksBelow() { // Координаты начальной точки разрушения int startX = (int)Player.Pos.X; // Начинаем с левого блока под персонажем int startY = (int)Player.Pos.Y + Player.PlayerHeight; // Блоки под персонажем if (startY >= _map.Height) { return; } // Ломаем три блока горизонтально под персонажем for (int i = 0; i < 3; i++) { int blockX = startX + i; // Смещаем координаты по горизонтали if (_map.GetBlock(startY, blockX) != null) Player.Score += ((AbstractBlock)_map.GetBlock(startY, blockX)).Value; _map.SetAirBlock(startY, blockX); } } /// <summary> /// Сломать блоки сверху /// </summary> public void BreakBlocksAbove() { // Координаты начальной точки разрушения int startY = (int)(Player.Pos.Y) - 1; // Блоки над персонажем int startX = (int)(Player.Pos.X); if (startY <= 0) { return; } // Ломаем три блока горизонтально над персонажем for (int i = 0; i < 3; i++) { int blockX = startX + i; // Смещаем координаты по горизонтали if (_map.GetBlock(startY, blockX) != null) Player.Score += ((AbstractBlock)_map.GetBlock(startY, blockX)).Value; _map.SetAirBlock(startY, blockX); } } /// <summary> /// Проверяет наличие блоков над игроком на высоте одного блока /// </summary> /// <returns>True, если есть хотя бы один блок, иначе false</returns> public bool IsBlockDirectlyAbovePlayer() { int playerX = (int)_player.Pos.X; int playerY = (int)(_player.Pos.Y - 0.2f); int width = _player.PlayerWidth; // Координата строки над головой игрока int aboveY = playerY; // Проверяем, не выходит ли выше верхней границы карты if (aboveY < 0) { return false; } // Проходим по ширине игрока for (int x = playerX; x < playerX + width; x++) { if (_map.GetBlock(aboveY, x) != null) // Если есть блок над игроком { return true; } } return false; // Если блоков нет } /// <summary> /// Проверяет наличие блоков справа от игрока /// </summary> /// <returns>True, если есть хотя бы один блок, иначе false</returns> public bool AreBlocksToRightOfPlayer() { int playerX = (int)_player.Pos.X; int playerY = (int)_player.Pos.Y; int height = _player.PlayerHeight; int width = _player.PlayerWidth; for (int y = playerY; y < playerY + height; y++) // Проходим по высоте игрока { if (playerX + width < _map.Width && _map.GetBlock(y, playerX + width) != null) // Проверяем справа { return true; } } return false; } /// <summary> /// Проверяет наличие блоков справа от игрока /// </summary> /// <returns>True, если есть хотя бы один блок, иначе false</returns> public bool AreBlocksUnderPlayer() { int playerX = (int)_player.Pos.X; int playerY = (int)_player.Pos.Y; int height = _player.PlayerHeight; int width = _player.PlayerWidth; if (playerY + height >= _map.Height) { return true; } for (int x = playerX; x < playerX + width; x++) // Проходим по высоте игрока { if (playerY + height < _map.Width && _map.GetBlock(playerY + height, x) != null) // Проверяем справа { return true; } } return false; } /// <summary> /// Проверяет наличие блоков слева от игрока /// </summary> /// <returns>True, если есть хотя бы один блок, иначе false</returns> public bool AreBlocksToLeftOfPlayer() { int playerX = (int)(_player.Pos.X - 1f); int playerY = (int)_player.Pos.Y; int height = _player.PlayerHeight; for (int y = playerY; y < playerY + height; y++) // Проходим по высоте игрока { if (playerX >= 1 && _map.GetBlock(y, (int)(playerX)) != null) // Проверяем слева { return true; } } return false; } } }