C#:XNA4:SpriteSortMode在X轴上随机排序

本文关键字:随机 排序 XNA4 SpriteSortMode | 更新日期: 2023-09-27 18:26:11

我正在开发一款基于tile/sprite的游戏,通过调用我的Drawings

public void Draw(SpriteBatch spriteBatch)
    {
        DrawBehind(spriteBatch);
        DrawEven(spriteBatch);
        DrawInFront(spriteBatch);
    }
    private void DrawBehind(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        ActiveMap.DrawAtDepth(spriteBatch, Player, 1);
        spriteBatch.End();
    }
    private void DrawEven(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin(SpriteSortMode.BackToFront, null);
        ActiveMap.DrawAtDepth(spriteBatch, Player, -1);
        Player.Draw(spriteBatch);
        spriteBatch.End();
    }
    private void DrawInFront(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        ActiveMap.DrawAtDepth(spriteBatch, Player, 0);
        spriteBatch.End();
    }

正如预期的那样,DrawBehind和DrawInFront只是根据他们所称的顺序进行绘制,在X和Y上都很稳定。

DrawEven在Y轴上正确排序,但在X轴上,精灵似乎只是无缘无故地前后翻转。

如果它是稳定的,我真的不在乎它按哪个顺序排序。相反,每次我"移动我的角色"(移动除了我角色的精灵之外的所有精灵的位置)时,它都会闪烁并切换。有人知道是什么原因或如何解决吗?

根据要求

编辑:

地图:

public void DrawAtDepth(SpriteBatch spriteBatch, Player player, int depth)
    {
        Area.DrawAtDepth(spriteBatch, player, depth);
    }

区域:

public void DrawAtDepth(SpriteBatch spriteBatch, Player player, int depth)
    {
        const int border = 10;
        var screenTiles = new Rectangle(
            0 - border,
            10 - border,
            (GameMain.ScreenRectangle.Width / Tile.Width - 1) + border,
            (GameMain.ScreenRectangle.Height / Tile.Height - 1) + 10 + border);
        var playerLevelPosition = player.LevelPosition;
        for (int layer = 0; layer < _layerCount; layer++)
            if (ActiveLevels[1, 1].GetLayerDepth(layer) == depth)
                for (int y = screenTiles.Y; y < screenTiles.Height; y++)
                    for (int x = screenTiles.X; x < screenTiles.Width; x++)
                        Draw(spriteBatch, player, playerLevelPosition, layer, x, y);
    }
private void Draw(SpriteBatch spriteBatch, Player player, Vector2 playerLevelPosition, int layer, int x, int y)
    {
        int levelX;
        var tileX = TilePos((int)playerLevelPosition.X, Level.Width, x, out levelX);
        int levelY;
        var tileY = TilePos((int)playerLevelPosition.Y, Level.Height, y, out levelY);
        var level = ActiveLevels[levelX, levelY];
        if (level != null)
            level.Draw(spriteBatch, player, layer, new Vector2(tileX, tileY));
    }
    private float TilePos(int playerPos, int mapBounds, int offset, out int levelPos)
    {
        var tilePos = ((playerPos) - (mapBounds/2f - 1)) + offset;
        levelPos = 1;
        if (tilePos < 0)
        {
            levelPos = 0;
            return tilePos + mapBounds;
        }
        if (tilePos >= mapBounds)
        {
            levelPos = 2;
            return tilePos - mapBounds;
        }
        return tilePos;
    }
    public static float GetDepth(float tilePos)
    {
        return 1 - tilePos / (Level.Height * 3);
    }

层:

public void Draw(SpriteBatch spriteBatch, Vector2 tile, Vector2 drawPosition, Color color, bool transparent = false)
    {
        if (_grid[(int)tile.X, (int)tile.Y] == null) return;
        _grid[(int)tile.X, (int)tile.Y].Draw(spriteBatch, drawPosition, color, transparent, (Depth != -1) ? Depth : Area.GetDepth(Level.Height + tile.Y));
    }

瓷砖:

public override void Draw(SpriteBatch spriteBatch, Vector2 drawPosition, Color color, bool transparent = false, float depth = 0)
    {
        if (!GameMain.ScreenRectangle.Intersects(_sprite.Bounds)) return;
        if (transparent && _fade)
            color = new Color(255, 255, 255, 100);
        spriteBatch.Draw(
            _sprite,
            drawPosition,
            null,
            color,
            0,
            new Vector2(_sprite.Width / 2 - Width / 2, _sprite.Height),
            1,
            SpriteEffects.None,
            depth
            );
    }

此外,欢迎为它提供任何一般提示。我是一个相当新的程序员,样式技巧很受欢迎。

C#:XNA4:SpriteSortMode在X轴上随机排序

我对最新的XNA4并不完全熟悉,所以这可能不是正确的答案,但:

从你描述的症状以及只有当你设置BackToFront精灵排序模式时才会发生的事实来看,我认为你要么没有为DrawEven中绘制的一些精灵设置深度坐标,要么没有让它们变得足够不同。因此,我认为它试图覆盖正常的延迟渲染顺序,但没有足够的深度信息,只是在每帧中选择一个任意顺序(可能是由于浮点不准确?不确定,但似乎很可能。)

既然你提到它在Y轴上正确排序,那么假设你使用Y坐标作为层深度的输入,也可以尝试添加少量的X坐标。假设屏幕上有32乘32个瓦片,我会这样计算层深度浮点值:

float depth = (someSprite.ScreenYCoord / 32) + (someSprite.ScreenXCoord / 1025);
spriteBatch.Draw(texture, position, sourceRect, color, rotation, origin, scale, spriteEffects, depth);

其中1025是32*32+1(以确保在排序时Y中的1个瓦片的差总是比X中的32个瓦片的全差更重要),并且假设基于零的屏幕坐标系。

此外,据我所知,ActiveMap.DrawAtDepth不是一个XNA库函数。你能给我们看一下代码吗?或者给我们看一看对SpriteBatch.Draw()的实际调用在哪里?这将帮助人们了解到底发生了什么,希望这意味着我们可以少猜测。

spritebatch Begin()和End()的想法是最小化对它的调用量以提高性能,因此很清楚,它们中的2个之间的所有内容都将按顺序绘制。将您的代码更改为:

spriteBatch.Begin();
DrawBehind(spriteBatch);
DrawEven(spriteBatch);
DrawInFront(spriteBatch); 
spriteBatch.End();

并删除这些函数中Begin()和End()的所有实例。

如果这没有帮助,请检查ActiveMap.DrawAtDepth()是如何工作的,但这无论如何都会提高程序的效率。