Опубликован: 14.08.2012 | Доступ: свободный | Студентов: 880 / 20 | Оценка: 5.00 / 5.00 | Длительность: 09:59:00
Специальности: Программист
Самостоятельная работа 14:

Пользовательский интерфейс в XNA

Этот класс использует класс Menu (листинг 20.4.), основная цель которого – удобное представление данных об отдельных пунктах меню, которых, в нашем случае, три.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace P14_1
{
    //Класс для хранения данных об элементах меню
    public class Menu
    {
        public Texture2D imageTexture;
        public Rectangle imageRectangle;
        public Color color;
        public Menu(Game game, Texture2D _texture, Rectangle _rectangle, Color _color)
        {
            imageTexture = _texture;
            imageRectangle = _rectangle;
            color = _color;
        }

    }
}
Листинг 20.4. Код класса Menu

Здесь мы лишь храним данные по отдельным элементам меню.

Экран меню вы можете видеть на рис. 20.3.

Экран меню

Рис. 20.3. Экран меню

Экран справки реализован в виде класса HelpScreen, листинг 20.5. Здесь мы выводим фоновое изображение и надпись, выполненную графическими средствами.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace P14_1
{
    class HelpScreen: Screen
    {
        //Текстуры для фона и справочной надписи
        Texture2D backTexture;
        Rectangle backRectangle;
        Texture2D helpTexture;
        Rectangle helpRectangle;

        public HelpScreen(Game game, Texture2D _back, Texture2D _help, Rectangle _backRec, Rectangle _helpRec)
            : base(game)
        {
            backTexture = _back;
            helpTexture = _help;
            backRectangle = _backRec;
            helpRectangle = _helpRec;
        }
        public override void Draw(GameTime gameTime)
        {
            //Выводим изображения
            sprBatch.Draw(backTexture, backRectangle, Color.White);
            sprBatch.Draw(helpTexture, helpRectangle, Color.White);
            base.Draw(gameTime);
        }
    }
}
Листинг 20.5. Код класса HelpScreen

Экран справки вы можете видеть на рис. 20.4.

Экран игровой справки

Рис. 20.4. Экран игровой справки

Основная игровая программа реализована в классе GameScreen, листинг 20.6.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;

namespace P14_1
{
    class GameScreen: Screen
    {
        private Texture2D sprTexture;
        private Rectangle sprRectangle;
        private Vector2 sprPosition;

        public GameScreen(Game game, ref Texture2D newTexture,
            Rectangle newRectangle, Vector2 newPosition)
            : base(game)
        {
            sprTexture = newTexture;
            sprRectangle = newRectangle;
            sprPosition = newPosition;
           
        }

        public override void Update(GameTime gameTime)
        {
            //Обработаем касание
            TouchCollection touchLocations = TouchPanel.GetState();
            foreach (TouchLocation touchLocation in touchLocations)
            {
                if (touchLocation.State == TouchLocationState.Pressed)
                {
                    sprPosition = touchLocation.Position;
                }
            }
            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            sprBatch.Draw(sprTexture, sprPosition, sprRectangle, Color.White);
            base.Draw(gameTime);
        }
    }
}
Листинг 20.6. Код класса GameScreen

Игровой процесс реализован здесь лишь формально – игровой объект перемещается по экрану в соответствии с позицией, которой коснулся пользователь. Игровой экран вы можете видеть на рис. 20.5.

Основной игровой экран

Рис. 20.5. Основной игровой экран

Управление игровыми объектами, обработка ввода для целей перемещения между экранами, реализована в классе Game1, листинг 20.7.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;

namespace P14_1
{
    /// <summary>
    /// Это главный тип игры
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //Стартовый экран
        SplashScreen splash;
        Texture2D splashTexture;
        bool firstSplash = true;
        //Экран справки
        HelpScreen help;
        Texture2D helpBack;
        Texture2D helpText;
        //Экран меню
        MenuScreen menu;
        Texture2D menuBack;
        Texture2D menuGameName;
        Texture2D menuTxtStartGame;
        Texture2D menuTxtHelp;
        Texture2D menuTxtExit;
        //Прямоугольники элементов меню
        Rectangle m1 = new Rectangle(100, 230, 400, 50);
        Rectangle m2 = new Rectangle(100, 320, 400, 50);
        Rectangle m3 = new Rectangle(100, 420, 400, 50);
        //Игровой экран
        GameScreen newGame;
        Texture2D gameBall;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.IsFullScreen = true;
            // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
            // Дополнительный заряд аккумулятора заблокирован.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
        }

        /// <summary>
        /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
        /// Здесь можно запросить нужные службы и загрузить неграфический
        /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
        /// их инициализации.
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();
        }

        /// <summary>
        /// LoadContent будет вызываться в игре один раз; здесь загружается
        /// весь контент.
        /// </summary>
        protected override void LoadContent()
        {
            //Загружаем элементы игры и создаем игровые экраны
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);
            helpBack = Content.Load<Texture2D>("helpBack");
            helpText = Content.Load<Texture2D>("helpText");
            help = new HelpScreen(this, helpBack, helpText,
                new Rectangle(0, 0, this.Window.ClientBounds.Height, this.Window.ClientBounds.Width),
                new Rectangle((this.Window.ClientBounds.Height - helpText.Width) / 2,
                (this.Window.ClientBounds.Width - helpText.Height) / 2,
                helpText.Width, helpText.Height));
            Components.Add(help);
            gameBall = Content.Load<Texture2D>("gameObj");
            newGame = new GameScreen(this, ref gameBall, new Rectangle(0, 0, 176, 176),
                new Vector2(100, 100));
            Components.Add(newGame);
            menuBack = Content.Load<Texture2D>("menuBack");
            menuGameName = Content.Load<Texture2D>("menuGameName");
            menuTxtStartGame = Content.Load<Texture2D>("menuTxtStartGame");
            menuTxtHelp = Content.Load<Texture2D>("menuTxtHelp");
            menuTxtExit = Content.Load<Texture2D>("menuTxtExit");
            menu = new MenuScreen(this, menuBack, menuGameName, menuTxtStartGame, menuTxtHelp,
                menuTxtExit, m1, m2, m3);
            Components.Add(menu);
            splashTexture = Content.Load<Texture2D>("splash");
            splash = new SplashScreen(this, splashTexture, new Rectangle(0, 0, this.Window.ClientBounds.Height,
               this.Window.ClientBounds.Width));
            Components.Add(splash);
            //Отображаем стартовый экран, остальные элементы скрыты
            splash.Show();
        }

        /// <summary>
        /// UnloadContent будет вызываться в игре один раз; здесь выгружается
        /// весь контент.
        /// </summary>
        protected override void UnloadContent()
        {
            // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
        }
        //Проверка попадания касания в область, занимаемую меню
        private bool MenuSelect(Rectangle m, Vector2 p)
        {
            bool res = false;
            if (p.X > m.X && p.X < m.X + m.Width && p.Y > m.Y && p.Y < m.Y + m.Height)
            {
                res = true;
            }

            return res;
        }

        /// <summary>
        /// Позволяет игре запускать логику обновления мира,
        /// проверки столкновений, получения ввода и воспроизведения звуков.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Update(GameTime gameTime)
        {
            //Стартовый экран показываем 2 секунды, после чего показываем
            //меню и отключаем показ стартового экрана
            if (gameTime.TotalGameTime.Seconds > 2 && firstSplash)
            {
                splash.Hide();
                menu.Show();
                firstSplash = false;
            }

            // Позволяет выйти из игры если кнопка Назад нажата в меню
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed && menu.Enabled)
                this.Exit();
            //Позволяет перейти к меню, если находимся на экране игры
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed && newGame.Enabled)
            {
                newGame.Hide();
                menu.Show();
            }
            //Позволяет перейти к меню, если мы находимся на справочном экране
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed && help.Enabled)
            {
                help.Hide();
                menu.Show();
            }
            //Если активен экран меню, проверяем прикосновения к экрану
            if (menu.Enabled)
            {
                TouchCollection touchLocations = TouchPanel.GetState();
                //Если пользователь коснулся экрана и попал в область соответствующего меню
                //Поменяем цвет этого пункта меню
                foreach (TouchLocation touchLocation in touchLocations)
                {
                    if (touchLocation.State == TouchLocationState.Pressed)
                    {
                        if (MenuSelect(m1, touchLocation.Position))
                        {
                            menu.Change(1);
                        }
                        if (MenuSelect(m2, touchLocation.Position))
                        {
                            menu.Change(2);
                        }
                        if (MenuSelect(m3, touchLocation.Position))
                        {
                            menu.Change(3);
                        }
                    }
                    //Если пользователь убрал палец с экрана, продолжая касаться
                    //соответствующего пункта меню
                    if (touchLocation.State == TouchLocationState.Released)
                    {
                        if (MenuSelect(m1, touchLocation.Position))
                        {
                            menu.Hide();
                            newGame.Show();
                        }
                        if (MenuSelect(m2, touchLocation.Position))
                        {
                            menu.Hide();
                            help.Show();
                        }
                        if (MenuSelect(m3, touchLocation.Position))
                        {
                            this.Exit();
                        }
                    }

                }

            }
            base.Update(gameTime);
        }

        /// <summary>
        /// Вызывается, когда игра отрисовывается.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            base.Draw(gameTime);
            spriteBatch.End();
        }
    }
}
Листинг 20.7. Код класса Game1

Особенности работы этого кода раскрыты в комментариях.

20.2. Выводы

В лабораторной работе мы рассмотрели один из методов организации игрового интерфейса, использующего несколько экранов. Помимо представленного метода организации интерфейса пользователя возможны и другие, стандартизированного подхода здесь нет, каждый разработчик создаёт систему игровых экранов сообразно собственным нуждам.

20.3. Задание

Разработайте игровой интерфейс для игры, созданием которой вы занимаетесь.

Гулич Анна
Гулич Анна
Невозможно пройти тесты, в окне с вопросами пусто