2012-08-10 1 views
3

Я работаю над кросс-платформенным фреймворком/абстракционным слоем в течение нескольких месяцев, основываясь на платформе XNA для WP7 и Mono для Android и iOS , Получив большинство функциональных возможностей для Android, я недавно вернулся в WP7, чтобы получить простую игру, работающую на обеих платформах.Графический сбой в XNA на Windows Phone 7 в альбомной ориентации

Проблема в том, что я столкнулся с очень странной графической ошибкой. Ошибка не возникает в XNA-игре на базе Windows и встречается только на WP7, когда ориентация является Landscape (по умолчанию или указана). Сбой появляется на эмуляторе, но не на физическом устройстве. Для тестирования я показываю одно изображение на красном фоне.

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)

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.

Game Class

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 

График Backend Класс

Графических бэкенд (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 

Renderer 2D XNA Класс

Отображатель 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. 
+0

Не могли бы вы посмотреть, что произойдет, если вы на самом деле использовать 'GraphicsDeviceManager' [правильно] (http://stackoverflow.com/a/11287316/165500)? Вы должны установить желаемые параметры графики в конструкторе, который затем «Игра» будет использоваться для инициализации устройства до вызова «Инициализация». Не знаю, поможет ли это решить вашу проблему, но это стоит того. –

+0

Я попытался переместить все настройки графики в конструктор и сбросил вызов ApplyChanges, как это рекомендовано в предоставленной вами ссылке. К сожалению, проблема сохраняется. Для меня очевидно, что я собрал где-то вдоль линии, но очень странно, что это происходит только в настройках пейзажа на телефоне, поскольку это единственное, что изменилось между примерами. Я буду продолжать смотреть, но любая идея, что может вызвать подобную ошибку в этих конкретных обстоятельствах? (Кроме того, спасибо за вашу помощь до сих пор, возможно, она не исправила проблему, но это хорошая практика.) –

+0

Рад помочь - жаль, что это было не так просто, как исправить это. Можете ли вы уточнить: есть ли код, который вы опубликовали, минимальный код, необходимый для воспроизведения проблемы? Можете ли вы сварить его до простого случая размножения? А также: это происходит на аппаратном или симуляторе или на обоих? –

ответ

2

добавления 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

+0

Строки ненадолго мерцали во время запуска, а затем ... проблема свободна. Я понятия не имею, почему это исправлено, но, похоже, это так. Спасибо. –

Смежные вопросы