未处理ObjectdispsoedException无法访问已处置的对象。对象名称:'Texture2D'

时间:2014-06-13 19:52:11

标签: c# xna

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;
      }
  }

}
}

我在一个较小的程序中简化并重现了我的问题,因此更容易分享。

当我运行程序并右键单击以保存时,然后稍微移动对象的位置以便我可以看到更改,然后在中间单击以加载游戏,我收到错误。

我做了什么来重现错误:

  • 运行程序
  • 右键单击 - 这样可以保存游戏
  • 用鼠标左键单击屏幕底部 - 这会将按钮的图像更改为“Catch - Red”
  • 将鼠标放在屏幕左侧,以便按钮移动
  • 中间点击以便游戏加载以前保存的数据,按钮应该以它的第一个图像“按钮”为中心

这是我收到错误消息的地方 未处理ObjectdispsoedException无法访问已处置的对象。对象名称:'Texture2D'。 在spriteBatch.End();线。

不可否认,我只是复制并通过互联网保存和加载课程,我不知道每一步是如何完全运作的。

代码的目标:我希望能够保存数据,例如位置,分配的内容,数组等。以便以后可以再次加载。

1 个答案:

答案 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....
}