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.Media;
using Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Xml.Serialization;
namespace ButtonGame
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MouseState mouse, prevMouse;
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public IAsyncResult result;
public Object stateobj;
public bool GameSaveRequested = false;
public GamePadState currentState;
public class GameImages
{
//Image Diminsions and Graphic
public Texture2D texture;
//Images position on the Viewport
public Vector2 position = new Vector2(0, 0);
}//GameImages
GameImages button;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.PreferMultiSampling = false;
graphics.IsFullScreen = false;
}//Game1()
protected override void Initialize()
{
button = new GameImages();
base.Initialize();
}//Initialize
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
//Gives the button the graphic "button.PNG" from resources
button.texture = Content.Load<Texture2D>("Button");
//Sets the drawing point of the button to the middle of the screen
button.position = new Vector2(300, 400);
}
protected override void Update(GameTime gameTime)
{
//Gets current position and condition of the mouse
mouse = Mouse.GetState();
//Makes the cursor visible on the screen of the game
this.IsMouseVisible = true;
//If the User has released the Left mouse button and previously had it pressed, (Left Clicked)
if (mouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
//Check if the mouse was within the bounds of GameImage button
if (CheckForClick(button))
{
//Remove the button from view
button.position = new Vector2(5000, 5000);
}
if (mouse.Y > 600)
{
button.texture = Content.Load<Texture2D>("Catch - Red");
}
}
if (mouse.X < 50)
{
button.position.X += 3;
}
else if (mouse.X > 500)
{
button.position.X -= 3;
}
//If the User has released the Right mouse button and previously had it pressed, (Right Clicked)
else if ((mouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed))
{
//Bring Back the button
//button.position = new Vector2(300,400);
InitiateSave();
}
else if ((mouse.MiddleButton == Microsoft.Xna.Framework.Input.ButtonState.Released && prevMouse.MiddleButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed))
{
InitiateLoad();
}
//Store the current mouse position and conditon into a orevious state to prepare for new input
prevMouse = mouse;
base.Update(gameTime);
}//Update
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
//Background Color
GraphicsDevice.Clear(Color.CornflowerBlue);
//if button is not off the screen
if (button.position != new Vector2(5000, 5000))
{
//Draw the button
DrawImage(button);
}
spriteBatch.End();
base.Draw(gameTime);
}//Draw
public void DrawImage(GameImages image)
{
spriteBatch.Draw(image.texture, image.position, Color.White);
}//DrawImage
public bool CheckForClick(GameImages rectangle)
{
if (mouse.Y < rectangle.position.Y + rectangle.texture.Height &&
mouse.Y > rectangle.position.Y &&
mouse.X > rectangle.position.X &&
mouse.X < rectangle.position.X + rectangle.texture.Width)
return true;
else
return false;
}//CheckForClick
StorageDevice device;
string containerName="MyGamesStorage";
string filename = "mysave.sav";
public struct SaveGame
{
public Vector2 buttonPosition;
public Texture2D newbuttonTexture;
}//Save Game
private void InitiateSave()
{
device = null;
StorageDevice.BeginShowSelector(PlayerIndex.One, this.SaveToDevice, null);
}
void SaveToDevice(IAsyncResult result)
{
device = StorageDevice.EndShowSelector(result);
if (device != null && device.IsConnected)
{
SaveGame SaveData = new SaveGame()
{
buttonPosition = button.position,
newbuttonTexture = button.texture,
};
IAsyncResult r = device.BeginOpenContainer(containerName, null, null);
result.AsyncWaitHandle.WaitOne();
StorageContainer container = device.EndOpenContainer(r);
if (container.FileExists(filename))
container.DeleteFile(filename);
Stream stream = container.CreateFile(filename);
XmlSerializer serializer = new XmlSerializer(typeof(SaveGame));
serializer.Serialize(stream, SaveData);
stream.Close();
container.Dispose();
result.AsyncWaitHandle.Close();
}
}
private void InitiateLoad()
{
device = null;
StorageDevice.BeginShowSelector(PlayerIndex.One, this.LoadFromDevice, null);
}
void LoadFromDevice(IAsyncResult result)
{
device = StorageDevice.EndShowSelector(result);
IAsyncResult r = device.BeginOpenContainer(containerName, null, null);
result.AsyncWaitHandle.WaitOne();
StorageContainer container = device.EndOpenContainer(r);
result.AsyncWaitHandle.Close();
if (container.FileExists(filename))
{
Stream stream = container.OpenFile(filename, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(SaveGame));
SaveGame SaveData = (SaveGame)serializer.Deserialize(stream);
stream.Close();
container.Dispose();
//Update the game based on the save game file
button.position = SaveData.buttonPosition;
button.texture = SaveData.newbuttonTexture;
}
}
}
}
我在一个较小的程序中简化并重现了我的问题,因此更容易分享。
当我运行程序并右键单击以保存时,然后稍微移动对象的位置以便我可以看到更改,然后在中间单击以加载游戏,我收到错误。
我做了什么来重现错误:
这是我收到错误消息的地方 未处理ObjectdispsoedException无法访问已处置的对象。对象名称:'Texture2D'。 在spriteBatch.End();线。
不可否认,我只是复制并通过互联网保存和加载课程,我不知道每一步是如何完全运作的。
代码的目标:我希望能够保存数据,例如位置,分配的内容,数组等。以便以后可以再次加载。
答案 0 :(得分:0)
首先,您不应该在更新中加载内容。它应该在&#34; loadcontent&#34;中完成,因此名称......您应该在加载内容中加载2个纹理,然后在更新中交换它们。
其次,问题是在load函数中再次设置texture2D。因为content.load()所做的是将纹理加载到图形卡上。但是如果你重置它,那么参考将会改变。这与我的第一点有关。调用content.load时,您应该已经加载了内容。所以你应该将texture2d和游戏对象分开。
例如(不会编译,但你明白了):
class MyGameObject
{
public int textureIndex = 0;
public Vector2 position = new Vector2(0, 0);
}
class Game
{
Texture2D[] textures;
MyGameObject poop;
void loadContent()
{
textures = new Texture2D[2];
textures[0] = Content.Load<Texture2D>("a texture");
textures[1] = Content.Load<Texture2D>("different texture");
poop = new MyGameObject();
poop.textureIndex = 0;
}
void update()
{
if (mouse.Y > 600)
{
poop.textureIndex = 1;
}
}
void draw()
{
spriteBatch.draw(textures[poop.textureIndex], poop.position);
}
....other stuff....
}