Xna “看见”;“包装”;使用时的纹理";夹;游戏模式(包括图片)

Xna “看见”;“包装”;使用时的纹理";夹;游戏模式(包括图片),xna,monogame,spritebatch,Xna,Monogame,Spritebatch,我在我的MonoGame项目中使用sprite批渲染一个平铺贴图 以下是渲染代码: protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Camera

我在我的MonoGame项目中使用sprite批渲染一个平铺贴图

以下是渲染代码:

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);

        SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, CameraManager.pInstance.pFinalTransform);

        foreach( TmxLayer Layer in mCurrentTileMap.Layers)
        {
            for (int y = 0; y < mCurrentTileMap.Height; y++)
            {
                for (int x = 0; x < mCurrentTileMap.Width; x++)
                {
                    TmxLayerTile Tile = Layer.Tiles[mCurrentTileMap.Width * y + x];
                    int TileID = -1;
                    Texture2D Texture = FindTileMapTextureForTileID(Tile.Gid, out TileID);
                    if (TileID > 0)
                    {
                        int atlasX = TileID % (Texture.Width / TileSize);
                        int atlasY = TileID / (Texture.Width / TileSize);

                        SpriteEffects FX = SpriteEffects.None;
                        if (Tile.HorizontalFlip)
                        {
                            FX = SpriteEffects.FlipHorizontally;
                        }

                        SpriteBatch.Draw(Texture, new Vector2(x * TileSize, y * TileSize), new Microsoft.Xna.Framework.Rectangle(atlasX * TileSize, atlasY * TileSize, TileSize, TileSize), Color.White, 0, Vector2.Zero, 1, FX, 0);
                    }
                }
            }
        }
如您所见,我使用的是
samplestate.PointClamp
。然而,当我环游世界时,我偶尔会看到这种事情;在一些瓷砖下面,您可以看到一行像素,这是sprite atlas中它下面的像素

单击放大以清楚地看到问题

我非常确定这是因为应用于sprite批处理(
CameraManager.pInstance.pFinalTransform
)的转换使用浮点percision。如果我强制将转换的比例部分钳制为整数,则不会出现问题。但是,这样做会导致相机移动非常不平稳(我的游戏非常放大,所以显示器上的每个像素约为10像素),因此这不是一个好的解决方案

有没有关于如何避免这种影响的想法

下面是源纹理精灵表的外观,供参考

我非常确定这是因为应用于sprite批处理(CameraManager.pInstance.pFinalTransform)的转换使用浮点percision

是的,这听起来是对的。在摄影机缩放贴图分片后,在中编写分片贴图渲染器时,我们遇到了类似的问题

解决方案是首先将未缩放贴图渲染为
RenderTarget2D
,然后在第二次过程中缩放整个对象。这样,您就不会缩放每个单独的分幅,而是将地图作为一个整体进行缩放

您可以看到这是如何与MonoGame一起工作的

在您的情况下,代码可能如下所示:

private readonly RenderTarget2D _renderTarget;

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.SetRenderTarget(_renderTarget); 

    GraphicsDevice.Clear(Color.Black);

    SpriteBatch.Begin(sortMode: SpriteSortMode.Deferred, samplerState: SamplerState.PointClamp);

    foreach( TmxLayer Layer in mCurrentTileMap.Layers)
    {
        for (int y = 0; y < mCurrentTileMap.Height; y++)
        {
            for (int x = 0; x < mCurrentTileMap.Width; x++)
            {
                TmxLayerTile Tile = Layer.Tiles[mCurrentTileMap.Width * y + x];
                int TileID = -1;
                Texture2D Texture = FindTileMapTextureForTileID(Tile.Gid, out TileID);
                if (TileID > 0)
                {
                    int atlasX = TileID % (Texture.Width / TileSize);
                    int atlasY = TileID / (Texture.Width / TileSize);

                    SpriteEffects FX = SpriteEffects.None;
                    if (Tile.HorizontalFlip)
                    {
                        FX = SpriteEffects.FlipHorizontally;
                    }

                    SpriteBatch.Draw(Texture, new Vector2(x * TileSize, y * TileSize), new Microsoft.Xna.Framework.Rectangle(atlasX * TileSize, atlasY * TileSize, TileSize, TileSize), Color.White, 0, Vector2.Zero, 1, FX, 0);
                }
            }
        }
    }

    SpriteBatch.End();

    GraphicsDevice.SetRenderTarget(null);

    SpriteBatch.Begin(sortMode: SpriteSortMode.Immediate, blendState: BlendState.NonPremultiplied,
        samplerState: SamplerState.PointClamp, transformMatrix: CameraManager.pInstance.pFinalTransform);
    SpriteBatch.Draw(_renderTarget, Vector2.Zero, Color.White);
    SpriteBatch.End();
}
_renderTarget = new RenderTarget2D(graphicsDevice, width*tileWidth, height*tileHeight);

它需要足够大才能渲染地图。理想情况下,它将被优化为只渲染地图的可见部分,但这是另一回事。

感谢您的详细回复。我给了你一个建议,它确实解决了这个问题,但在这个过程中,我失去了“亚像素运动”。之前,游戏像素最终会在4个或更多屏幕像素上渲染,因此角色(和相机)的移动(和渲染)距离可以小于一个像素宽。现在,因为它在“真实”像素空间中渲染,所以如果角色向右移动(例如)0.25像素,它们实际上不会在屏幕上移动。最终的结果是一个非常紧张的动作。有趣的。。。显然,我不知道细节,所以我不知道如何帮助你。我仍然认为这是解决这个问题的正确方法。也许你可以发布一个关于亚像素运动的新问题。耶,解释起来有点混乱。它很可能出现在MonoGame中。根据我在那里看到的扩展。试着放大最后一个摄像头,比如说放大10倍(这样所有的东西都被放大了)。当精灵在世界空间中移动一个像素时,它现在将在屏幕空间中移动10个像素(是原稿的10倍),这看起来是破损的。无论如何,这并不是真正需要解决的问题,这只是rendertarget方法的一个局限性(再次感谢您的详细回答!!)。我不认为它发生在MonoGame中。扩展,但我可能错了。如果我理解正确,您正在将所有内容渲染到渲染目标?您是否尝试过仅渲染贴图分片并将精灵渲染为第二个渲染过程?另外,试着关闭点夹,看看是否有帮助?
_renderTarget = new RenderTarget2D(graphicsDevice, width*tileWidth, height*tileHeight);