netlib.narod.ru | < Назад | Оглавление | Далее > |
Все сцены созданы, и теперь нам надо только показывать их в соответствии с пожеланиями пользователя. Через меню в начальной сцене пользователь может посмотреть сцену помощи, сцену игры (с одним или двумя игроками), или просто покинуть игру. Здесь вы будете использовать технику в которой концентрируете весь ввод, относящийся к навигации или управлению состоянием сцен в одном классе. В данном случае вы используете класс Game1, чтобы у вас была центральная точка, где вы запускаете сцены и управляете состоянием класса Game1. Добавьте в класс Game1 следующий код:
private readonly GraphicsDeviceManager graphics; private SpriteBatch spriteBatch; // Текстуры protected Texture2D helpBackgroundTexture, helpForegroundTexture; protected Texture2D startBackgroundTexture, startElementsTexture; protected Texture2D actionElementsTexture, actionBackgroundTexture; // Игровые сцены protected HelpScene helpScene; protected StartScene startScene; protected ActionScene actionScene; protected GameScene activeScene; // Звуковые ресурсы private AudioComponent audioComponent; // Шрифты private SpriteFont smallFont, largeFont, scoreFont; // Используется для обработки ввода protected KeyboardState oldKeyboardState; protected GamePadState oldGamePadState;
В метод LoadContent добавьте код для создания и загрузки содержимого для объекта ActionScene:
// Создание сцены игры actionElementsTexture = Content.Load<Texture2D>("rockrainenhanced"); actionBackgroundTexture = Content.Load<Texture2D>("SpaceBackground"); scoreFont = Content.Load<SpriteFont>("score"); actionScene = new ActionScene(this, actionElementsTexture, actionBackgroundTexture, scoreFont); Components.Add(actionScene); // Запуск игры с начальной сцены :) startScene.Show(); activeScene = startScene;
И снова в этом классе вы загружаете все игровые ресурсы и инициализируете все сцены, делая StartScene сценой, открываемой изначально.
Метод Update обрабатывает весь пользовательский ввод для каждой сцены и, если необходимо, меняет активную сцену:
/// <summary> /// Позволяет игре выполнять логику, такую как обновление мира, /// проверка столкновений, сбор ввода и воспроизведение звука /// </summary> /// <param name="gameTime">Предоставляет снимок значения таймера</param> protected override void Update(GameTime gameTime) { // Обработка игрового ввода HandleScenesInput(); base.Update(gameTime); }
HandleScenesInput просто вызывает обработчик активной сцены игры:
/// <summary> /// Обработка ввода всех игровых сцен /// </summary> private void HandleScenesInput() { // Обработка ввода начальной сцены if (activeScene == startScene) { HandleStartSceneInput(); } // Обработка ввода сцены помощи else if (activeScene == helpScene) { if (CheckEnterA()) { ShowScene(startScene); } } // Обработка ввода для сцены игры else if (activeScene == actionScene) { HandleActionInput(); } }
Метод CheckEnterA содержит простой код для проверки нажатия клавиши Enter или кнопки A на игровом пульте Xbox 360:
/// <summary> /// Проверка нажатия клавиши Enter или кнопки A /// </summary> /// <returns>true, если нажата клавиша Enter или кнопка A</returns> private bool CheckEnterA() { // Получаем состояние клавиатуры и игрового пульта GamePadState gamepadState = GamePad.GetState(PlayerIndex.One); KeyboardState keyboardState = Keyboard.GetState(); bool result = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter))); result |= (oldGamePadState.Buttons.A == ButtonState.Pressed) && (gamepadState.Buttons.A == ButtonState.Released); oldKeyboardState = keyboardState; oldGamePadState = gamepadState; return result; }
HandleStartSceneInput показывает требуемую сцену в соответствии с выбранным пользователем пунктом меню. Если выбрана игра для двух игроков, вы просто делаете атрибут TwoPlayers в actionScene равным true:
/// <summary> /// Обработка кнопок и клавиатуры в начальной сцене /// </summary> private void HandleStartSceneInput() { if (CheckEnterA()) { audioComponent.PlayCue("menu_select3"); switch (startScene.SelectedMenuIndex) { case 0: actionScene.TwoPlayers = false; ShowScene(actionScene); break; case 1: actionScene.TwoPlayers = true; ShowScene(actionScene); break; case 2: ShowScene(helpScene); break; case 3: Exit(); break; } } }
HandleActionInput обрабатывает ввод в сцене игры для приостановки и прекращения игры с использованием клавиатуры или игрового пульта Xbox 360:
/// <summary> /// Проверяем нажатие клавиши Enter или кнопки A /// </summary> /// <returns>true, если нажата клавиша Enter или кнопка A</returns> private void HandleActionInput() { // Получаем сосотояние клавиатуры и игрового пульта GamePadState gamepadState = GamePad.GetState(PlayerIndex.One); KeyboardState keyboardState = Keyboard.GetState(); bool backKey = (oldKeyboardState.IsKeyDown(Keys.Escape) && (keyboardState.IsKeyUp(Keys.Escape))); backKey |= (oldGamePadState.Buttons.Back == ButtonState.Pressed) && (gamepadState.Buttons.Back == ButtonState.Released); bool enterKey = (oldKeyboardState.IsKeyDown(Keys.Enter) && (keyboardState.IsKeyUp(Keys.Enter))); enterKey |= (oldGamePadState.Buttons.A == ButtonState.Pressed) && (gamepadState.Buttons.A == ButtonState.Released); oldKeyboardState = keyboardState; oldGamePadState = gamepadState; if (enterKey) { if (actionScene.GameOver) { ShowScene(startScene); } else { audioComponent.PlayCue("menu_back"); actionScene.Paused = !actionScene.Paused; } } if (backKey) { ShowScene(startScene); } }
Метод ShowScene является вспомогательным для вызова Show новой сцены и Hide предыдущей, как показано ниже:
/// <summary> /// Открывает новую сцену /// </summary> /// <param name="scene">Открываемая сцена</param> protected void ShowScene(GameScene scene) { activeScene.Hide(); activeScene = scene; scene.Show(); }
А что насчет метода Draw? Сейчас все элементы вашей игры являются GameComponent, так что просто позвольте XNA выполнять его работу:
/// <summary> /// Вызывается, когда игра должна нарисовать себя /// </summary> /// <param name="gameTime">Предоставляет снимок значения таймера</param> protected override void Draw(GameTime gameTime) { // Начинаем spriteBatch.Begin(); // Рисуем все GameComponent base.Draw(gameTime); // Заканчиваем spriteBatch.End(); }
Вот так. Скомпилируйте и запустите игру, чтобы увидеть финальный результат. Архитектура получилась гибкой и к вашей игре легко добавить новые возможности, что вы и увидите в следующей главе. Попробуйте, например, добавить новые типы астероидов или новые способы получения энергии. Вы начнете понимать как игры «собираются» из GameComponent.
netlib.narod.ru | < Назад | Оглавление | Далее > |