Pour répondre à ta question, j'utilise souvent mes propres objets pour dessiner dans un jeu, et ces objets sont directement dessinables via plusieurs moyens différents.
On peut par exemple hériter de sf::Drawable, et réimplémenter la fonction draw() pour alors afficher tous les sprites que l'on contient.
On peut aussi juste contenir une liste de sprite, et implémenter une méthode qui prend en argument la cible d'affichage (RenderWindow par exemple) et qui va boucler pour afficher tous les sprites que l'objet contient.
Je ne sais pas quelle méthode est la plus propre ou la plus agréable, mais j'ai déjà utilisé les deux.
Concernant les soucis de devant/derrière, j'ai une petite idée qui vaudrait peut-être le coup d'être essayé.
Imaginons notre héros sur une minimap, et le souci est de l'afficher au bon moment pour être derrière notre arbre, mais devant la pierre et le sol. Il suffit donc d'affiche notre minimap, mais d'afficher le héro au bon moment (puisque le problème interne à la minimap ne se pose pas si tu l'as créée correctement).
On pourrait donc essayer par exemple de donnée les éléments qui bougent et les éléments qui ne bougent pas, puis de parcourir les éléments qui ne bougent pas, et quand on arrive aux bonnes ordonnées (le y du héro est entre les deux objets non bougeants), alors on affiche le héros, puis on continue le parcours de notre liste.
On peut généraliser cette méthode à plusieurs object bougeant, en triant d'abord la liste des bougeant (ou juste en swappant les éléments qui ont bougé d'ordre d'une image à l'autre, si on veut optimiser), puis on parcours les immobiles en insérant les mobiles au bon moment.