Aumentare la velocità di blitting?


9

Sto lavorando su un sidescroller 2D in PyGame. Per ogni mappa utilizziamo una trama (questa è la dimensione effettiva della trama):

trama della mappa

Quindi carichiamo l'immagine con questo codice:

sprite = pygame.image.load("Maps/MapTesting.png")
sprite.convert()
sprite = pygame.transform.scale(sprite,
              (sprite.get_width()*6, sprite.get_height()*6))

Come puoi vedere, la trama viene fatta saltare in aria 6 volte per creare la trama reale della mappa. In media questa trama è di circa 4500x800. Questa trama deve essere distribuita sullo schermo ad ogni fotogramma , perché l'intero schermo è sporco (grazie allo scorrimento laterale). Lo facciamo usando questo codice:

screen.blit(sprite, (0, 0),
(cameraposx, cameraposy, windowheight, windowwidth))

E funziona Il problema è che è piuttosto lento: ottengo un misero 40 FPS su un PC decente, e questo è senza alcun AI / oggetti reali in corso, mentre puntiamo a 60 FPS. Come possiamo accelerare questo?


Si noti che il codice sopra è disinfettato e rimosso dal contesto. Il codice completo è disponibile qui: https://github.com/nightcracker/PyGG2

E, ultimo ma non meno importante, mentre l'immagine sopra potrebbe sembrare a 8 bit, ci sono elementi nel gioco che richiedono più profondità di bit.


Dividi in una dimensione sana per trama, ad esempio 1024 di larghezza per blocco e mescola solo i due che sono rilevanti alla volta.
Jari Komppa,

@JariKomppa: l'ho provato, non ha alcun effetto sul blitting (pygame è abbastanza intelligente da blitare solo il retto a cui glielo dico), solo l'uso della memoria.
orlp,

Non potevi ... non usare pygame (trollface.jpg) .... jkjk, in questo caso suppongo che non si verifichi il tuo rallentamento, l'hai provato ampiamente?
ultifinito

@ultifinitus: Sì, l'ho profilato con cProfile.
orlp,

Qual è la differenza di velocità se la visualizzi alla sua risoluzione effettiva? Che cosa succede se precomponi l'immagine più grande?
ultifinito

Risposte:


7

Vorrei elencare alcune ottimizzazioni comparate generali relative a Blitting pixel su una superficie (dalla mia esperienza).

1) Di solito le immagini della tavolozza (immagini indicizzate) quando vengono sbattute, subiranno un ulteriore livello di reindirizzamento (per ottenere il colore), quindi saranno lente durante il blitting rispetto alle immagini a colori reali.

2) I dati con pixel a colori reali (supponiamo Senza Alpha - diciamo dati a 24 bit) possono essere cancellati molto velocemente poiché possiamo fare un memcpy per ogni linea di scansione dell'immagine (se stiamo copiando una parte dell'immagine) sul buffer del frame del dispositivo Se i dati da benedire sono un'immagine completa, allora possiamo memorizzare direttamente tutti i dati che è molto più veloce!

3) Il blitting dei dati pixel Alpha sarà il più costoso in quanto includerà il calcolo di ogni componente risultante e dovremo impacchettarlo nuovamente in dati RGB. In termini semplici più operazioni per ogni pixel per ottenere il colore finale!

Finalrgb = Alpha*(Srgb) + (1-Alpha)*Drgb (this is for normal blend equation)
    where Srgb is source-rgb (we need to apply for each of the component for final color)
       Drgb is the color that will be there in the destination buffer.

Non ho mai lavorato su pyGame prima, ma, una rapida occhiata al codice su di esso, mi porta ad assumere che sta usando le funzioni Blit 'sdl' sotto il cofano. Di solito Sdl Blit sarà molto più veloce e ottimizzato, quindi fai ancora una volta i punti e il profilo sopra! In bocca al lupo!

* Aggiornamento: * L'impostazione del tasto colorato è come l'aggiunta di un ulteriore controllo quando si esegue il blitting di ciascun pixel sulla superficie. Alcune cose come questa -

       for(eachPixelColor in allPixels)
         {
            if(eachPixelColor is NOT colorKeyColor)
            {
              copy color to the frame buffer!
            }

         }

Quindi, qui se vedi, siamo limitati a non usare memcpy in quanto dobbiamo controllare la validità del colore di ogni pixel!


Ok, quando si scopre che è arrivata una chiamata set_colorkeysulla trama della mappa, dandogli un (costoso) canale alfa. Un convertproblema risolto, e ora sto eseguendo 150 FPS stabili su questo PC schifoso. Grazie!
orlp,

hey modificherà in relazione al tasto colorato anche dimenticato di aggiungere alcune informazioni su di esso: D
Ayyappa

5

sprite.convert() non fa quello che pensi che faccia.

sprite = sprite.convert() è quello che ti serve.


Accidenti, ho sprite = sprite.convert()nel vero codice però :)
orlp

Aha bene. :) In tal caso, non ho molto da offrirti se non considerare l'utilizzo di pyglet invece di pygame, oppure utilizzare direttamente pyOpenGL se ti senti a tuo agio con OpenGL.
Kylotan,

@Kylotan: buon amico! non l'ho controllato :)
Ayyappa,

o, ancora meglio:sprite = pygame.image.load("Maps/MapTesting.png").convert()
MestreLion,
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.