如何按照给定的叠加顺序绘制图片?(层..)



我正在制作一个2D游戏引擎,它在基本级别上运行良好。现在我想对它进行微调,并为引擎添加一些额外的(但必要的(功能。不幸的是,我坚持我的";层";系统

你可以想象这在Unity中是一样的,或者像Photoshop中的图层。。。我想确定精灵(图像(的显示顺序。大多数";解决方案";我发现说";在另一个图像之前绘制一个图像,这样这将显示在顶部"是的,我知道这是怎么回事,但这不是最好的方式,因为游戏可以包含数千个精灵,渲染顺序也可以由用户动态更改。因此,我需要应用某种"层"系统,用户可以在Sprite类的实例化对象期间设置顺序,或者在需要时通过更改相关属性值来更改层顺序(类似于"layerOrder=2"(。我想,我说的很直白。

有什么合适且成本效益高的方法可以做到这一点吗?这应该具有成本效益,因为Renderer((函数在一秒钟内运行多次,同时在屏幕上绘制大量图像。如果这个";函数";可能是C#本身的一部分,但看起来不是!

这里是我的简化Renderer((方法:

private void Renderer(object sender, PaintEventArgs e)                                                              
{
Graphics g = e.Graphics;
g.Clear(BkgColor);                                                                                              
foreach (Sprite s in RegisterSprite.ToList())
{
g.DrawImage(s.SpriteBmp, s.Position.X, s.Position.Y, s.Size.X * s.Scale.X, s.Size.Y * s.Scale.Y;
}
}

我的精灵类没有什么特别的。。。构造函数,它从给定的目录加载图像,并设置用户通过构造函数传递的属性,如位置、名称等…"RegisterSprite"只是一个包含所有精灵的列表。当用户创建精灵的对象时,精灵会添加到列表中。。(像墙或敌人…(精灵类会自动将新精灵注册到列表中,仅此而已!

请尝试给出一些想法或解决方案,我可以将其集成到我的引擎中。或者让我知道是否有一种内置的方法来做到这一点。很难想象没有任何方法来决定哪一个位图/图像绘制在其他位图/图像之上。。。谢谢

好的TaW在问题的评论部分发布了我的问题解决方案,但我会在这里自我回答,因为TaW看起来不再写答案了。

创建一个"分层系统"比我写问题时想的更简单。我在Sprite类中添加了一个整数变量(layerOrder(,这样我就可以为每个Sprite(图像(设置所需的顺序。正如我提到的,我有一个列表(RegisterSprite(,当我创建每个精灵(实例化对象(时,我会在其中存储它们。然后我写了一个小方法,可以根据精灵的layerOrder值对列表进行排序。这样,列表中的第一个精灵将是最低值,最后一个精灵是最高值。。我使用foreach循环将列表中的每个图像绘制到屏幕上,当然,这将从第一个元素开始。因此,具有较低layerOrder的精灵将首先绘制在具有较高值的精灵下方。重要的是在渲染器(使用foreach(部分之前调用排序方法。

如果需要在"运行时"更改sprite layerOrder,只需在更改值后调用排序算法,或者创建一个方法来更改layerOrder,该方法也会自动对列表进行重新排序。如果需要,优化算法(堆优化?(或编写另一个更新列表的算法(更改相关元素(,以便快速重新排序。。。

以下是我的排序方法和渲染器的简化版本:

public List<Sprite> SortSpriteList(List<Sprite> list)
{
for (int i = 0; i < list.Count - 1; i++)
{
int lowest = i;
int j = i + 1;
for (; j < list.Count; j++)
{
if (list[j].Layer < list[lowest].Layer)
{
lowest = j;
}
}
if (lowest != i)
{
Sprite copy = list[i];
list[i] = list[lowest];
list[lowest] = copy;
}
}
return list;
}

private void Renderer(object sender, PaintEventArgs e)                                                              
{
Graphics g = e.Graphics;
g.Clear(BkgColor);                                                                                              
foreach (Sprite s in RegisterSprite.ToList())
{
g.DrawImage(s.SpriteBmp, s.Position.X, s.Position.Y, s.Size.X * s.Scale.X, s.Size.Y * s.Scale.Y;
}
}

最新更新