In un browser, è meglio usare un enorme foglio di calcolo o molti (10000) PNG diversi?


33

Sto creando un gioco in jQuery, dove utilizzo circa 10000 tessere 32x32. Fino ad ora li ho usati tutti separatamente (nessun foglio sprite). Una mappa media utilizza circa 2000 riquadri (a volte riutilizzati PNG ma tutti i div separati) e le prestazioni vanno da stabili (Chrome) a un po 'ritardate (Firefox). Ognuno di questi div è posizionato in modo assoluto usando CSS. Non è necessario aggiornarli ad ogni tick, proprio quando viene caricata una nuova mappa.

Sarebbe meglio per le prestazioni usare i metodi dello spritesheet per i div usando il posizionamento in background CSS, come fa gameQuery?

Grazie in anticipo!


3
Dove diavolo hai bisogno di 10.000 tessere per la mappa? Ti suggerisco di non caricare / disegnare tutta la mappa sul lato utente. Mostra solo una porzione, che è visibile. Quando l'utente si sposta, carica la sezione successiva. Il modo in cui funziona ogni grafica 3D.
Deele

Una mappa media utilizza 2000 tessere diverse o solo 2000 tessere totali? Quanto sono grandi le mappe che stai creando?
Nick Larsen,

Hai considerato di utilizzare una o alcune immagini più grandi come sfondo e di eseguire il rilevamento poligonale delle collisioni per i confini?
SAHornickel,

Risposte:


50

Il mio consiglio

Troppi piccoli PNG aggiungeranno un sacco di sovraccarico di rete (a causa delle dimensioni delle richieste HTTP, ma anche dell'intestazione PNG e, probabilmente ancora più importante, dell'incapacità di comprimere in modo efficace). D'altra parte, un PNG molto grande ha gli svantaggi che richiede un po 'di tempo per caricarsi e deve rimanere permanentemente in memoria (40 megabyte per 10.000 tessere) in un blocco continuo di memoria.

Raccomando la via di mezzo: diversi PNG di dimensioni ragionevoli, ad esempio 1024 tessere di dimensioni 32 × 32 . Forse raggruppati per tema (ad esempio, un PNG con tessere foresta, uno con tessere montagna, un altro con tessere città - non conosco il tema del tuo gioco, ma hai l'idea).

Nota sull'efficienza della cache

A causa dell'efficienza dell'accesso alla memoria, non dovresti mai allargare troppo i tuoi fogli di calcolo. La fusione di tessere da un'immagine di 128 × 8192 sarà sempre più veloce della fusione di un'immagine di 8192 × 128.

Immagina di voler blitare la prima tessera in un'immagine 8192 × 128. Per semplicità, supponiamo che 1 pixel sia 1 byte. Le prime due righe di pixel sono disposte in questo modo (le celle contengono il loro numero di byte in memoria):

┌────┬────┬───┬────┬──────────┬─────┐
  0   1 │...│ 31    ....    8191 1st line of pixels: bytes 0 to 8191
├────┼────┼───┼────┼──────────┼─────┤
81928193│...│8223   ....   16383 2nd line of pixels: bytes 8192 to 16383
├────┼────┼───┼────┼──────────┼─────┤
 ..  .. │...│ ..    ....    ... 

Quindi, per blitare la prima riga del primo titolo, il motore del browser recupererà i byte 0in31 . Per i riferimenti nella seconda riga , esso recupererà byte 8192a8223 , e così via fino alla linea 32a dove byte 253952a253983 vengono recuperate.

Il numero totale di byte elaborati sarà 32 × 32. Tuttavia, l'intervallo di memoria totale è superiore a 253984 byte. Su una CPU moderna, ciò significa 32 o 33 bancarelle di cache . Al contrario, se l'immagine fosse 128 × 8192, l'intervallo di memoria sarebbe solo di 4000 byte, il che significa che non più di due blocchi di cache.

Poiché le CPU di oggi sono molto veloci, le bancarelle di cache sono molto costose e bloccano i calcoli. Quindi usare un'immagine 128 × 8192 invece di un'immagine 8192 × 128 è potenzialmente 8 volte più veloce, almeno in teoria. In pratica ciò dipenderà dall'implementazione del blitting: è possibile che lo stesso motore sottostante divida le immagini in riquadri per ridurre il problema.

Questo non è facile da spiegare correttamente e non mi aspettavo di elaborare molto. Spero abbia senso!


4
"Nota anche che, a causa dell'efficienza dell'accesso alla memoria, non dovresti mai allargare troppo i tuoi fogli di calcolo. La fusione delle tessere da un'immagine 128 × 8192 sarà sempre più veloce della fusione da un'immagine 8192 × 128." - bella curiosità, potresti approfondire per favore? :)
Grimshaw

@DevilWithin: ho provato a spiegare il problema; fammi sapere se sono abbastanza chiaro!
sam hocevar,

L'efficienza della cache è affascinante. Hai qualche numero sulla differenza che questo fa riguardo al framerate?
Gregory Avery-Weir,

Che si tratti di un problema, sembra specifico dell'implementazione, ma se API come OpenGL agiscono in questo modo sulle trame, è sicuramente importante tenerne conto, grazie :)
Grimshaw,

2
@DevilWithin: ciò che ho scritto è valido solo per una CPU: una GPU, essendo massicciamente parallela, ha impostazioni della cache molto diverse e memorizzerà le trame utilizzando il proprio formato interno, ottimizzato per l'accesso casuale. Questo è il motivo per cui in OpenGL sono consigliate trame quadrate, potenza di due, e seguirei questa regola anche per i tileset.
sam hocevar,

5

Un enorme spritesheet ti offrirà (probabilmente) migliori prestazioni, semplicemente perché una delle maggiori cause di ritardo è il round trip dalla richiesta del browser al server al browser. 10.000 chiamate HTTP impiegheranno molto, molto più tempo di 1 chiamata HTTP che restituisce un file di 10.000 volte più grande.

Potrebbero esserci altre cose che puoi usare per ridurre il ritardo, a seconda della struttura del gioco e del codice HTML che stai creando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.