2014-06-13 55 views
0
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'

當我運行程序並右鍵單擊保存,然後移動對象的位置有點,所以我可以看到一個變化,然後中間點擊加載遊戲,我得到的錯誤。

我做什麼重現錯誤:

  • 運行程序
  • 右鍵 - 這個保存的遊戲鼠標經過屏幕的底部
  • 左擊 - 這改變了按鈕的圖像爲「Catch - Red」
  • 將鼠標置於屏幕左側,以便按鈕移動
  • 中間點擊以便遊戲加載之前保存的數據,按鈕應居中它的第一個圖像「按鈕」

這是我得到的錯誤信息 ObjectdispsoedException了未處理無法訪問已釋放的對象。對象名稱:'Texture2D'。在spriteBatch.End()上的 ;線。

不可否認,我只是複製並通過互聯網上的保存和加載類,我不知道每一步如何完全工作。

代碼的目標:我希望能夠保存數據,例如位置,分配的內容,數組等,以便稍後再次加載。

+0

直到有人有更好的答案走來: 由於我在與content.load /圖像的麻煩,我m只是保存數字變量並使用它們來重新加載圖像數據。 即;調用一個指定int變量的方法, public int numImageSaver; 當用戶點擊保存按鈕時,分配變量numImageSaver = 1; 然後在savetodevice方法,保存numImageSaver, 當用戶加載數據,抓住numImageSaver從可變後在保存文件。 然後調用如果(numImageSaver == 1){button.texture = ...) –

+0

研究由線代碼行後,我意識到SAVEDATA沒有轉移,將破譯的數量與if或切換 的方法GameImages的紋理部分。爲了解決這個問題,我只需在變量從Savedata獲取分配數據之後調用一個方法。這個方法必須爲你計劃在當前屏幕上使用的每一個紋理賦值(如果你做了一些加載或分配一個新紋理的東西(點擊/類型),你不需要把它加載到這個方法中。) –

回答

0

首先,您不應該在更新中加載內容。它應該在「loadcontent」中完成,因此名稱...您應該在加載內容中加載2個紋理,然後在更新中交換它們。

其次,問題在於你在載入函數中再次設置texture2D。因爲content.load()所做的是將紋理加載到圖形卡上。但是如果你重置它,那麼參考將會改變。這與我的第一點有關。在調用content.load時,您應該已經加載了內容。所以你應該分離紋理2D和遊戲對象。

例如(編譯習慣,但你的想法):

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.... 
} 
+0

哇,這是容易理解,但我從來不知道的東西。我不知道我是如何挑選如此糟糕的方式來加載紋理。謝謝您的幫助。 –

+0

反正可以輕鬆地遍歷我的所有圖像資源嗎? 對於int i = 0;我<資源/圖片/文件數量; i ++)紋理[i] = Content.Load ([/ images後面的文件名稱]); –

+0

編輯:我意識到,爲我的圖像類型製作多個Texture2D數組會更好。 –

相關問題