/// <summary> /// Метод проверяет столкновение с яблоком /// </summary> /// <returns></returns> private bool IsAte() { if (GameAuxFunctions.VDist(applePosition, playerPosition[0]) < AppleOffs) { return(true); } return(false); }
/// <summary> /// Метод проверяет съедение объекта /// Функция возвращает в качестве X номер элемента для удаления, /// в качестве Y - номер текстуры, от которого зависит количество очков /// </summary> /// <returns></returns> private Vector2 IsAte() { for (int i = 0; i < eatable.Count; i++) { if (GameAuxFunctions.VDist(playerPosition, eatable[i].Position) < (playerAnimation.FrameWidth + eatableTextures[0].Width) / 2 - 20) { return(new Vector2(i, eatable[i].TextureNumber)); } } // Не было съедения return(new Vector2(-1, 0)); }
///////////////////////////////////////////////////////////////////////////////// // ПРОВЕРКА СТОЛКНОВЕНИЙ /// <summary> /// Метод проверяет столкновение данной точки с любой точкой стенок или тела змейки /// </summary> /// <param name="Collaptor">Проверяемая точка</param> /// <param name="WithBody">Проверка столкновения с телом</param> private bool IsCollapted(Vector2 Collaptor, bool WithBody) { // Чтобы не тестировать с каждым обновлением все камни уровня, // имеет смысл проверить только те клетки игры, которые находятся // на минимальном расстоянии от головы. Таких должно быть всего // четыре: на StoneOffs вверх, влево, вправо и вниз. По координатам // таких смещений легко посчитать масштабный индекс массива для // ближайшей позиции и проверить её collision Vector2[] V1 = new Vector2[] { new Vector2(Collaptor.X / Tile.Width + StoneOffs, Collaptor.Y / Tile.Height + StoneOffs), new Vector2(Collaptor.X / Tile.Width + StoneOffs, Collaptor.Y / Tile.Height - StoneOffs), new Vector2(Collaptor.X / Tile.Width - StoneOffs, Collaptor.Y / Tile.Height + StoneOffs), new Vector2(Collaptor.X / Tile.Width - StoneOffs, Collaptor.Y / Tile.Height - StoneOffs) }; // Проверка на столкновение со стенами for (int i = 0; i < V1.Length; i++) { // Вынужденное ограничение индекса (исключение может возникнуть // при генерации нового яблока) if (level.Tiles[(int)V1[i].X % (int)level.LevelSize.X, (int)V1[i].Y % (int)level.LevelSize.Y].Collision == TileCollision.Stone) { collaptedOn.X = (int)V1[i].X * Tile.Width + Tile.Width / 2; collaptedOn.Y = (int)V1[i].Y * Tile.Height + Tile.Width / 2; return(true); } } // Проверка на столкновение с собой (если требуется) if (WithBody) { for (int i = 1; i < playerPosition.Count; i++) { if (GameAuxFunctions.VDist(Collaptor, playerPosition[i]) < BodyOffs) { return(true); } } } // Не было столкновений return(false); }
/// <summary> /// Отображение сообщения об уровне /// </summary> private void ShowLevelMessage() { string S1 = string.Format("УРОВЕНЬ {0,2:D}", levelNumber + 1), S2 = "Нажмите Пробел,", S3 = "чтобы начать"; Vector2 V1 = new Vector2((BackBufferWidth - midFont.MeasureString(S1).X) / 2, (BackBufferHeight - 180) / 2) + level.CameraPosition, V2 = new Vector2((BackBufferWidth - defFont.MeasureString(S2).X) / 2, (BackBufferHeight + 60) / 2) + level.CameraPosition, V3 = new Vector2((BackBufferWidth - defFont.MeasureString(S3).X) / 2, (BackBufferHeight + 110) / 2) + level.CameraPosition; spriteBatch.Draw(messageBack, GameAuxFunctions.CenterOf(messageBackLeftTop, level.CameraPosition), TurtleGameColors.LBlue_B); spriteBatch.DrawString(midFont, S1, V1, TurtleGameColors.LBlue); spriteBatch.DrawString(defFont, S2, V2, TurtleGameColors.Orange); spriteBatch.DrawString(defFont, S3, V3, TurtleGameColors.Orange); }
/// <summary> /// Отображение запроса на подтверждение выхода /// </summary> private void ShowExitMessage() { string S1 = "Вы действительно хотите", S2 = "завершить игру?", S3 = "Нажмите Y, чтобы выйти из игры,", S4 = "или N, чтобы вернуться"; Vector2 V1 = new Vector2((BackBufferWidth - midFont.MeasureString(S1).X) / 2, (BackBufferHeight - 180) / 2) + level.CameraPosition, V2 = new Vector2((BackBufferWidth - midFont.MeasureString(S2).X) / 2, (BackBufferHeight - 110) / 2) + level.CameraPosition, V3 = new Vector2((BackBufferWidth - defFont.MeasureString(S3).X) / 2, (BackBufferHeight + 70) / 2) + level.CameraPosition, V4 = new Vector2((BackBufferWidth - defFont.MeasureString(S4).X) / 2, (BackBufferHeight + 110) / 2) + level.CameraPosition; spriteBatch.Draw(messageBack, GameAuxFunctions.CenterOf(messageBackLeftTop, level.CameraPosition), TurtleGameColors.Yellow_B); spriteBatch.DrawString(midFont, S1, V1, TurtleGameColors.Yellow); spriteBatch.DrawString(midFont, S2, V2, TurtleGameColors.Yellow); spriteBatch.DrawString(defFont, S3, V3, TurtleGameColors.Orange); spriteBatch.DrawString(defFont, S4, V4, TurtleGameColors.Orange); }
/// <summary> /// Отображение сообщения о проигрыше /// </summary> private void ShowLoseMessage() { string S1 = "УРОВЕНЬ", S2 = "НЕ ПРОЙДЕН!", S3 = "Нажмите Пробел,", S4 = "чтобы попробовать снова"; Vector2 V1 = new Vector2((BackBufferWidth - midFont.MeasureString(S1).X) / 2, (BackBufferHeight - 180) / 2) + level.CameraPosition, V2 = new Vector2((BackBufferWidth - midFont.MeasureString(S2).X) / 2, (BackBufferHeight - 110) / 2) + level.CameraPosition, V3 = new Vector2((BackBufferWidth - defFont.MeasureString(S3).X) / 2, (BackBufferHeight + 60) / 2) + level.CameraPosition, V4 = new Vector2((BackBufferWidth - defFont.MeasureString(S4).X) / 2, (BackBufferHeight + 110) / 2) + level.CameraPosition; spriteBatch.Draw(messageBack, GameAuxFunctions.CenterOf(messageBackLeftTop, level.CameraPosition), TurtleGameColors.Red_B); spriteBatch.DrawString(midFont, S1, V1, TurtleGameColors.Red); spriteBatch.DrawString(midFont, S2, V2, TurtleGameColors.Red); spriteBatch.DrawString(defFont, S3, V3, TurtleGameColors.Orange); spriteBatch.DrawString(defFont, S4, V4, TurtleGameColors.Orange); }
/// <summary> /// Метод отрисовывает уровень игры /// </summary> /// <param name="VGameTime">Время игры</param> protected override void Draw(GameTime VGameTime) { // Создание чистого окна и запуск рисования graphics.GraphicsDevice.Clear(SnakeGameColors.DGreen); spriteBatch.Begin(); // В ЗАВИСИМОСТИ ОТ СОСТОЯНИЯ ИГРЫ switch (gameStatus) { ////////////////////////////////////////////////////////////////// case GameStatus.Start: ShowStartMessage(); break; ////////////////////////////////////////////////////////////////// case GameStatus.Help: ShowHelpMessage(); break; ////////////////////////////////////////////////////////////////// case GameStatus.Playing: // ОТОБРАЖЕНИЕ УРОВНЯ level.Draw(VGameTime, spriteBatch, playerPosition[0]); // ОТОБРАЖЕНИЕ АНИМИРОВАННЫХ ИХОБРАЖЕНИЙ // Яблоко appleAnimator.Draw(VGameTime, spriteBatch, applePosition, SpriteEffects.None, SnakeGameColors.White, 0.0); // Тело змейки for (int n = 1; n < playerPosition.Count; n++) { bodyAnimator.Draw(VGameTime, spriteBatch, playerPosition[n], SpriteEffects.None, SnakeGameColors.White, 0.0); } // Голова змейки headAnimator.Draw(VGameTime, spriteBatch, playerPosition[0], SpriteEffects.None, SnakeGameColors.White, // Изменение угла поворота текстуры Math.Acos(Math.Sign(playerTo.X)) * GameAuxFunctions.NNSign(playerTo.Y, true)); // ОТОБРАЖЕНИЕ ИНФОРМАЦИИ DrawInfo(); // Отображение сообщений Vector2 backBufferSize = new Vector2(SnakeGame.BackBufferWidth, SnakeGame.BackBufferHeight); if (showLevelMsg) { messageBackAnimator.Draw(VGameTime, spriteBatch, GameAuxFunctions.CenterOf(backBufferSize, level.CameraPosition), SpriteEffects.None, SnakeGameColors.LBlue_B, 0.0); ShowLevelMessage(); } if (showWinMsg) { messageBackAnimator.Draw(VGameTime, spriteBatch, GameAuxFunctions.CenterOf(backBufferSize, level.CameraPosition), SpriteEffects.None, SnakeGameColors.Green_B, 0.0); ShowWinMessage(); } if (showLoseMsg) { messageBackAnimator.Draw(VGameTime, spriteBatch, GameAuxFunctions.CenterOf(backBufferSize, level.CameraPosition), SpriteEffects.None, SnakeGameColors.Red_B, 0.0); ShowLoseMessage(); } if (showExitMsg) { messageBackAnimator.Draw(VGameTime, spriteBatch, GameAuxFunctions.CenterOf(backBufferSize, level.CameraPosition), SpriteEffects.None, SnakeGameColors.Yellow_B, 0.0); ShowExitMessage(); } break; ////////////////////////////////////////////////////////////////// case GameStatus.Finish: ShowFinishMessage(); break; } // Отключение устройства рисования spriteBatch.End(); // Перерисовка base.Draw(VGameTime); }
///////////////////////////////////////////////////////////////////////////////// // ПРОРИСОВКА ИГРОВОГО ПОЛЯ /// <summary> /// Метод отрисовывает информационное поле игры (очки, уровень, состояние) /// </summary> private void DrawInfo() { string S1, S2 = String.Format(" В розыгрыше: {0,4:D} ", currentScore), S3 = String.Format(" Выигрыш: {0,6:D} ", score), S4 = String.Format(" Съедено: {0,5:D} ", ateApples), S5 = String.Format(" Осталось съесть: {0,2:D} ", applesQuantity - currentScore / SMult); if (isWorking) { S1 = String.Format(" УРОВЕНЬ {0,2:D} ", levelNumber + 1); } else { S1 = " ПАУЗА "; } float StrUp = Tile.Height * 0.15f, StrDown = BackBufferHeight - Tile.Height * 0.8f; // Векторы позиций для отображения элементов учитывают смещение камеры наблюдения Vector2 V1 = new Vector2(BackBufferWidth * 0.05f, StrUp) + level.CameraPosition, V2 = new Vector2(BackBufferWidth * 0.21f, StrUp) + level.CameraPosition, V3 = new Vector2(BackBufferWidth * 0.50f, StrUp) + level.CameraPosition, V4 = new Vector2(BackBufferWidth * 0.80f, StrUp) + level.CameraPosition, V5 = new Vector2(BackBufferWidth * 0.05f, StrDown) + level.CameraPosition, V6 = new Vector2(BackBufferWidth * 0.89f, StrDown) + level.CameraPosition, V7 = new Vector2(BackBufferWidth * 0.92f, StrDown) + level.CameraPosition; DrawShadowedString(defFont, S1, V1, SnakeGameColors.LRed); DrawShadowedString(defFont, S2, V2, SnakeGameColors.Yellow); DrawShadowedString(defFont, S3, V3, SnakeGameColors.Green); DrawShadowedString(defFont, S4, V4, SnakeGameColors.LBlue); // Если игра идёт, выводить строку "осталось съесть" if (isAlive) { DrawShadowedString(defFont, S5, V5, SnakeGameColors.Silver); } // Если есть музыка или звук, выводить соответствующий знак if (isMusic) { DrawShadowedString(defFont, "[\x266B]", V6, SnakeGameColors.Yellow); } else { DrawShadowedString(defFont, "[\x266B]", V6, SnakeGameColors.Black); } if (isSound) { DrawShadowedString(defFont, "[\x266A]", V7, SnakeGameColors.Yellow); } else { DrawShadowedString(defFont, "[\x266A]", V7, SnakeGameColors.Black); } // КОМПАС // Смена цвета стрелки компаса Color compasColor = SnakeGameColors.CompasRed; if (GameAuxFunctions.VDist(playerPosition[0], applePosition) < GameAuxFunctions.VDist(compasOffs, applePosition)) { compasColor = SnakeGameColors.CompasGreen; } // Положение стрелки компаса compasOffs = playerPosition[0]; compasPosition.X = (int)playerPosition[0].X; compasPosition.Y = (int)playerPosition[0].Y; Vector2 V8 = applePosition - playerPosition[0]; // Формула движения стрелки компаса и её отображение compasTurn = (float)Math.Acos(V8.X / GameAuxFunctions.VDist(V8, Vector2.Zero)) * GameAuxFunctions.NNSign(V8.Y, true); spriteBatch.Draw(compas, compasPosition, compasSize, compasColor, compasTurn, new Vector2(compas.Width, compas.Height) / 2, SpriteEffects.None, 0.0f); }
/// <summary> /// Метод отрисовывает уровень игры /// </summary> /// <param name="VGameTime"></param> protected override void Draw(GameTime VGameTime) { // Создание чистого окна и запуск рисования graphics.GraphicsDevice.Clear(TurtleGameColors.Black); spriteBatch.Begin(); // В ЗАВИСИМОСТИ ОТ СОСТОЯНИЯ ИГРЫ switch (gameStatus) { ////////////////////////////////////////////////////////////////// case GameStatus.Start: // Отображает стартовый экран ShowStartMessage(); break; ////////////////////////////////////////////////////////////////// case GameStatus.Help: ShowHelpMessage(); break; ////////////////////////////////////////////////////////////////// case GameStatus.Playing: // ОТОБРАЖЕНИЕ УРОВНЯ level.Draw(VGameTime, spriteBatch, playerPosition); // ОТОБРАЖЕНИЕ ИЗОБРАЖЕНИЙ // Съедобные объекты for (int i = 0; i < eatable.Count; i++) { spriteBatch.Draw(eatableTextures[eatable[i].TextureNumber], eatable[i].DestinationRect, eatable[i].SourceRect, TurtleGameColors.White, eatable[i].Turn, eatable[i].Origin, SpriteEffects.None, 0.0f); } // Игрок (над ними) playerAnimator.Draw(VGameTime, spriteBatch, playerPosition, SpriteEffects.None, TurtleGameColors.White, // Изменение угла поворота текстуры Math.Acos(playerTo.X) * GameAuxFunctions.NNSign(playerTo.Y, false)); // Автомобили (ещё выше) for (int i = 0; i < carPosition.Count; i++) { spriteBatch.Draw(carTextures[carPosition[i].TextureNumber], carPosition[i].DestinationRect, carPosition[i].SourceRect, TurtleGameColors.White, carPosition[i].Turn, carPosition[i].Origin, SpriteEffects.None, 0.0f); } // ОТОБРАЖЕНИЕ ИНФОРМАЦИИ УРОВНЯ DrawInfo(); // Отображение сообщений (если они вызваны) if (showLevelMsg) { ShowLevelMessage(); } if (showWinMsg) { ShowWinMessage(); } if (showLoseMsg) { ShowLoseMessage(); } if (showExitMsg) { ShowExitMessage(); } break; ////////////////////////////////////////////////////////////////// case GameStatus.Finish: ShowFinishMessage(); break; } // Завершение рисования spriteBatch.End(); // Перерисовка base.Draw(VGameTime); }