gpt4 book ai didi

C# XNA 4.0 纹理在最小化时消失

转载 作者:太空宇宙 更新时间:2023-11-03 20:14:07 25 4
gpt4 key购买 nike

我是 XNA 的新手,遇到了一些问题。每当我最小化游戏时,再次打开它时屏幕会变黑。这可能是什么原因造成的,如何解决?

这是我的图像类:

 public class Image
{
public float Alpha;
public string Text, FontName, Path;
public Vector2 Position, Scale;
public Rectangle SourceRect;
public bool IsActive;
public bool Logo;
public Texture2D Texture;
Vector2 origin;
ContentManager content;
RenderTarget2D renderTarget;
SpriteFont font;
Dictionary<string, ImageEffect> effectList;
public string Effects;

public FadeEffect FadeEffect;

void SetEffect<T>(ref T effect)
{
if (effect == null)
effect = (T)Activator.CreateInstance(typeof(T));
else
{
(effect as ImageEffect).IsActive = true;
var obj = this;
(effect as ImageEffect).LoadContent(ref obj);
}

effectList.Add(effect.GetType().ToString().Replace("RPG.", ""), (effect as ImageEffect));
}

public void ActivateEffect(string effect)
{
if (effectList.ContainsKey(effect))
{
effectList[effect].IsActive = true;
var obj = this;
effectList[effect].LoadContent(ref obj);
}
}

public void DeactivateEffect(string effect)
{
if (effectList.ContainsKey(effect))
{
effectList[effect].IsActive = false;
effectList[effect].UnloadContent();
}
}

public void StoreEffects()
{
Effects = String.Empty;
foreach (var effect in effectList)
{
if (effect.Value.IsActive)
Effects += effect.Key + ":";
}

if(Effects != String.Empty)
Effects.Remove(Effects.Length - 1);
}

public void RestoreEffects()
{
foreach (var effect in effectList)
DeactivateEffect(effect.Key);
string[] split = Effects.Split(':');
foreach (string s in split)
ActivateEffect(s);
}

public Image()
{
Path = Text = Effects = String.Empty;
FontName = "Fonts/FixedSys Ex";
Position = Vector2.Zero;
Scale = Vector2.One;
Alpha = 1.0f;
SourceRect = Rectangle.Empty;
effectList = new Dictionary<string, ImageEffect>();
}

public void LoadContent()
{
content = new ContentManager(ScreenManager.Instance.Content.ServiceProvider, "Content");


if (Path != String.Empty)
Texture = content.Load<Texture2D>(Path);

font = content.Load<SpriteFont>(FontName);

Vector2 dimensions = Vector2.Zero;

if (Texture != null)
dimensions.X += Texture.Width;
dimensions.X += font.MeasureString(Text).X;

if (Texture != null)
dimensions.Y = Math.Max(Texture.Height, font.MeasureString(Text).Y);
else
dimensions.Y = font.MeasureString(Text).Y;

if (SourceRect == Rectangle.Empty)
SourceRect = new Rectangle(0, 0, (int)dimensions.X, (int)dimensions.Y);

renderTarget = new RenderTarget2D(ScreenManager.Instance.GraphicsDevice, (int)dimensions.X, (int)dimensions.Y);
ScreenManager.Instance.GraphicsDevice.SetRenderTarget(renderTarget);
ScreenManager.Instance.GraphicsDevice.Clear(Color.Transparent);
ScreenManager.Instance.SpriteBatch.Begin();
if (Texture != null)
ScreenManager.Instance.SpriteBatch.Draw(Texture, Vector2.Zero, Color.White);
ScreenManager.Instance.SpriteBatch.DrawString(font, Text, Vector2.Zero, Color.White);
ScreenManager.Instance.SpriteBatch.End();

Texture = renderTarget;

ScreenManager.Instance.GraphicsDevice.SetRenderTarget(null);

SetEffect<FadeEffect>(ref FadeEffect);

if (Effects != string.Empty)
{
string[] split = Effects.Split(':');
foreach (string item in split)
ActivateEffect(item);
}


}

public void UnloadContent()
{
content.Unload();
foreach (var effect in effectList)
{
DeactivateEffect(effect.Key);
}
}

public void Update(GameTime gameTime)
{
foreach (var effect in effectList)
{
if(effect.Value.IsActive)
effect.Value.Update(gameTime);
}
}

public void Draw(SpriteBatch spriteBatch)
{
origin = new Vector2(SourceRect.Width / 2, SourceRect.Height / 2);
spriteBatch.Draw(Texture, Position + origin, SourceRect, Color.White * Alpha, 0.0f, origin, Scale, SpriteEffects.None, 0.0f);
}
}

编辑:

我终于设法让它正常工作了!

固定代码:

public class Image
{
public float Alpha;
public string Text, FontName, Path;
public Vector2 Position, Scale;
public Rectangle SourceRect;
public bool IsActive;
public bool Logo;
public Texture2D Texture;
Vector2 origin;
Vector2 dimensions;
ContentManager content;
RenderTarget2D renderTarget;
SpriteFont font;
Dictionary<string, ImageEffect> effectList;
public string Effects;

public FadeEffect FadeEffect;

void SetEffect<T>(ref T effect)
{
if (effect == null)
effect = (T)Activator.CreateInstance(typeof(T));
else
{
(effect as ImageEffect).IsActive = true;
var obj = this;
(effect as ImageEffect).LoadContent(ref obj);
}

effectList.Add(effect.GetType().ToString().Replace("RPG.", ""), (effect as ImageEffect));
}

public void ActivateEffect(string effect)
{
if (effectList.ContainsKey(effect))
{
effectList[effect].IsActive = true;
var obj = this;
effectList[effect].LoadContent(ref obj);
}
}

public void DeactivateEffect(string effect)
{
if (effectList.ContainsKey(effect))
{
effectList[effect].IsActive = false;
effectList[effect].UnloadContent();
}
}

public void StoreEffects()
{
Effects = String.Empty;
foreach (var effect in effectList)
{
if (effect.Value.IsActive)
Effects += effect.Key + ":";
}

if(Effects != String.Empty)
Effects.Remove(Effects.Length - 1);
}

public void RestoreEffects()
{
foreach (var effect in effectList)
DeactivateEffect(effect.Key);
string[] split = Effects.Split(':');
foreach (string s in split)
ActivateEffect(s);
}

public Image()
{
Path = Text = Effects = String.Empty;
FontName = "Fonts/FixedSys Ex";
Position = Vector2.Zero;
Scale = Vector2.One;
Alpha = 1.0f;
SourceRect = Rectangle.Empty;
effectList = new Dictionary<string, ImageEffect>();
}

public void LoadContent()
{
content = new ContentManager(ScreenManager.Instance.Content.ServiceProvider, "Content");


if (Path != String.Empty)
Texture = content.Load<Texture2D>(Path);

font = content.Load<SpriteFont>(FontName);

dimensions = Vector2.Zero;

if (Texture != null)
dimensions.X += Texture.Width;
dimensions.X += font.MeasureString(Text).X;

if (Texture != null)
dimensions.Y = Math.Max(Texture.Height, font.MeasureString(Text).Y);
else
dimensions.Y = font.MeasureString(Text).Y;

if (SourceRect == Rectangle.Empty)
SourceRect = new Rectangle(0, 0, (int)dimensions.X, (int)dimensions.Y);

SetEffect<FadeEffect>(ref FadeEffect);

LoadDevice();

if (Effects != string.Empty)
{
string[] split = Effects.Split(':');
foreach (string item in split)
ActivateEffect(item);
}

}

public void LoadDevice()
{
if (Path != String.Empty)
Texture = content.Load<Texture2D>(Path);

font = content.Load<SpriteFont>(FontName);

renderTarget = new RenderTarget2D(ScreenManager.Instance.GraphicsDevice, (int)dimensions.X, (int)dimensions.Y);
ScreenManager.Instance.GraphicsDevice.SetRenderTarget(renderTarget);
ScreenManager.Instance.GraphicsDevice.Clear(Color.Transparent);
ScreenManager.Instance.SpriteBatch.Begin();
if (Texture != null)
ScreenManager.Instance.SpriteBatch.Draw(Texture, Vector2.Zero, Color.White);
ScreenManager.Instance.SpriteBatch.DrawString(font, Text, Vector2.Zero, Color.White);
ScreenManager.Instance.SpriteBatch.End();

Texture = renderTarget;

ScreenManager.Instance.GraphicsDevice.SetRenderTarget(null);
}

public void UnloadContent()
{
content.Unload();
foreach (var effect in effectList)
{
DeactivateEffect(effect.Key);
}
}

public void Update(GameTime gameTime)
{
foreach (var effect in effectList)
{
if(effect.Value.IsActive)
effect.Value.Update(gameTime);
}
}

public void Draw(SpriteBatch spriteBatch)
{
origin = new Vector2(SourceRect.Width / 2, SourceRect.Height / 2);
spriteBatch.Draw(Texture, Position + origin, SourceRect, Color.White * Alpha, 0.0f, origin, Scale, SpriteEffects.None, 0.0f);

if (renderTarget.IsContentLost)
{
ScreenManager.Instance.SpriteBatch.End();
LoadDevice();
ScreenManager.Instance.SpriteBatch.Begin();
}
}
}

renderTarget 的内容现在在一个单独的方法中绘制,并且在 LoadContent() 中被调用一次,并且在内容被调用时在 Draw() 方法中被调用迷路了。

最佳答案

所以这里的问题是因为您正在使用 RenderTarget2D 作为纹理。

在纯 DirectX 中,只要图形设备丢失,纹理和渲染目标都会丢失其内容。这是因为视频内存中的所有内容(纹理所在的位置)都必须卸载。 XNA 在纹理方面对您进行了抽象:它在 CPU 内存中保留了纹理的副本,以便在设备重置后可以自动重新创建它。

然而,渲染目标是一件比较棘手的事情。您通常不会从预先存在的图像加载渲染目标;相反,您是直接在 GPU 本身上生成渲染目标内容。那么,如果 XNA 不能在 CPU 内存中保存其内容的副本,它如何为您重新创建渲染目标?答案是不能。当设备丢失时,您的渲染目标将丢失其内容,XNA 对此无能为力。

这就是 RenderTarget2D 类公开名为 IsContentLost 的属性的原因。这使您可以确定上述情况何时发生并做出适当的响应。您不需要创建一个渲染目标——该对象仍然存在于内存中——但您需要再次告诉图形设备它包含什么。 p>

现在,您正在 LoadContent() 中绘制渲染目标,它只会被调用一次。您需要将负责绘制渲染目标的代码部分移到另一个方法中,并在渲染目标丢失时调用该方法。

现在,要绘制渲染目标,您需要使用 SetRenderTarget(myRenderTarget) 在图形设备上设置它。完成绘制后,您需要使用 SetRenderTarget(null) 再次取消设置,这会将后台缓冲区恢复为主要渲染目标。这一点很重要,因为渲染目标不能同时是渲染的(即纹理)和渲染的目标。如果您尝试这样做,您将得到一个异常(exception)。

你的情况似乎很复杂,因为你正在将纹理加载到 Texture 字段中,然后将其绘制到渲染目标,然后替换 Texture带有渲染目标的字段。如果您尝试用您所拥有的执行我刚才描述的操作,您将最终尝试将渲染目标绘制到自身上——这可能是导致您所看到的异常的原因。所以不要那样做。将原始纹理存储在不同的字段中,因为稍后您将需要它来重新生成目标。

关于C# XNA 4.0 纹理在最小化时消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18058742/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com