En supposant que vos sprites occupent des ensembles de carreaux qui sont des rectangles (s'ils occupent des ensembles arbitraires, vous ne pouvez pas du tout dessiner correctement dans le cas général), le problème est qu'il n'y a pas de relation d'ordre total entre les éléments, donc vous ne pouvez pas trier les utilisant un tri qui entraînerait des comparaisons O (nlogn).
Notez que pour deux objets A et B, A doit être dessiné avant B (A <- B), B doit être dessiné avant A (B <- A) ou ils peuvent être dessinés dans n'importe quel ordre. Ils forment un ordre partiel. Si vous vous dessinez quelques exemples avec 3 objets qui se chevauchent, vous remarquerez peut-être que même si le 1er et le 3ème objet ne se chevauchent pas, n'ayant donc pas de dépendance directe, leur ordre de dessin dépend du 2ème objet qui les sépare - selon la façon dont vous le placez, vous obtiendrez différents ordres de dessin. Conclusion - les tris traditionnels ne fonctionnent pas ici.
Une solution consiste à utiliser la comparaison (mentionnée par le Dani) et à comparer chaque objet les uns aux autres pour déterminer leurs dépendances et former un graphe de dépendances (qui sera un DAG). Effectuez ensuite un tri topologique sur le graphique pour déterminer l'ordre de dessin. S'il n'y a pas trop d'objets, cela peut être assez rapide (c'estO(n^2)
).
Une autre solution consiste à utiliser un (pour l'équilibrage - pseudo ) arbre quadruple et à y stocker les rectangles de tous les objets.
Ensuite, parcourez tous les objets X et utilisez l'arborescence quadruple pour vérifier s'il y a des objets Y dans la bande au-dessus de l'objet X qui commence par le plus à gauche et se termine par le coin le plus à droite de l'objet X - pour tous ces Y, Y < - X. Comme ça, vous devrez toujours former un graphe et trier topologiquement.
Mais vous pouvez l'éviter. Vous utilisez une liste d'objets Q et une table d'objets T. Vous parcourez tous les emplacements visibles des valeurs les plus petites aux plus grandes sur l'axe des x (une ligne), en allant ligne par ligne sur l'axe des y. S'il y a un coin inférieur d'un objet à cet emplacement, effectuez la procédure ci-dessus pour déterminer les dépendances. Si un objet X dépend d'un autre objet Y qui est en partie au-dessus de lui (Y <- X), et que chacun de ces Y est déjà dans Q, ajoutez X à Q. S'il y a un Y qui n'est pas dans Q, ajoutez X à T et dénotons Y <- X. Chaque fois que vous ajoutez un objet à Q, vous supprimez les dépendances des objets en attente dans T. Si toutes les dépendances sont supprimées, un objet de T est déplacé vers Q.
Nous supposons que les sprites d'objets ne sortent pas de leurs emplacements en bas, à gauche ou à droite (uniquement en haut, comme les arbres dans votre image). Cela devrait améliorer les performances d'un grand nombre d'objets. Cette approche sera à nouveau O(n^2)
, mais seulement dans le pire des cas, qui comprend des objets de taille étrange et / ou des configurations d'objets étranges. Dans la plupart des cas, c'est le cas O(n * logn * sqrt(n))
. La connaissance de la hauteur de vos sprites peut éliminer le sqrt(n)
, car vous n'avez pas à vérifier toute la bande ci-dessus. Selon le nombre d'objets à l'écran, vous pouvez essayer de remplacer l'arborescence quadruple par un tableau indiquant les emplacements à prendre (cela a du sens s'il y a beaucoup d'objets).
Enfin, n'hésitez pas à inspecter ce code source pour trouver des idées: https://github.com/axel22/sages/blob/master/src/gui/scala/name/brijest/sages/gui/Canvas.scala