Опубликован: 14.08.2012 | Уровень: специалист | Доступ: платный
Самостоятельная работа 13:

Сохранение и загрузка игр, сериализация, работа с файлами

Пользуемся этим объектом мы в основном классе игры, его код приведен в листинге 19.2.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
using Microsoft.Phone.Shell;
using System.IO.IsolatedStorage;

namespace P13_1
{
    /// <summary>
    /// Это главный тип игры
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont myFont;
        String text = "";
        //Объект, хранящий параметры игры
        SavedParam parameters = new SavedParam();
        //Счётчик количества запусков
        int launchCount = 0;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Дополнительный заряд аккумулятора заблокирован.
            InactiveSleepTime = TimeSpan.FromSeconds(1);

            //Получаем объект PhoneApplicationService, связанный с текущим приложением
            PhoneApplicationService appSrv = PhoneApplicationService.Current;
            //Назначаем обработчики событий
            appSrv.Launching += new EventHandler<LaunchingEventArgs>(appSrv_Launching);
            appSrv.Activated += new EventHandler<ActivatedEventArgs>(appSrv_Activated);
            appSrv.Deactivated += new EventHandler<DeactivatedEventArgs>(appSrv_Deactivated);
            appSrv.Closing += new EventHandler<ClosingEventArgs>(appSrv_Closing);
            //Счётчик количества запусков приложения
            //Проверим, есть ли данные в хранилище настроек
            if (IsolatedStorageSettings.ApplicationSettings.Contains("launchCount") == true)
            {
                //Если есть - прочитаем
                launchCount = (int)IsolatedStorageSettings.ApplicationSettings["launchCount"];
            }
            //Увеличим на 1 количество запусков
            launchCount++;
            //Запишем в хранилище (если ранее данных с этим ключом не было, он будет создан)
            IsolatedStorageSettings.ApplicationSettings["launchCount"] = launchCount;
            //Сохраним данные
            IsolatedStorageSettings.ApplicationSettings.Save();
        }
        //При прекращении работы приложения
        void appSrv_Closing(object sender, ClosingEventArgs e)
        {
            parameters.Save();
        }
        //При деактивации приложения
        void appSrv_Deactivated(object sender, DeactivatedEventArgs e)
        {
            parameters.Save();
        }
        //При активации приложения
        void appSrv_Activated(object sender, ActivatedEventArgs e)
        {
            text = text + " srv_Activation";
            parameters = SavedParam.Load();
        }
        //При запуске приложения
        void appSrv_Launching(object sender, LaunchingEventArgs e)
        {
            text = text + " srv_Launching";
            parameters = SavedParam.Load();
        }

        /// <summary>
        /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
        /// Здесь можно запросить нужные службы и загрузить неграфический
        /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
        /// их инициализации.
        /// </summary>
        protected override void Initialize()
        {
            text = text + " XNA_Initialize";
            base.Initialize();
        }
        //Метод базового класса Game, выполняется при деактивации приложения
        protected override void OnDeactivated(object sender, EventArgs args)
        {
            text = "";
            base.OnDeactivated(sender, args);

        }
        //Метод базового класса Game, выполняется при активации приложения
        protected override void OnActivated(object sender, EventArgs args)
        {
            text = text + " XNA_OnActivated";
            base.OnActivated(sender, args);
        }


        /// <summary>
        /// LoadContent будет вызываться в игре один раз; здесь загружается
        /// весь контент.
        /// </summary>
        protected override void LoadContent()
        {
            // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            myFont = Content.Load<SpriteFont>("MyFont");

        }

        /// <summary>
        /// UnloadContent будет вызываться в игре один раз; здесь выгружается
        /// весь контент.
        /// </summary>
        protected override void UnloadContent()
        {
            // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
        }

        /// <summary>
        /// Позволяет игре запускать логику обновления мира,
        /// проверки столкновений, получения ввода и воспроизведения звуков.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Update(GameTime gameTime)
        {
            // Позволяет выйти из игры
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            //Обработакм касание
            TouchCollection touchLocations = TouchPanel.GetState();
            foreach (TouchLocation touchLocation in touchLocations)
            {
                if (touchLocation.State == TouchLocationState.Pressed)
                {
                    //Сохраним позицию касания
                    parameters.touchPos = touchLocation.Position;
                    //Увеличим количество касаний
                    parameters.touchCount++;
                }
            }

            base.Update(gameTime);
        }

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

            spriteBatch.Begin();
            //Выведем сообщение, сгенерированное при изменении состояния приложения
            spriteBatch.DrawString(myFont, text, new Vector2(0, 0), Color.Red);
            //Выведем сообщение о количестве касаний в позиции последнего касания
            spriteBatch.DrawString(myFont, parameters.touchCount.ToString(), parameters.touchPos, Color.White);
            //Выведем данные о количестве запусков программы
            spriteBatch.DrawString(myFont, "Launch count = " + launchCount.ToString(), new Vector2(0, 240), Color.Black);
            spriteBatch.End();

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

Логика работы данного проекта разъясняется в комментариях, рассмотрим его основные моменты.

В конструкторе класса мы подсчитываем количество запусков игры. Здесь мы работаем с изолированным хранилищем настроек. Сначала проверяем, есть ли в хранилище данные по ключу launchCount, если данные есть, приводим их к типу int и записываем в переменную launchCount, после чего увеличиваем переменную на 1 (по умолчанию она равна 0) и записываем значение переменной в хранилище настроек с ключом launchCount. При этом, если такого ключа в хранилище пока нет (при первом запуске) он будет создан. Записав данные, сохраняем состояние хранилища настроек.

В конструкторе мы подключаем обработчики событий Launching, Activated, Deactivated, Closing класса PhoneApplicationService. Эти обработчики мы будем использовать для сохранения состояния игры (Deactivated и Closing) и загрузки (Activated, Launching). Кроме того, в классе мы переопределили методы базового класса OnActivated и OnDeactivated.

В данном случае это сделано для того, чтобы показать, что при активации приложения после деактивации (то есть, например, в ситуации, когда, работая в приложении мы нажимаем на кнопку вызова домашнего экрана, после чего, воспользовавшись кнопкой Назад возвращаемся в приложение) происходит вызов методов Initialize и OnActivated.

В то же время, при активации после деактивации вызывается лишь обработчик события Activated. При первом запуске приложения происходит вызов Initialize и OnActivated, относящихся к классу Game и Launching из PhoneApplicationService. Мы формируем строку text в этих событиях, она выводится на экран. Для самостоятельного исследования данных методов и особенностей жизненного цикла приложения полезно будет воспользоваться инструментами отладки.

В методе Update мы наблюдаем за касаниями экрана, если касание зафиксировано, записываем в открытую переменную touchPos объекта типа SavedParam координату касания и увеличиваем на 1 значение переменной touchCount из этого же объекта для подсчёта числа касаний.

В методе Draw мы выводим строку, сформированную при исполнении методов, отражающих изменение жизненного цикла приложения, выводим сведения о количестве касаний в позицию последнего зафиксированного касания, пользуясь данными объекта parameters типа SavedParam, и выводим сведения о количестве запусков программы из переменной launchCount, которая ранее (начиная со второго запуска программы) была установлена с использованием параметра, сохранённого в изолированном хранилище параметров.

На рис. 19.2 вы можете видеть экран программы в эмуляторе.

Программа в эмуляторе

Рис. 19.2. Программа в эмуляторе

Для целей отладки программ, контроля за содержимым изолированного хранилища, можно использовать специальный программный инструмент, который мы сейчас рассмотрим.

Гулич Анна
Гулич Анна
Невозможно пройти тесты, в окне с вопросами пусто
Сашечка Огнев
Сашечка Огнев
Россия, Красноярский край
Андрей Корягин
Андрей Корягин
Россия, Пенза, Вазерская средняя школа, 2001