Supponendo che i tuoi sprite occupino insiemi di tessere rettangolari (se occupano insiemi arbitrari, quindi non puoi affatto disegnare correttamente nel caso generale), il problema è che non esiste una relazione di ordine totale tra gli elementi, quindi non puoi ordinare usando un ordinamento che comporterebbe confronti O (nlogn).
Si noti che per ogni due oggetti A e B, A deve essere disegnato prima di B (A <- B), B deve essere disegnato prima di A (B <- A) oppure possono essere disegnati in qualsiasi ordine. Formano un ordine parziale. Se ti fai alcuni esempi con 3 oggetti sovrapposti, potresti notare che anche se il 1o e il 3o oggetto non possono sovrapporsi, quindi non avendo una dipendenza diretta, il loro ordine di disegno dipende dal 2o oggetto che è tra loro - a seconda di come lo metti, otterrai diversi ordini di disegno. Bottomline - i tipi tradizionali non funzionano qui.
Una soluzione consiste nell'utilizzare il confronto (menzionato da Dani) e confrontare ciascun oggetto con l'altro per determinare le loro dipendenze e formare un grafico delle dipendenze (che sarà un DAG). Quindi eseguire un ordinamento topologico sul grafico per determinare l'ordine di disegno. Se non ci sono troppi oggetti, questo potrebbe essere abbastanza veloce (è O(n^2)
).
Un'altra soluzione è quella di utilizzare un (per bilanciamento - pseudo ) albero quad e memorizzare i rettangoli di tutti gli oggetti al suo interno.
Quindi scorrere tutti gli oggetti X e utilizzare l'albero dei quadratini per verificare se ci sono oggetti Y nella striscia sopra l'oggetto X che inizia con l'estrema sinistra e termina con l'angolo più a destra dell'oggetto X - per tutti questi Y, Y < - X. In questo modo, dovrai comunque formare un grafico e ordinare topologicamente.
Ma puoi evitarlo. Si utilizza un elenco di oggetti Q e una tabella di oggetti T. Si ripetono tutti gli slot visibili da valori più piccoli a più grandi sull'asse x (una riga), procedendo riga per riga sull'asse y. Se esiste un angolo inferiore di un oggetto in quello slot, eseguire la procedura sopra per determinare le dipendenze. Se un oggetto X dipende da qualche altro oggetto Y che è parzialmente sopra di esso (Y <- X), e ogni Y simile è già in Q, aggiungi X a Q. Se c'è qualche Y che non è in Q, aggiungi X a T e denota che Y <- X. Ogni volta che aggiungi un oggetto a Q, rimuovi le dipendenze degli oggetti in sospeso in T. Se tutte le dipendenze vengono rimosse, un oggetto da T viene spostato in Q.
Partiamo dal presupposto che gli sprite degli oggetti non sbirciano dalle loro fessure in basso, a sinistra oa destra (solo in alto, come gli alberi nella tua foto). Ciò dovrebbe migliorare le prestazioni per un gran numero di oggetti. Questo approccio sarà di nuovo O(n^2)
, ma solo nel peggiore dei casi che include oggetti di strane dimensioni e / o strane configurazioni di oggetti. Nella maggior parte dei casi, lo è O(n * logn * sqrt(n))
. Conoscere l'altezza dei tuoi sprite può eliminare il sqrt(n)
, perché non devi controllare l'intera striscia sopra. A seconda del numero di oggetti sullo schermo, è possibile provare a sostituire il quad tree con un array che indica quali slot sono presi (ha senso se ci sono molti oggetti).
Infine, sentiti libero di ispezionare questo codice sorgente per alcune idee: https://github.com/axel22/sages/blob/master/src/gui/scala/name/brijest/sages/gui/Canvas.scala