Aumentar la velocidad de disparo?

9

Estoy trabajando en un desplazamiento lateral 2D en PyGame. Para cada mapa usamos una textura (este es el tamaño real de la textura):

textura del mapa

Luego cargamos la imagen con 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 puede ver, la textura se explota 6 veces para crear la textura del mapa real. En promedio, esta textura es de aproximadamente 4500x800. Esta textura tiene que borrarse a la pantalla cada fotograma , porque toda la pantalla está sucia (gracias al desplazamiento lateral). Hacemos eso usando este código:

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

Y funciona. El problema es que es bastante lento: obtengo unos escasos 40 FPS en una PC poco decente, y eso sin que ocurra ninguna de las IA / objetos reales, mientras apuntamos a 60 FPS. ¿Cómo podemos acelerar esto?


Tenga en cuenta que el código anterior se desinfecta y se saca de contexto. El código completo se puede encontrar aquí: https://github.com/nightcracker/PyGG2

Y por último, pero no menos importante, aunque la imagen de arriba puede parecer de 8 bits, hay elementos en el juego que requieren más profundidad de bits.

orlp
fuente
Divida a un tamaño sensato por textura, digamos 1024 de ancho por bloque, y solo borre los dos que son relevantes a la vez.
Jari Komppa
@JariKomppa: Probé, no tiene ningún efecto en el bliting (pygame es lo suficientemente inteligente como para bloquear solo el rectángulo que le digo), solo el uso de la memoria.
orlp
No podrías ... no usar pygame (trollface.jpg) .... jkjk, en este caso supongo que no es donde está ocurriendo tu desaceleración, ¿lo has probado exhaustivamente?
ultifinitus
@ultifinitus: Sí, lo perfilé con cProfile.
orlp
¿Cuál es la diferencia de velocidad si la muestra con su resolución real? ¿Qué pasa si precalcula la imagen más grande?
ultifinitus

Respuestas:

7

Permítanme enumerar algunas optimizaciones comparadas generales relacionadas con Blitting píxeles a una superficie (desde mi experiencia).

1) Por lo general, las imágenes de paleta (imágenes indexadas) cuando se borran tendrán un nivel adicional de redireccionamiento (para obtener el color), por lo que serán lentas cuando se borren en comparación con las imágenes en color real.

2) Los datos de píxeles de color verdadero (suponga que sin Alpha - digamos datos de 24 bits) pueden borrarse muy rápido, ya que podemos hacer una memoria para cada línea de escaneo de la imagen (si estamos copiando una parte de la imagen) en el búfer del marco del dispositivo Si los datos que se borran son una imagen completa, entonces podemos memorizar directamente todos los datos, ¡lo cual es mucho más rápido!

3) Los datos de píxeles Alpha de Blitting serán los más costosos, ya que incluirán el cálculo de cada componente resultante y necesitamos empacarlos nuevamente en datos RGB. En términos simples, ¡más operaciones para cada píxel para obtener el color 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.

No he trabajado en pyGame antes, pero, un vistazo rápido al código fuente, me lleva a suponer que está usando funciones 'sdl' Blit debajo del capó. Por lo general, Sdl blit será mucho más rápido y optimizado, así que no hagas caso de los puntos y el perfil anteriores una vez más. ¡Buena suerte!

* Actualización: * La configuración de la clave de color es como agregar un cheque adicional al borrar cada píxel a la superficie. Algo así:

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

         }

Entonces, aquí, si ve, ¡estamos limitados a no usar memcpy, ya que necesitamos verificar la validez de color de cada píxel!

Ayyappa
fuente
Ok, ya que resulta una llamada para set_colorkeydeslizarse en la textura del mapa, dándole un canal alfa (costoso). A convertsolucioné eso, y ahora estoy ejecutando 150 FPS estables en esta PC de mierda. ¡Gracias!
orlp
hey editará relacionado con la clave de color, incluso se olvidó de agregar algo de información: D
Ayyappa
5

sprite.convert() no hace lo que crees que hace.

sprite = sprite.convert() es lo que necesitas

Kylotan
fuente
Woops, yo tengo sprite = sprite.convert()en el código real, aunque :)
orlp
Si, bien. :) En ese caso, no tengo mucho que ofrecer, excepto considerar usar pyglet en lugar de pygame, o usar pyOpenGL directamente si te sientes cómodo con OpenGL.
Kylotan
@Kylotan: ¡buen compañero! no lo he comprobado :)
Ayyappa
o, mejor aún:sprite = pygame.image.load("Maps/MapTesting.png").convert()
MestreLion