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
);
}
此外,欢迎为它提供任何一般提示。我是一个相当新的程序员,样式技巧很受欢迎。
我对最新的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()是如何工作的,但这无论如何都会提高程序的效率。