简体   繁体   English

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

[英]C# : XNA4 : SpriteSortMode on X-axis sorts at random?

I'm working on a tile/sprite-based game, calling my Draws via 我正在开发基于图块/精灵的游戏,通过

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();
    }

As expected, DrawBehind and DrawInFront just draw based on the order they are called, stable and well on both X and Y. 不出所料,DrawBehind和DrawInFront只是根据它们被调用的顺序绘制,并且在X和Y上都稳定且良好。

DrawEven sorts on the Y-axis correctly, but on the X-axis, the sprites just seem to flip in front of eachother and back for no apparent reason. DrawEven在Y轴上正确排序,但在X轴上,精灵似乎只是在彼此前后翻转而没有明显的原因。

If it would be stable, I don't really care in which order it sorts it. 如果它是稳定的,我真的不在乎它按什么顺序排序。 Instead, everytime I "move my character" (move the position of all the sprites but my character's), it flickers and switches all around. 取而代之的是,每当我“移动我的角色”(移动除我角色以外的所有子画面的位置)时,它都会闪烁并在周围切换。 Anyone knows what causes this or how to fix it? 谁知道是什么原因或如何解决?

As per request 按要求

EDIT: 编辑:

Map: 地图:

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

Area: 区域:

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);
    }

Layer: 层:

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));
    }

Tile: 瓦:

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
            );
    }

Also, any general tips for the sake of it are welcome. 另外,欢迎使用任何一般性提示。 I'm a pretty new programmer, styling tips are appreciated. 我是一个非常新的程序员,非常感谢样式提示。

The idea of spritebatch Begin() and End() is to minimize the amount of calls to it to increase performace, so it was concievedthat everything between 2 of them will be drawn in order. spritebatch Begin()和End()的想法是为了最大程度地减少对它的调用,以提高性能,因此确信可以将其中2个之间的所有内容按顺序绘制。 Change your code to this: 将代码更改为此:

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

and remove all instances of Begin() and End() in those functions. 并删除这些函数中Begin()和End()的所有实例。

If that doesn't help, check how ActiveMap.DrawAtDepth() works, but that should improve your program effciency in any case. 如果那没有帮助,请检查ActiveMap.DrawAtDepth()的工作方式,但这在任何情况下都可以提高程序效率。

I'm not completely familiar with the latest XNA 4, so this might not be -the- correct answer, but: 我对最新的XNA 4并不完全熟悉,所以这可能不是正确的答案,但是:

From the symptoms you describe and the fact that it's only happening when you set the BackToFront SpriteSortMode, I would expect that you're either not setting a depth coordinate for some of the sprites being drawn in DrawEven or not making them different enough. 根据您描述的症状以及仅在设置BackToFront SpriteSortMode时才发生的事实,我希望您没有为在DrawEven中绘制的某些精灵设置深度坐标,或者没有为它们设置足够的差异。 As such, I believe that it is trying to override the normal deferred render order, but doesn't have enough depth information and just picks an arbitrary order each frame (perhaps due to floating point inaccuracy? Not certain, but it seems likely.) 因此,我相信它正在尝试覆盖正常的延迟渲染顺序,但没有足够的深度信息,并且仅在每个帧中选择一个任意顺序(可能是由于浮点不准确?不确定,但似乎很有可能。)

Since you mention it's sorting properly on the Y axis, then assuming you're using the Y coordinate as an input to the layer depth, try adding a very small amount of the X coordinate as well. 由于您提到它在Y轴上正确排序,因此假设您使用Y坐标作为图层深度的输入,请尝试也添加少量X坐标。 Assuming 32 by 32 tiles on screen, I would calculate the layer depth floating point value like this: 假设屏幕上有32 x 32瓦片,我将像这样计算层深度浮点值:

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

where 1025 is 32 * 32 + 1 (to make sure that a difference of 1 tile in Y is always more important when sorting than even a full 32 tiles difference in X) and assuming a zero-based screen coordinate system where something can be on tile 0 to 31 in either axis. 其中1025是32 * 32 +1(以确保排序时Y上的1个图块的差异总是比X中的完整32个图块的差异更重要),并假设从零开始的屏幕坐标系在任一轴上平铺0到31。

Also as far as I can tell ActiveMap.DrawAtDepth is not an XNA library function. 而且据我所知ActiveMap.DrawAtDepth不是XNA库函数。 Can you show us the code for that please, or show us wherever else the actual calls to SpriteBatch.Draw() are - that would help people work out what exactly is happening, and hopefully mean we have to guess less. 您能否向我们显示代码,还是向我们显示对SpriteBatch.Draw()的实际调用,这将帮助人们弄清楚到底发生了什么,并希望意味着我们不必做太多猜测。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM