Suponiendo que sus sprites ocupan conjuntos de mosaicos que son rectángulos (si ocupan conjuntos arbitrarios, entonces no puede dibujar correctamente en el caso general), el problema es que no hay una relación de orden total entre los elementos, por lo que no puede ordenar usando un tipo que resultaría en comparaciones O (nlogn).
Tenga en cuenta que para cualquiera de los dos objetos A y B, A debe dibujarse antes de B (A <- B), B debe dibujarse antes de A (B <- A) o pueden dibujarse en cualquier orden. Forman un orden parcial. Si dibuja algunos ejemplos con 3 objetos superpuestos, puede notar que aunque el primer y el tercer objeto no se superpongan, por lo que no tienen una dependencia directa, su orden de dibujo depende del segundo objeto que esté entre ellos, dependiendo de cómo Si lo coloca, obtendrá diferentes órdenes de dibujo. En pocas palabras: los tipos tradicionales no funcionan aquí.
Una solución es usar la comparación (mencionada por Dani) y comparar cada objeto entre sí para determinar sus dependencias y formar un gráfico de dependencia (que será un DAG). Luego, haga una ordenación topológica en el gráfico para determinar el orden de dibujo. Si no hay demasiados objetos, esto puede ser lo suficientemente rápido (es O(n^2)
).
Otra solución es usar un árbol cuádruple (para equilibrar - pseudo ) y almacenar los rectángulos de todos los objetos en él.
Luego, recorra todos los objetos X y use el árbol cuádruple para verificar si hay algún objeto Y en la franja sobre el objeto X, que comienza con el extremo izquierdo y termina con la esquina derecha del objeto X, para todos esos Y, Y < - X. De esta manera, aún tendrá que formar un gráfico y ordenarlo topológicamente.
Pero puedes evitarlo. Utiliza una lista de objetos Q y una tabla de objetos T. Usted itera todas las ranuras visibles de valores más pequeños a más grandes en el eje x (una fila), yendo fila por fila en el eje y. Si hay una esquina inferior de un objeto en esa ranura, realice el procedimiento anterior para determinar las dependencias. Si un objeto X depende de otro objeto Y que está parcialmente por encima de él (Y <- X), y cada uno de estos Y ya está en Q, agregue X a Q. Si hay algo de Y que no está en Q, agregue X a T y denota que Y <- X. Cada vez que agrega un objeto a Q, elimina las dependencias de los objetos pendientes en T. Si se eliminan todas las dependencias, un objeto de T se mueve a Q.
Asumimos que los sprites de los objetos no se asoman desde sus ranuras en la parte inferior, izquierda o derecha (solo en la parte superior, como los árboles en su imagen). Esto debería mejorar el rendimiento de una gran cantidad de objetos. Este enfoque volverá a serlo O(n^2)
, pero solo en el peor de los casos, que incluye objetos de tamaños extraños y / o configuraciones extrañas de objetos. En la mayoría de los casos, lo es O(n * logn * sqrt(n))
. Conocer la altura de tus sprites puede eliminar el sqrt(n)
, porque no tienes que verificar toda la franja de arriba. Dependiendo del número de objetos en la pantalla, puede intentar reemplazar el árbol cuádruple con una matriz que indique qué ranuras se toman (tiene sentido si hay muchos objetos).
Finalmente, siéntase libre de inspeccionar este código fuente para algunas ideas: https://github.com/axel22/sages/blob/master/src/gui/scala/name/brijest/sages/gui/Canvas.scala