Aumentar a velocidade do blitting?

9

Estou trabalhando em um sidecroller 2D no PyGame. Para cada mapa, usamos uma textura (esse é o tamanho real da textura):

textura do mapa

Em seguida, carregamos a imagem com este código:

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

Como você pode ver, a textura é ampliada 6 vezes para criar a textura real do mapa. Em média, essa textura é de cerca de 4500x800. Essa textura deve ser unida à tela em todos os quadros , porque a tela inteira está suja (graças à rolagem lateral). Fazemos isso usando este código:

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

E isso funciona. O problema é que é muito lento: recebo 40 FPS em um PC decente, e isso sem a IA / objetos reais, enquanto pretendemos 60 FPS. Como podemos acelerar isso?


Observe que o código acima é higienizado e retirado de contexto. O código completo pode ser encontrado aqui: https://github.com/nightcracker/PyGG2

E por último mas não menos importante, embora a imagem acima possa parecer 8 bits, existem elementos no jogo que exigem mais profundidade de bits.

orlp
fonte
Divida em um tamanho sensato por textura, digamos 1024 de largura por bloco, e blit apenas os dois que são relevantes por vez.
Jari Komppa
@JariKomppa: Tentei, não tem efeito sobre a cegueira (pygame é inteligente o suficiente para citar apenas o correto que eu digo), apenas o uso de memória.
orlp 29/09
Você poderia ... não usar pygame (trollface.jpg) .... jkjk, nesse caso, acho que não é onde o seu lentidão está ocorrendo, você o testou extensivamente?
Ultifinitus
@ultifinitus: Sim, eu criei um perfil com o cProfile.
orlp
Qual é a diferença de velocidade se você a exibir na resolução real? E se você precompute a imagem maior?
Ultifinitus

Respostas:

7

Deixe-me listar algumas otimizações gerais comparadas relacionadas a Blitting pixels em uma superfície (pela minha experiência).

1) Geralmente, as imagens da paleta (imagens indexadas) quando são blitadas passam por um nível extra de redirecionamento (para obter a cor).

2) Os dados de pixels de cores reais (suponha que os dados de Alpha - say24 bits) possam ser misturados muito rapidamente, pois podemos fazer um memcpy para cada linha de digitalização da imagem (se estiver copiando uma parte da imagem) no buffer do quadro do dispositivo .Se os dados a serem blitados são uma imagem completa, podemos copiar diretamente todos os dados, o que é muito mais rápido!

3) Blitting Alpha pixel data será o mais caro, pois incluirá o cálculo de cada componente resultante e precisamos compactá-lo novamente para dados RGB. Em termos simples, mais operações para cada pixel para obter a cor final!

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.

Eu não trabalhei no pyGame antes. Mas, uma rápida olhada no código de código, me leva a supor que ele está usando as funções 'sdl' Blit sob o capô. Normalmente, o Sdl blit será muito mais rápido e otimizado, portanto, faça um dos pontos e perfil acima novamente! Boa sorte!

* Atualização: * Definir chave de cor é como adicionar uma verificação extra ao misturar cada pixel na superfície.

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

         }

Portanto, aqui, se você vir, estamos limitados a não usar o memcpy, pois precisamos verificar a validade das cores de cada pixel!

Ayyappa
fonte
Ok, como se vê, uma chamada set_colorkeyentrou na textura do mapa, dando a ele um canal alfa (caro). Um convertfixo que, e agora eu estou correndo 150 FPS estável nessa porcaria PC. Obrigado!
orlp 29/09
hey irá editar relacionadas com tecla de cor até se esqueceu de acrescentar outras informações abt-lo: D
Ayyappa
5

sprite.convert() não faz o que você pensa que faz.

sprite = sprite.convert() é o que você precisa.

Kylotan
fonte
Woops, eu tenho sprite = sprite.convert()no código real embora :)
orlp
AHA bom. :) Nesse caso, não tenho muito a oferecer, exceto considerar o uso de pyglet em vez de pygame, ou use pyOpenGL diretamente se você estiver familiarizado com o OpenGL.
Kylotan
@Kylotan: bom companheiro de captura! Eu não tenho verificado que :)
Ayyappa
ou ainda melhor:sprite = pygame.image.load("Maps/MapTesting.png").convert()
MestreLion 14/08