I am working on a 2D game engine in C# using OpenGL. I am trying to find a collection to satisfy my needs for sprite ordering, and I can't seem to find the combination of performance and functionality.
The following is the criteria I am after:
- The ability to be iterated over in order according to "Z" value, which may change for any sprite at any time
- Possible for many sprites to be added/removed within a single frame, so sorting each time a value was added/removed will have large performance impact without the correct implementation
- Insertion/removal speed is much lower priority than access speed during enumeration
- Have no need for indexing
- Only unique values, but with the correct collection, I can manage that manually if the base collection does not implement it, as I do in the example
Currently, this is the best I could come up with. (I removed all the interface implementations for clarity, leaving only the important stuff)
public class SpriteBatch : ICollection<IRenderable>
{
private readonly Dictionary<uint, IRenderable> _dict;
private readonly List<uint> _keys;
private bool _needSort;
public SpriteBatch()
{
_dict = new Dictionary<uint, IRenderable>();
_keys = new List<uint>();
_needSort = false;
}
public void Add(IRenderable renderable)
{
if (renderable == null)
throw new ArgumentNullException(nameof(renderable), "Item cannot be undefined.");
if (_dict.ContainsKey(renderable.Id))
return;
_needSort = true;
renderable.Disposed += (sender, args) => Remove(renderable);
renderable.ZChanged += (sender, args) => _needSort = true;
_keys.Add(renderable.Id);
_dict.Add(renderable.Id, renderable);
}
public bool Remove(IRenderable renderable)
{
if (renderable == null)
return false;
_dict.Remove(renderable.Id);
return _keys.Remove(renderable.Id);
}
public IEnumerator<IRenderable> GetEnumerator()
{
if (_needSort)
_keys.Sort((a, b) => _dict[a].Z.CompareTo(_dict[b].Z));
foreach (var key in _keys)
yield return _dict[key];
}
}
Was curious if anyone else had a better approach, or what the "standard" tried-and-true way of doing this is?