【问题标题】:Graphical glitch occuring in XNA on Windows Phone 7 in Landscape orientationWindows Phone 7 上的 XNA 中出现横向图形故障
【发布时间】:2012-08-10 04:19:52
【问题描述】:

几个月来,我一直在研究跨平台框架/抽象层,基于 WP7 的 XNA 框架和 Android 和 iOS 的 Mono。在获得了适用于 Android 的大部分功能后,我最近回到了 WP7,以便让一个简单的游戏在两个平台上都能运行。

问题是,我遇到了一个非常奇怪的图形错误。该错误不会在基于 Windows 的 XNA 游戏中发生,并且仅在方向为横向(默认或指定)时发生在 WP7 上。故障出现在模拟器上,但不在物理设备上。出于测试目的,我在红色背景上显示单个图像。

Windows XNA

Windows http://www.genius-i.com/images/Windows.png

Windows Phone 7(纵向)

Portait http://www.genius-i.com/images/Portrait.png

Windows Phone 7(横向)

Landscape http://www.genius-i.com/images/Landscape.png

显然,横向图像没有按预期显示。虽然这一切都是通过抽象层处理的,但 XNA 平台文件是相同的,Windows 和 WP7 版本之间的唯一区别是目标平台/框架。

同样,对图形设备和渲染器的调用是相同的。

构建期间(从各种类和函数中提取)

device = new Microsoft.Xna.Framework.GraphicsDeviceManager(game);
device.PreferredBackBufferHeight = 480;
device.PreferredBackBufferWidth = 800;
Backend.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
// Whether or not I set the orientation, the glitchoccurs.

初始化期间(从各种类和函数中提取)

renderer = new SpriteBatch(device.GraphicsDevice);

绘图中

device.Clear(Color.Red);
renderer.Begin();
renderer.Draw(ZNGTexture, new Rectangle(10, 400, 145, 66), null, Color.White, 0f, Vector.Zero, SpriteEffects.none, 0f);
renderer.End()

是否有人对可能导致图形故障的原因(例如我所描述的故障)有任何见解?

感谢您提供的任何帮助,很抱歉在几天之内提出第二个问题。

完整代码

为了帮助识别问题,我提供了大量的实际代码。我最初排除它是因为它有点长,而且这些类是 XNA 大部分功能的简单包装器。

游戏类

public class Game : Microsoft.Xna.Framework.Game, IGame
{
    #region Data: Fields

    private GraphicsBackendXNA graphics;
    private Renderer2DXNA renderer;
    ContentLoaderXNA content;

    #endregion

    #region Data: Properties

    public GraphicsBackend Backend { get { return graphics; } }
    public Renderer2D Renderer { get { return renderer; } }
    public ContentLoader Loader { get { return content; } }

    #endregion

    #region Methods: Construction

    public Game()
    {
        graphics = new GraphicsBackendXNA(this);
        content = new ContentLoaderXNA(this.Services, "Content");
        FinaliseConstruction();
    }

    protected virtual void FinaliseConstruction() { }

    #endregion

    #region Methods: Initialisation

    protected override void Initialize()
    {
        Core.Console.Initialise(); // Initialised once for error logging.
        base.Initialize();
        renderer = new RendererXNA(graphics);
        Core.Console.Initialise(renderer); // Initialised a second time for graphics services.

        Transform.ScreenSize = new Vector2(Backend.ScreenWidth, Backend.ScreenHeight);

        Core.Audio.MediaPlayer.Initialise(new Audio.MediaHandler());
        Core.Audio.SoundEffect.Initialise(Audio.SoundEffectXNA.SetVolume);

        Core.Input.Input.Set(new KeyboardReaderXNA(), new MouseReaderXNA(), new GamePadReaderXNA(), new Input.Touch.TouchPanelXNA(), new GamePadOutputXNA());
        Core.Input.InputManager.Initialise();
    }

    #endregion

    #region Methods: Loading and Unloading Content

    protected override void UnloadContent()
    {
        content.Unload();
        base.UnloadContent();
    }

    #endregion

    #region Methods: Drawing

    protected override void EndDraw()
    {
        Camera2D.AllOff();
        base.EndDraw();
    }

    #endregion

图形后端类

图形后端 (XNA) 类是一个简单的包装类。它扩展了 GraphicsBackend 类,该类是抽象的,不包含任何功能。

public class GraphicsBackendXNA : GraphicsBackend
{
    #region Data: Fields

    private Microsoft.Xna.Framework.GraphicsDeviceManager device;

    #endregion

    #region Data: Properties

    public override Display Display { get { return device.GraphicsDevice.PresentationParameters.ToHeron(); } }
    public override Core.Graphics.Viewport Viewport { get { return device.GraphicsDevice.Viewport.ToHeron(); } }

    public override int ScreenWidth { get { return device.PreferredBackBufferWidth; } set { device.PreferredBackBufferWidth = value; } }
    public override int ScreenHeight { get { return device.PreferredBackBufferHeight; } set { device.PreferredBackBufferHeight = value; } }

    public override bool IsFullScreen { get { return device.IsFullScreen; } set { device.IsFullScreen = value; } }
    public override Core.DisplayOrientation SupportedOrientations
    {
        get { return ((Core.DisplayOrientation)((int)device.SupportedOrientations); }
        set { device.SupportedOrientations = (Microsoft.Xna.Framework.DisplayOrientation)((int)value); }
    }

    #endregion

    #region Methods: Construction

    public GraphicsBackendXNA(Microsoft.Xna.Framework.Game game)
    {
        device = new Microsoft.Xna.Framework.GraphicsDeviceManager(game);
    }

    #endregion

    #region Methods: Settings

    public override void ApplyChanges()
    {
        device.ApplyChanges();
    }

    #endregion

    #region Methods: Rendering

    public override void Clear(Colour colour)
    {
        device.GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(colour.R, colour.G, colour.B, colour.A));
    }

    #endregion

    #region Methods: Renderer

    public override Renderer2D CreateRenderer() { return new Renderer2DXNA(this); }

    #endregion

渲染器 2D XNA 类

Renderer 2D XNA 类是另一个简单的包装器。它继承自 Renderer2D 基类,该基类实现了大量用于绘制内容的抽象方法。它有一些非常基本的功能,我将首先详细介绍,但我不会费心包含所有空白方法。

public class Renderer2D : IDisposable
{
    private GraphicsBackend backend;
    private Matrix currentMatrix;

    public virtual GraphicsBackend Backend { get { return backend; } protected set { backend = value; } }
    public Matrix CurrentMatrix { get { return currentMatrix; } set { currentMatrix = value; } }

    public Renderer2D(GraphicsBackend backend) { this.backend = backend; CurrentMatrix = Matrix.Identity; }
}

public class Renderer2DXNA : Renderer2D
{
    #region Static: 1 Pixel Texture

    private static Texture2D filler;
    private static bool Initialised { get { return filler != null; } }

    public static void Initialise(GraphicsBackendXNA backend)
    {
        filler = CreateFiller(backend)
    }

    private static Texture2D CreateFiller(GraphicsBackendXNA backend)
    {
        Texture2D rt = new Texture2D(backend.Device.GraphicsDevice, 1, 1);
        rt.SetData<Microsoft.Xna.Framework.Color>(new Microsoft.Xna.Framework.Color[] { Microsoft.Xna.Framework.Color.White });
        return rt;
    }

    #endregion

    #region Data: Fields

    private SpriteBatch renderer;

    #endregion

    #region Methods: Construction

    public Renderer2DXNA(GraphicsBackendXNA backend) : base(backend)
    {
        if (!Initialised)
            Initialise(backend);

        renderer = new SpriteBatch(backend.Device.GraphicsDevice);
    }

    #endregion

    #region Methods: Begin and End

    public override void Begin(Core.Graphics.SpriteSortMode sortMode, BlendMode blendMode, Core.Matrix transformMatrix)
    {
        renderer.Begin(); // Obviously not fully implemented, but simple for now.
    }

    public override void End() { renderer.End(); }

    #endregion

    #region Methods: Draw Image

    public override void Draw(Image Image, Core.Rectangle Boundary, Core.Rectangle? Source, Colour DrawColour, float RotationRadians, Core.Vector2 Origin, Core.SpriteEffects Effects, float Layer)
    {
        if (!(Image is ImageXNA))
            return;

        ImageXNA realImage = Image as ImageXNA;
        Microsoft.Xna.Framework.Rectangle finalSource = 
            Source.HasValue ? Source.Value.ToXNARectangle()
            : new Microsoft.Xna.Framework.Rectangle(0, 0, realImage.Width, realImage.Height);

        renderer.Draw(
            realImage.Texture,
            Boundary.ToXNARectangle(),
            finalSource,
            new Microsoft.Xna.Framework.Color(DrawColour.R, DrawColour.G, DrawColour.B, DrawColour.A),
            RotationRadians,
            Origin.ToXNAVector2(),
            (SpriteEffects)((int)Effects),
            Layer);
    }         

    #endregion

}
// I'll leave off string and shape drawing, considering they're not being used here.

【问题讨论】:

  • 如果你真的使用GraphicsDeviceManagerproperly,你能看到会发生什么吗?您应该在构造函数中设置所需的图形设置,然后Game 将在调用Initialize 之前使用它来初始化设备。不知道这是否能解决您的问题 - 但值得一试。
  • 我尝试将所有图形设置移动到构造函数中,并按照您提供的链接中的建议放弃了对 ApplyChanges 的调用。不幸的是,问题仍然存在。对我来说很明显我已经在某个地方塞满了东西,但很奇怪它只出现在手机的横向设置上,这是示例之间唯一改变的事情。我会继续寻找,但知道在这些特定情况下会导致这种故障的原因是什么吗? (另外,感谢您到目前为止的帮助,它可能无法解决问题,但无论如何这是一个很好的做法。)
  • 很高兴为您提供帮助 - 可惜没有修复它那么简单。您能否澄清一下:您发布的代码是重现问题所需的最低代码吗?你能把它归结为一个简单的复制案例吗?还有:这会发生在硬件上还是模拟器上,还是两者兼而有之?
  • 我正在整理适用于该问题的全套相关代码,上面的代码是对图形设备或 spritebatch 进行任何引用的全套代码。我刚刚进行了测试,似乎错误不会发生在实际硬件上,只是模拟器。这当然是个好消息,但似乎更令人困惑。
  • 我为更重要的类添加了很多代码。还有一些其他相关的类、结构和枚举,我可以很快了解它们。不过,我已经对它们进行了相当详细的检查,到目前为止没有任何问题。

标签: c# windows-phone-7 graphics xna visual-glitch


【解决方案1】:

在构造函数中添加 device.IsFullScreen = true; 为我解决了类似的问题。每当我尝试绘制任何东西时,我都会看到对角线的图案。

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        graphics.PreferredBackBufferWidth = 480;
        graphics.PreferredBackBufferHeight = 800;
        graphics.IsFullScreen = true;

        // Frame rate is 30 fps by default for Windows Phone.
        TargetElapsedTime = TimeSpan.FromTicks(333333);

        // Extend battery life under lock.
        InactiveSleepTime = TimeSpan.FromSeconds(1);
    }

Here's how my glitch looked like

【讨论】:

  • 线路在启动过程中短暂闪烁,然后...没有问题。我不知道为什么要修复它,但它似乎已经这样做了。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-22
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多