Forgotten Elixir

An enchanting engine where magic and technology intertwine

Sorting sprites by distance from player

created: 2025-03-31 04:26:29 UTC
last updated: 2025-03-31 04:35:54 UTC

It has been a little while since I last posted. I have been working on the engine and have gotten quite a bit done. Some of it was refactoring along with some features. But since then, probably the largest feature, is sorting sprites for a draw order. Up until now, sprites were not really ordered. If a player was lined up in such a way that there is a straight line in the field of view from the player to a barrel and armor, and the barrel was behind the armor, the barrel may render over the sprite for the order. I guess a good way to term it is, it could clip. So both would be rendered. But this is not what is really wanted. If the amour is before the barrel, the player should see the full armor set and maybe bit of the barrel. Such as the sides of the barrel if the barrel is wider than the amor.

To fix this, I just needed to sort the draw order. I do have a drawOrder property on the SpriteComponent, however, it is not that useful since these sprites may have a different draw order depending on the player position. The way the draw order is handled is more in line with painter's algorithm and in such a way it lends itself better to something like 2-D top down or you have clear defined layers. For actors with sprites, like a barrel and maybe a table, they exist on sort of the same layer, but one may need to be infant of the other.

How to solve this? Actually quite simple, at least for right now since it does not appear to have a big performance impact. At least not from a playable perspective on my machine. But I needed a way to loop over all SpriteComponent components in the scene. I do attach the SpriteComponent to each Actor and it has it in its vector of Components. Well, this presented a little bit of a problem. In my draw logic, I loop over all components on actors that have RenderComponent types and call the draw functions there. So it makes a little harder to order. I could have just ordered the actors by their positions, but that seemed a little too much. Instead, I created a vector of sprites in my game class that had references to the SpriteComponent of each actor. Then I just loop over that.

Now, for ordering. Before drawing the sprites, need to sort them. They just need to be sorted by the distance between the player and the actors. So just a simple distance calculation and then putting the ones closer to the player at the beginning of the vector with farther ones at the end. 

Now, time to show some code.

  sort(sprites.begin(), sprites.end(), [](SpriteComponent* a, SpriteComponent* b) {
    return a->DistanceFromPlayer() > b->DistanceFromPlayer();
  });
  
  for (auto sprite : sprites) {
    sprite->Draw(graphics);
  }