我正在使用精灵批处理在我的MonoGame项目中渲染一个平铺地图。
以下是渲染代码:
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);
}
}
}
}
以下是我认为重要的代码行:
SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp,
null, null, null, CameraManager.pInstance.pFinalTransform);
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);
如您所见,我正在使用SamplerState.PointClamp
。然而,当我在世界各地移动时,我偶尔会看到这个类的东西;在某些瓷砖下方,您可以看到一行像素,即精灵地图集中位于其下方的像素。
我很确定这种情况正在发生,因为应用于sprite批处理(CameraManager.pInstance.pFinalTransform
)的转换正在使用浮点运算。如果我强行将该变换的比例部分钳制为整数,则不会出现问题。然而,这样做会导致非常抖动的相机移动(我的游戏非常放大,因此每个像素在显示器上约为10个像素),因此这不是一个好的解决方案。
关于如何避免这种影响的任何想法?
以下是源纹理精灵表的外观,供参考。
答案 0 :(得分:1)
是的,这听起来很对。当地图图块被相机缩放后,我们在MonoGame.Extended中编写了Tiled地图渲染器时遇到了类似的问题。我很确定这种情况正在发生,因为应用于sprite批处理的转换(CameraManager.pInstance.pFinalTransform)正在使用浮点运算。
解决方案是首先将未缩放的地图渲染为db.tapwiser.find({"custID" : "12345"}, {}, {}).count();
,然后在第二遍中缩放整个事物。这样您就不会缩放每个单独的图块,而是整个地图。
您可以在TiledMap class。
中查看MonoGame.Extended的工作原理在您的情况下,代码可能如下所示:
db.tapwiser.find({"custID" : "6789"}, {}, {}).count();
请注意,我已将相机转换移至第二个RenderTarget2D
调用并引入了新的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();
}
成员变量。在调用SpriteBatch.Begin
之前,不要忘记在某处声明_renderTarget
。像这样:
_renderTarget
它需要足够大才能渲染你的地图。理想情况下,它会被优化为仅渲染地图的可见部分,但这是另一个故事。