Supondo que seus sprites ocupem conjuntos de blocos que são retângulos (se eles ocupam conjuntos arbitrários, então você não pode desenhar corretamente de maneira alguma no caso geral), o problema é que não há uma relação total de ordem entre os elementos, portanto, você não pode classificar usando uma classificação que resultaria em comparações de O (nlogn).
Observe que, para quaisquer dois objetos A e B, A deve ser desenhado antes de B (A <- B), B deve ser desenhado antes de A (B <- A) ou pode ser desenhado em qualquer ordem. Eles formam uma ordem parcial. Se você desenhar alguns exemplos com três objetos sobrepostos, poderá perceber que, embora o primeiro e o terceiro objetos não possam se sobrepor, não tendo uma dependência direta, sua ordem de desenho depende do segundo objeto que está entre eles - dependendo de como Se você colocá-lo, obterá diferentes ordens de desenho. Bottomline - os tipos tradicionais não funcionam aqui.
Uma solução é usar a comparação (mencionada pela Dani) e comparar cada objeto com o outro para determinar suas dependências e formar um gráfico de dependência (que será um DAG). Em seguida, faça uma classificação topológica no gráfico para determinar a ordem do desenho. Se não houver muitos objetos, isso pode ser rápido o suficiente (é O(n^2)
).
Outra solução é usar uma quad tree (para equilibrar - pseudo ) e armazenar os retângulos de todos os objetos nela.
Em seguida, percorra todos os objetos X e use a árvore quádrupla para verificar se há algum objeto Y na faixa acima do objeto X que começa com a extremidade esquerda e termina com o canto mais à direita do objeto X - para todos esses Y, Y < - X. Assim, você ainda precisará formar um gráfico e classificar topologicamente.
Mas você pode evitá-lo. Você usa uma lista de objetos Q e uma tabela de objetos T. Você itera todos os slots visíveis, dos valores menores aos maiores no eixo x (uma linha), passando linha por linha no eixo y. Se houver um canto inferior de um objeto nesse slot, faça o procedimento acima para determinar as dependências. Se um objeto X depender de algum outro objeto Y que esteja parcialmente acima dele (Y <- X), e todos esses Y já estiverem em Q, adicione X a Q. Se houver algum Y que não esteja em Q, adicione X a T e denote que Y <- X. Toda vez que você adiciona um objeto a Q, você remove dependências de objetos pendentes em T. Se todas as dependências forem removidas, um objeto de T será movido para Q.
Estamos assumindo que os sprites de objetos não espreitam pelas fendas na parte inferior, esquerda ou direita (apenas na parte superior, como árvores na imagem). Isso deve melhorar o desempenho de um grande número de objetos. Essa abordagem será novamente O(n^2)
, mas apenas no pior dos casos, que inclui objetos de tamanhos estranhos e / ou configurações estranhas de objetos. Na maioria dos casos, é O(n * logn * sqrt(n))
. Saber a altura de seus sprites pode eliminar o sqrt(n)
, porque você não precisa verificar a faixa inteira acima. Dependendo do número de objetos na tela, você pode tentar substituir a árvore quádrupla por uma matriz indicando quais slots estão ocupados (faz sentido se houver muitos objetos).
Por fim, sinta-se à vontade para inspecionar este código-fonte em busca de algumas idéias: https://github.com/axel22/sages/blob/master/src/gui/scala/name/brijest/sages/gui/Canvas.scala