2017-01-16 70 views
1

這看起來很簡單,但仍然不起作用。所以我試圖通過使用RenderTarget2D繪製一個可滾動的日誌窗口(不滾動)。MonoGame - RenderTarget2D在精靈和錯誤位置下繪製

Render target bugs

有以下幾種錯誤:

  • 案文應在黑色背景上繪製,現在看來透明
  • 文本應該在遊戲區域下方的黑盒子繪製,現在它被畫在左上角
  • 文本現在只出現在背景顏色上,它應該畫在其他精靈上

我的代碼有什麼問題?相關部分如下。

private GraphicsDevice graphicsDevice; 
    private RenderTarget2D logRenderTarget; 

    private bool redrawLogFlag; 

    public void Init(ContentManager content, GraphicsDevice graphicsDevice) 
    { 
     this.graphicsDevice = graphicsDevice; 
     logRenderTarget = new RenderTarget2D(
      graphicsDevice, 
      10, 
      10 
     ); 
     Log.LogWritten += SetRedrawLogFlag; 
    } 

    private void DrawUiComponents(SpriteBatch spriteBatch) 
    { 
     spriteBatch.Draw(Scavenger.AssetManager.TextureMap["game_area"], Vector2.Zero, Color.White); 
     spriteBatch.Draw(Scavenger.AssetManager.TextureMap["log_area"], new Vector2(0, Constants.GAME_AREA_HEIGHT), Color.White); 
     spriteBatch.Draw(Scavenger.AssetManager.TextureMap["stats_area"], new Vector2(Constants.GAME_AREA_WIDTH, 0), Color.White); 
     spriteBatch.Draw(Scavenger.AssetManager.TextureMap["help_info"], new Vector2(Constants.GAME_AREA_WIDTH, Constants.SCREEN_HEIGHT - 52), Color.White); 

     DrawStats(spriteBatch); 
     TryRedrawLog(spriteBatch); 
     WriteLog(spriteBatch); 
    } 

    private void SetRedrawLogFlag(object sender, EventArgs e) 
    { 
     redrawLogFlag = true; 
    } 

    private void TryRedrawLog(SpriteBatch spriteBatch) 
    { 
     if(redrawLogFlag) 
     { 
      redrawLogFlag = false; 

      logRenderTarget = new RenderTarget2D(
       this.graphicsDevice, 
       Constants.GAME_AREA_WIDTH, 
       Log.Height 
      ); 

      this.graphicsDevice.SetRenderTarget(logRenderTarget); 
      this.graphicsDevice.Clear(Color.Black); 

      for (int i = 0; i < Log.Count; i++) 
      { 
       spriteBatch.DrawString(Scavenger.AssetManager.Font12, 
        Log.Entries[i], 
        new Vector2(Constants.LOG_MARGIN, Constants.LOG_MARGIN + i * Scavenger.AssetManager.Font12.LineSpacing), 
        Color.GreenYellow 
       ); 
      } 

      this.graphicsDevice.SetRenderTarget(null); 
     } 
    } 

    private void WriteLog(SpriteBatch spriteBatch) 
    { 
     spriteBatch.Draw(logRenderTarget, 
      new Rectangle(0, Constants.GAME_AREA_HEIGHT, Constants.GAME_AREA_WIDTH, Constants.LOG_HEIGHT), 
      new Rectangle(0, 0, Constants.GAME_AREA_WIDTH, Constants.LOG_HEIGHT), 
      Color.White 
     ); 
    } 

回答

0

我決定切換到使用視口。但是,似乎MonoGame在調用spriteBatch.End()之前使用最後一個設置的視口。它也似乎與ScissorRectangle一樣,所以我可以使它也起作用。我在評論中添加了ScissorRectangle特定的代碼。這是我的新類:

public class LogWriter 
{ 
    private GraphicsDevice graphicsDevice; 

    private Viewport defaultViewport, logViewport; 
    //private Rectangle scissor, scissorBackup; 

    public void Init(GraphicsDevice graphicsDevice) 
    { 
     this.graphicsDevice = graphicsDevice; 

     defaultViewport = this.graphicsDevice.Viewport; 
     logViewport = new Viewport(0, Constants.GAME_AREA_HEIGHT, Constants.GAME_AREA_WIDTH, Constants.LOG_HEIGHT); 

     //scissor = new Rectangle(0, Constants.GAME_AREA_HEIGHT, Constants.GAME_AREA_WIDTH, Constants.LOG_HEIGHT); 
     //scissorBackup = this.graphicsDevice.ScissorRectangle; 
    } 

    public void WriteLog(SpriteBatch spriteBatch) 
    { 
     this.graphicsDevice.Viewport = logViewport; 
     //this.graphicsDevice.ScissorRectangle = scissor; 

     spriteBatch.Begin(); 
     //spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, new RasterizerState() { ScissorTestEnable = true }); 

     for (int i = 0; i < Log.Count; i++) 
     { 
      spriteBatch.DrawString(Scavenger.AssetManager.Font12, 
       Log.Entries[i], 
       new Vector2(
        Constants.LOG_MARGIN, 
        Constants.LOG_MARGIN - 100 + i * Scavenger.AssetManager.Font12.LineSpacing), 
       Color.GreenYellow 
      ); 
     } 

     spriteBatch.End(); 

     this.graphicsDevice.Viewport = defaultViewport; 
     //this.graphicsDevice.ScissorRectangle = scissorBackup; 
    } 
} 

Init()是所謂的LoadContent()功能。 WriteLog()在繪製所有其他東西后,在spriteBatch上調用了End()後,在Draw()函數中調用該函數。