Программируем игры на XNA и MonoGame для Windows 8. Часть 4. Игровые состояния и состояние приложения.

С выходом новой версии MonoGame 3.0.1 информация из статьи могла устареть. Смотрите новые статьи в постах выше.

Если в текущей версии игры мы переведем приложение в режим Snap (когда приложение занимает только левую или правую четверть экрана), мы заметим, что астероиды все так же пытаются летать по маленько экрану. Понятно, что в таком состоянии играть было бы невозможно. Чтобы решить эту проблему мы будем ставить игру на паузу, когда пользователь меняет размер окна.

Чтобы облегчить себе жизнь, я просто «позаимствую» класс для поддержки различных состояний окна отсюда:

http://blogs.msdn.com/b/bobfamiliar/archive/2012/08/07/windows-8-xna-and-monogame-part-3-code-migration-and-windows-8-feature-support.aspx

Нужно только сделать в нем некоторые изменения:

  1. При изменении размеров окна мы будем получать уведомление в виде события.
  2. В оригинальном коде неправильно определялся режим Full. Это можно исправить за счет сохранения начального размера окна. Не уверен, что это хороший способ, но пока он меня устраивает.

Весь будет выглядеть таким образом:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Windows.Foundation;

using Windows.UI.Core;

 

namespace Game1

{

    publicenumEWindowState

    {

        Full = 0,

        Snap1Quarter = 1,

        Snap3Quarter = 2

    }

 

    publicclassWindowStateArgs : EventArgs

    {

        publicEWindowState NewValue { get; set; }

    }

 

    publicstaticclassWindowState

    {

        publicdelegatevoidWindowStateEventHandler(WindowStateArgs args);

        publicstaticeventWindowStateEventHandler SizeChanged;

        publicstaticEWindowState _windowState;

        publicstaticCoreWindow _window;

        publicstaticRect _windowsBounds;

 

        publicstaticvoid Initialize()

        {

            _window = CoreWindow.GetForCurrentThread();

            _windowsBounds = _window.Bounds;

            _windowState = EWindowState.Full;

            _window.SizeChanged += _window_SizeChanged;

        }

 

        //called when the window is resized

        staticvoid _window_SizeChanged(CoreWindow sender, WindowSizeChangedEventArgs args)

        {

            if (args.Size.Width == _windowsBounds.Width)

            {

                _windowState = EWindowState.Full;

            }

            elseif (args.Size.Width <= 320.00)

            {

                _windowState = EWindowState.Snap1Quarter;

            }

            else

            {

                _windowState = EWindowState.Snap3Quarter;

            }

 

            if (SizeChanged != null)

            {

                SizeChanged(newWindowStateArgs() { NewValue = _windowState });

            }

        }

    }

}

Подписку на событие я помещу в Game1:

        public Game1()

        {

            graphics = newGraphicsDeviceManager(this);

            Content.RootDirectory = «Content»;

 

            WindowState.SizeChanged += WindowState_SizeChanged;

        }

 

        void WindowState_SizeChanged(WindowStateArgs e)

        {

           

        }

 

Теперь добавим поддержку игровых состояний. Для начала сделаем только два состояния: В игре/Пауза (потом можно добавить и другие нужные состояния).

    publicenumEGameState

    {

        Pause,

        Game

    }

 

Теперь добавим в Game1 поддержку состояний.

        EGameState state = EGameState.Game;

 

        void WindowState_SizeChanged(WindowStateArgs e)

        {

            if (e.NewValue == EWindowState.Full)

                state = EGameState.Game;

            else

                state = EGameState.Pause;

        }

Теперь нужно исправить код в Update и Draw так, чтобы астероиды не двигались и не рисовались во время паузы.

        protectedoverridevoid Update(GameTime gameTime)

        {

            if (state == EGameState.Pause)

                return;

 

            // TODO: Add your update logic here

            foreach (var asteroid in asteroids)

            {

                asteroid.Update(gameTime);

            }

 

            base.Update(gameTime);

        }

 

        protectedoverridevoid Draw(GameTime gameTime)

        {

            GraphicsDevice.Clear(newColor(10, 10, 30));

 

            // TODO: Add your drawing code here

            spriteBatch.Begin();

            spriteBatch.Draw(sunTexture, newRectangle(GraphicsDevice.Viewport.Width / 2 — 128, GraphicsDevice.Viewport.Height / 2 — 128, 256, 256), Color.White);

 

            if (state == EGameState.Game)

            {

                foreach (var asteroid in asteroids)

                {

                    spriteBatch.Draw(asteroidTexture, asteroid.Rect, null, Color.White, asteroid.Rotation, newVector2(asteroid.Width / 2, asteroid.Width / 2), SpriteEffects.None, 0);

                }

            }

            if (state == EGameState.Pause)

            {

                var pauseString = «PAUSE»;

                var size = font.MeasureString(pauseString);

                spriteBatch.DrawString(font, pauseString, newVector2(GraphicsDevice.Viewport.Width / 2 — size.X / 2, GraphicsDevice.Viewport.Height / 2 — 100), Color.White);

 

            }

 

            spriteBatch.End();

 

 

            base.Draw(gameTime);

        }

В Draw мы будем писать слово PAUSE вместо всех астероидов.

Сейчас наша игра в режиме Snap должна выглядеть так:

Реклама
Запись опубликована в рубрике Компьютерная графика с метками , , , , , , . Добавьте в закладки постоянную ссылку.

2 комментария на «Программируем игры на XNA и MonoGame для Windows 8. Часть 4. Игровые состояния и состояние приложения.»

  1. Александр:

    На гитхабе есть вариант
    if (ApplicationView.Value == Windows.UI.ViewManagement.ApplicationViewState.FullScreenLandscape)
    {
    _windowState = WindowState.Full;
    }
    else if (ApplicationView.Value == Windows.UI.ViewManagement.ApplicationViewState.Snapped)
    {
    _windowState = WindowState.Snap1Quarter;
    }
    else if (ApplicationView.Value == Windows.UI.ViewManagement.ApplicationViewState.Filled)
    {
    _windowState = WindowState.Snap3Quarter;
    }
    Как оцениваете такой вариант?

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s