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

时间:2012-03-01 15:35:33

标签: c# xna-4.0

我正在开发基于平铺/精灵的游戏,通过

调用我的Draws
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
            );
    }

此外,欢迎任何一般提示。我是一个非常新的程序员,赞赏造型技巧。

2 个答案:

答案 0 :(得分:0)

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

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

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

如果这没有帮助,请检查ActiveMap.DrawAtDepth()的工作原理,但这样可以提高您的程序效率。

答案 1 :(得分:0)

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

根据您描述的症状以及仅在设置BackToFront SpriteSortMode时发生的这一事实,我希望您要么不为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个图块差异更重要)并且假设基于零的屏幕坐标系在哪里可以在任一轴上的瓦片0到31上。

另据我所知,ActiveMap.DrawAtDepth不是XNA库函数。您能否向我们展示代码,或者向我们展示SpriteBatch.Draw()的实际调用 - 这将有助于人们弄清楚究竟发生了什么,并希望我们不得不猜错。