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< Назад | Оглавление | Далее >

Сайт управляется системой uCoz