Meningkatkan kecepatan blitting?

9

Saya sedang mengerjakan sidescroller 2d di PyGame. Untuk setiap peta kami menggunakan satu tekstur (ini adalah ukuran sebenarnya dari tekstur):

tekstur peta

Lalu kami memuat gambar dengan kode ini:

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

Seperti yang Anda lihat, teksturnya akan meledak 6 kali untuk membuat tekstur peta yang sebenarnya. Rata-rata tekstur ini sekitar 4500x800. Tekstur ini harus dicampurkan ke layar setiap frame , karena seluruh layar kotor (berkat gulir samping). Kami melakukannya dengan menggunakan kode ini:

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

Dan itu berhasil. Masalahnya adalah itu sangat lambat: Saya mendapatkan 40 FPS yang sedikit pada PC yang layak, dan itu tanpa AI / objek aktual yang sedang terjadi, sementara kami mengincar 60 FPS. Bagaimana kita bisa mempercepat ini?


Perhatikan bahwa kode di atas dibersihkan dan dikeluarkan dari konteks. Kode lengkap dapat ditemukan di sini: https://github.com/nightcracker/PyGG2

Dan last but not least, sementara gambar di atas mungkin terlihat seperti 8-bit, ada elemen dalam game yang membutuhkan kedalaman bit lebih.

orlp
sumber
Membagi menjadi ukuran waras per tekstur, katakanlah 1024 lebar per blok, dan hanya blit dua yang relevan pada suatu waktu.
Jari Komppa
@JariKomppa: Mencobanya, tidak berpengaruh pada blitting (pygame cukup pintar untuk hanya mengitari rect yang saya kirim), hanya penggunaan memori.
orlp
Anda tidak bisa ... tidak menggunakan pygame (trollface.jpg) .... jkjk, dalam hal ini saya menduga itu bukan tempat pelambatan Anda terjadi, sudahkah Anda mengujinya secara luas?
ultifinitus
@ultifinitus: Ya, saya membuat profil dengan cProfile.
orlp
Apa perbedaan kecepatan jika Anda menampilkannya pada resolusi sebenarnya? Bagaimana jika Anda mengkompilasi gambar yang lebih besar?
ultifinitus

Jawaban:

7

Biarkan saya daftar beberapa optimasi umum dibandingkan terkait dengan Blitting piksel ke permukaan (dari pengalaman saya).

1) Biasanya gambar palet (gambar yang diindeks) saat blitted, akan menjalani satu tingkat pengalihan tambahan (untuk mendapatkan warna).

2) Data piksel warna yang sebenarnya (anggap Tanpa Alpha - say24 bit data) dapat dicairkan dengan sangat cepat karena kita dapat melakukan memcpy untuk setiap garis pemindaian gambar (jika kita menyalin bagian gambar) ke buffer bingkai perangkat Jika data yang akan dicap adalah gambar penuh, maka kita bisa langsung memcpy seluruh data yang jauh lebih cepat!

3) Blitting data pixel Alpha akan menjadi yang paling mahal karena akan termasuk menghitung setiap komponen yang dihasilkan dan kita perlu mengemasnya lagi ke data RGB. Secara sederhana, lebih banyak operasi untuk setiap piksel untuk mendapatkan warna akhir!

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.

Saya belum pernah menggunakan pyGame sebelumnya. Tapi, sekilas tentang kode sumbernya, buat saya berasumsi bahwa ia menggunakan fungsi 'sdl' Blit di bawah tenda. Biasanya Sdl blit akan sangat cepat dan dioptimalkan, jadi buat saja bukan poin dan profil di atas sekali lagi! Semoga berhasil!

* Pembaruan: * Pengaturan tombol warna seperti menambahkan satu pemeriksaan tambahan ketika menggigit setiap piksel ke permukaan. Beberapa hal seperti ini -

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

         }

Jadi, di sini jika Anda lihat, kami dibatasi untuk tidak menggunakan memcpy karena kami perlu memeriksa validitas warna setiap piksel!

Ayyappa
sumber
Ok, ternyata panggilan untuk set_colorkeymemasukkan tekstur peta, memberikan saluran alpha (mahal). Yang convertdiperbaiki itu, dan sekarang saya menjalankan 150 FPS stabil pada PC omong kosong ini. Terima kasih!
orlp
hei akan mengedit terkait dengan tombol warna bahkan lupa untuk menambahkan beberapa info tentang itu: D
Ayyappa
5

sprite.convert() tidak melakukan apa yang Anda pikirkan.

sprite = sprite.convert() adalah apa yang kamu butuhkan.

Kylotan
sumber
Woops, saya punya sprite = sprite.convert()kode sebenarnya :)
orlp
Aha bagus :) Dalam hal ini, saya tidak punya banyak hal untuk ditawarkan kepada Anda kecuali untuk mempertimbangkan menggunakan pyglet daripada pygame, atau menggunakan pyOpenGL secara langsung jika Anda merasa nyaman dengan OpenGL.
Kylotan
@Kylotan: good catch mate! saya belum memeriksanya :)
Ayyappa
atau, bahkan lebih baik:sprite = pygame.image.load("Maps/MapTesting.png").convert()
MestreLion