MonoGame - RenderTarget2D在精灵下方和错误的位置绘制

时间:2017-01-16 10:17:52

标签: c# text scroll 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
        );
    }

1 个答案:

答案 0 :(得分:0)

我决定改用Viewport。但是,似乎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()。在绘制了所有其他内容之后,在spriteBatch上调用WriteLog()之后,在Draw()函数中调用End()