2013-05-29 53 views
2

我在最新的XNA(C#)中編寫2D遊戲。我正在對舊代碼進行一些修改,然後放回按鈕來改變分辨率。然而,在全屏模式切換或窗口大小/分辨率被改變之後,儘管遊戲仍在運行,但我仍然可以通過按鍵退出,但屏幕只是黑色(我的清屏呼叫的顏色)。 這在我之前的版本中沒有發生 - 它一切正常 - 但我可以找到的相關代碼沒有區別。但是,我做了重做我的圖形加載使用我自己的紋理加載器,而不是內容加載器 - 這可能是問題嗎?在XNA中更改分辨率 - 屏幕後黑色

如果沒有其他選擇,是否有一種簡單的方法可以使遊戲重新啓動,因爲圖形是否正常並且在重新啓動後以選定的格式?

我的代碼是:

public override void Click() 
    { 
     base.Click(); 
     Settings.Default.screenWidth = resolution[0]; 
     Settings.Default.screenHeight = resolution[1]; 
     Settings.Default.Save(); 
     Variables.screenWidth = Settings.Default.screenWidth; 
     Variables.screenHeight = Settings.Default.screenHeight; 

     Game1.graphics.PreferredBackBufferWidth = Variables.screenWidth; 
     Game1.graphics.PreferredBackBufferHeight = Variables.screenHeight; 
     Game1.graphics.ApplyChanges(); 
    } 

謝謝!

編輯:我的質地loadign碼 - 負載與包含在枚舉作爲Texture2Ds一個名稱的所有文件..

public static void LoadAll(string subFolder) 
    { 
     List<string> s = Directory.GetFiles(path + "\\" + subFolder, "*.png", SearchOption.AllDirectories).ToList<string>(); 
     foreach (string S in s) 
     { 
      if (Enum.IsDefined(typeof(T), Path.GetFileNameWithoutExtension(S))) 
      { 
       FileStream stream = new FileStream(S, FileMode.Open); 
       Texture2D t = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream); 
       RenderTarget2D result = null; 

       //Setup a render target to hold our final texture which will have premulitplied alpha values 
       result = new RenderTarget2D(Game1.graphics.GraphicsDevice, t.Width, t.Height); 

       Game1.graphics.GraphicsDevice.SetRenderTarget(result); 
       Game1.graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.Black); 

       //Multiply each color by the source alpha, and write in just the color values into the final texture 
       BlendState blendColor = new BlendState(); 
       blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue; 

       blendColor.AlphaDestinationBlend = Blend.Zero; 
       blendColor.ColorDestinationBlend = Blend.Zero; 

       blendColor.AlphaSourceBlend = Blend.SourceAlpha; 
       blendColor.ColorSourceBlend = Blend.SourceAlpha; 


       Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendColor); 
       Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White); 
       Game1.spriteBatch.End(); 

       //Now copy over the alpha values from the PNG source texture to the final one, without multiplying them 
       BlendState blendAlpha = new BlendState(); 
       blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha; 

       blendAlpha.AlphaDestinationBlend = Blend.Zero; 
       blendAlpha.ColorDestinationBlend = Blend.Zero; 

       blendAlpha.AlphaSourceBlend = Blend.One; 
       blendAlpha.ColorSourceBlend = Blend.One; 

       Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha); 
       Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White); 
       Game1.spriteBatch.End(); 

       //Release the GPU back to drawing to the screen 

       Game1.graphics.GraphicsDevice.SetRenderTarget(null); 


       t = result; 

       textureDictionary.Add(Path.GetFileNameWithoutExtension(S), t); 
      } 
      // else 
      // Console.WriteLine("Did not load -- " + Path.GetFileNameWithoutExtension(S) + " -- (add to enum to enable loading)"); 
     } 
    } 

編輯:從遵循以下建議工作代碼 - 可能不是最有效的,但它的工作原理!

public static void LoadAll(string subFolder) 
    { 
     List<string> s = Directory.GetFiles(path + "\\" + subFolder, "*.png", SearchOption.AllDirectories).ToList<string>(); 
     foreach (string S in s) 
     { 
      if (Enum.IsDefined(typeof(T), Path.GetFileNameWithoutExtension(S))) 
      { 
       FileStream stream = new FileStream(S, FileMode.Open); 
       Texture2D t = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream); 
       RenderTarget2D result = null; 
       Texture2D resultTexture; 

       //Setup a render target to hold our final texture which will have premulitplied alpha values 
       result = new RenderTarget2D(Game1.graphics.GraphicsDevice, t.Width, t.Height); 

       Game1.graphics.GraphicsDevice.SetRenderTarget(result); 
       Game1.graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.Black); 

       //Multiply each color by the source alpha, and write in just the color values into the final texture 
       BlendState blendColor = new BlendState(); 
       blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue; 

       blendColor.AlphaDestinationBlend = Blend.Zero; 
       blendColor.ColorDestinationBlend = Blend.Zero; 

       blendColor.AlphaSourceBlend = Blend.SourceAlpha; 
       blendColor.ColorSourceBlend = Blend.SourceAlpha; 


       Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendColor); 
       Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White); 
       Game1.spriteBatch.End(); 

       //Now copy over the alpha values from the PNG source texture to the final one, without multiplying them 
       BlendState blendAlpha = new BlendState(); 
       blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha; 

       blendAlpha.AlphaDestinationBlend = Blend.Zero; 
       blendAlpha.ColorDestinationBlend = Blend.Zero; 

       blendAlpha.AlphaSourceBlend = Blend.One; 
       blendAlpha.ColorSourceBlend = Blend.One; 

       Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha); 
       Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White); 
       Game1.spriteBatch.End(); 

       //Release the GPU back to drawing to the screen 

       Game1.graphics.GraphicsDevice.SetRenderTarget(null); 

       resultTexture = new Texture2D(Game1.graphics.GraphicsDevice, result.Width, result.Height); 
       Color[] data = new Color[result.Height * result.Width]; 
       Color[] textureColor = new Color[result.Height * result.Width]; 

       result.GetData<Color>(textureColor); 

       resultTexture.SetData(textureColor); 

       textureDictionary.Add(Path.GetFileNameWithoutExtension(S), resultTexture); 
      } 
      // else 
      // Console.WriteLine("Did not load -- " + Path.GetFileNameWithoutExtension(S) + " -- (add to enum to enable loading)"); 
     } 
    } 
+1

您發佈的代碼很好。可能是你的紋理加載器出了問題 - 你是否在渲染目標上做任何事情?您的紋理可能無法正確處理「設備丟失」。你可以嘗試最小化你的遊戲或鎖定你的會話 - 我很確定這些也會導致設備丟失(不是100%肯定) - 並看看你是否得到相同的結果。 –

+0

謝謝@Andrew,我懷疑我可能會對任何渲染目標都做些古怪的事情。另外如何處理設備丟失?我將編輯我的答案以顯示紋理加載代碼。 –

回答

2

根據你更新的代碼,你的紋理複製到一個渲染目標(RenderTarget2D)。

與常規紋理不同,它們不受CPU端內存的支持。當圖形設備丟失時,常規紋理將自動在GPU上重新設置它們的數據。但是,渲染目標會提高其ContentLost事件並設置IsContentLost - 然後您可以自行重置其內容!

有幾個解決方案:您可以簡單地迴應ContentLost並刷新數據。

我更喜歡使用GetDataSetData在加載時渲染目標的內容複製到正規Texture2D,因爲這「只是工作」。儘管對於像使用預乘alpha的紋理切換這樣簡單的情況,我寧願只保留所有的CPU。我有一個very detailed answer about RenderTarget2D usage for fixed textures over here。它包括直接在CPU上進行預乘的代碼。

雖然在你的情況,我會嘗試使用內容管理器。它is possible讓它處理目錄中的所有文件,然後動態加載它們。

+0

@Mr Russell你是一個救星。令人印象深刻,一切都解決了。謝謝你,謝謝你堆棧溢出! –