Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Опубликован: 10.04.2009 | Уровень: специалист | Доступ: свободно
Самостоятельная работа 10:
Работа с файлами, сериализация
Механизмы сериализации и игровая логика реализованы в коде класса Game1. Его вы можете видеть в листинге 14.5.
using System; using System.Collections.Generic; 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.Net; using Microsoft.Xna.Framework.Storage; //Классы для работы с устройствами ввода-вывода using System.IO; //Классы для работы механизмов сериализации using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace P10_2 { /// <summary> /// This is the main type for your game /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; //Для текстуры стены Texture2D txtWall; //Прямоугольник для создания объектов Wall Rectangle recSprite = new Rectangle(0, 0, 64, 64); //Массив объектов Wall Wall [,] arrayOfWalls; //Объект, хранящий игровые данные и подлежащий сериализации //Массив в этом объекте используется при загрузке игры и //при сохранении игры, в игровом процессе используется //массив объектов Wall GameData MyObj; //Переменная для хранения состояния мыши MouseState mouse; //устройство для хранения информации StorageDevice sDev; //результат операции доступа к устройству IAsyncResult res; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { //Разрешение экрана 640х512 graphics.PreferredBackBufferWidth = 640; graphics.PreferredBackBufferHeight = 512; graphics.ApplyChanges(); //Сделать указатель мыши видимым this.IsMouseVisible = true; base.Initialize(); } protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); Services.AddService(typeof(SpriteBatch), spriteBatch); txtWall = Content.Load<Texture2D>("wall"); //В этом массиве лишь единицы - это значит //что при запуске все игровое поле заполнено //изображениями стен byte [,] arrayForGame = new byte[8, 10] { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, }; //Новый массив стен arrayOfWalls = new Wall[8, 10]; //Создаем объект для хранения данных, //передавая ему массив MyObj = new GameData(arrayForGame); //вызываем процедуру создания и //вывода на экран игровых объектов AddSprites (); } //Создание игровых объектов void AddSprites() { //Просматриваем массив array в объекте типа GameData for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { if (MyObj.array[i, j] == 1) { //Если в массиве единица - создаем новый объект в текущей ячейке //массива arrayOfWalls и добавляем в список игровых компонентов arrayOfWalls[i, j] = new Wall(this, ref txtWall, new Vector2(j, i), recSprite); Components.Add(arrayOfWalls[i, j]); } } } } //Процедура очистки массива игровых компонентов void ClearAll() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { if (arrayOfWalls[i, j] != null) { arrayOfWalls[i, j].Dispose(); arrayOfWalls[i, j] = null; } } } } //Процедура проверки массива игровых компонентов и отражения //его состояния в массиве объекта типа GameData //в нашем случае, если ячейка массива игровых компонентов содержит //объект, в массив объекта GameData записывают 1, если нет - 0 void SetWallToArray() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { if (arrayOfWalls[i, j] == null) { MyObj.array[i, j] = 0; } else { MyObj.array[i, j] = 1; } } } } //Процедура сериализации объекта void serializ() { //Контейнер для хранения данных StorageContainer container = sDev.OpenContainer("P10_2"); //Полное имя файла - комбинация адреса контейнера и имени string filename = Path.Combine(container.Path, "savegame.sav"); //Объект, предназначенный для сериализации и десериализации других объектов IFormatter formatter = new BinaryFormatter(); //Создаем новый поток для записи файла Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); //Сериализуем объект MyObj в поток stream formatter.Serialize(stream, MyObj); //Закрываем поток stream.Close(); //Уничтожаем контейнер container.Dispose(); //выводим сообщение в заголовок игрового окна this.Window.Title = "Игра сохранена"; } //Процедура десериализации объекта //похожа на процедуру десериализации //при десериализации файл открывают для чтения и //десериализуют в объект void deserializ() { StorageContainer container = sDev.OpenContainer("P10_2"); string filename = Path.Combine(container.Path, "savegame.sav"); IFormatter formatter = new BinaryFormatter(); //Новый поток для чтения файла Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); //Получаем данные из потока и приводим их к типу MyObj MyObj = (GameData)formatter.Deserialize(stream); stream.Close(); container.Dispose(); this.Window.Title = "Игра загружена"; } protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } protected override void Update(GameTime gameTime) { //получим состояние клавиатуры KeyboardState kb = Keyboard.GetState(); //Сохраняем игру при нажатой клавише A if (kb.IsKeyDown(Keys.A)) { //Отразим состояние игровго окна в массиве объекта типа GameData SetWallToArray(); //Получим устройство для хранения данных res = Guide.BeginShowStorageDeviceSelector(PlayerIndex.One, null, null); sDev = Guide.EndShowStorageDeviceSelector(res); //Вызовем процедуру сериализации serializ (); } //Загружаем игру при нажатой клавише W if (kb.IsKeyDown (Keys .W )) { //Очищаем игровой экран ClearAll(); //Получим устройство для хранения данных res = Guide.BeginShowStorageDeviceSelector(PlayerIndex.One, null, null); sDev = Guide.EndShowStorageDeviceSelector(res); //Десериализуем объект из файла deserializ(); //Сконструируем игровой экран на основе десериализованного //объекта MyObj AddSprites(); } //Работа с мышью mouse = Mouse.GetState(); if (mouse.LeftButton == ButtonState.Pressed) { for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { //Если в текущей ячейке массива есть "стена" //проверим, находился ли указатель мыши в пределах объекта //соответствующего текущей ячейке. Если да - уничтожим объект if (arrayOfWalls[i, j] != null) { if (arrayOfWalls[i, j].sprPosition.X + arrayOfWalls[i, j].sprRectangle.Width > mouse.X && arrayOfWalls[i, j].sprPosition.X < mouse.X && arrayOfWalls[i, j].sprPosition.Y + arrayOfWalls[i, j].sprRectangle.Height > mouse.Y && arrayOfWalls[i, j].sprPosition.Y < mouse.Y) { arrayOfWalls[i, j].Dispose(); arrayOfWalls[i, j] = null; } } } } } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); base.Draw(gameTime); spriteBatch.End(); } } }Листинг 14.5. Код класса Game1
На рис. 14.3. вы можете видеть игровой экран проекта P10_2.