2011-06-18 72 views
9

Escribo un rpg simple de arriba hacia abajo en Pygame, y he descubierto que es bastante lento ... Aunque no espero que python o pygame coincidan con el FPS de juegos hechos con lenguajes compilados como C/C++ o evento Los compilados como Java, pero el FPS actual de pygame es como 15. Traté de renderizar mapas de bits de 16 colores en lugar de PNG o 24 mapas de bits, lo que aumentó ligeramente la velocidad y luego, desesperado, cambié todo a mapas de bits monocromáticos en blanco y negro y eso hizo que los FPS pasaran a 35. Pero no más. Ahora, de acuerdo con la mayoría de los libros de Desarrollo de juegos que he leído, para que un usuario esté completamente satisfecho con los gráficos del juego, el FPS de un juego 2d debe ser al menos de 40, entonces ¿hay ALGUNA forma de aumentar la velocidad de pygame?¿Alguna forma de acelerar Python y Pygame?

+9

¿Olvidaste tu perfil? –

+0

perfilado aún? lo siento, no entiendo por favor explica lo que estás tratando de decir. – ApprenticeHacker

+4

El problema probablemente recaiga en su código (como en todos los proyectos). Perfilar es el acto de descubrir dónde. Escriba "perfil de python" en el cuadro de búsqueda [o vaya aquí] (http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script). –

Respuesta

13

Uso Psyco, por python2:

import psyco 
psyco.full() 

Además, permiten doublebuffering. Por ejemplo:

from pygame.locals import * 
flags = FULLSCREEN | DOUBLEBUF 
screen = pygame.display.set_mode(resolution, flags, bpp) 

También puede desactivar alfa si no lo necesita:

screen.set_alpha(None) 

En lugar de mover de un tirón toda la pantalla cada vez, mantener un registro de las áreas cambiado y sólo actualizar los . Por ejemplo, algo más o menos así (bucle principal):

events = pygame.events.get() 
for event in events: 
    # deal with events 
pygame.event.pump() 
my_sprites.do_stuff_every_loop() 
rects = my_sprites.draw() 
activerects = rects + oldrects 
activerects = filter(bool, activerects) 
pygame.display.update(activerects) 
oldrects = rects[:] 
for rect in rects: 
    screen.blit(bgimg, rect, rect) 

La mayoría (? Todos) funciones de dibujo devuelven un rect.

También puede establecer solamente algunos eventos permitidos, para más rápido manejo de eventos:

pygame.event.set_allowed([QUIT, KEYDOWN, KEYUP]) 

Además, no me molestaría con la creación de una solución tampón e no usaría la bandera hwaccel, como yo he experimentado problemas con él en algunas configuraciones.

Utilicé esto, logré FPS y suavidad razonablemente buenos para un pequeño juego de plataformas en 2d.

+1

Gracias, la bandera DOUBLEBUF me dio el impulso final que necesitaba para mi objetivo de 40 FPS. Trataré de renderizar las lecturas por separado, pero dado que todos los sprites de mi rpg son primero embestidos por el motor de baldosas sobre una superficie enorme y luego esa superficie se ve abrupta en la pantalla, no hará mucha diferencia. ¡Gracias! Finalmente obtuve los 40 FPS que quería.^_^ – ApprenticeHacker

+2

"todos los sprites de mi rpg son primero blighted por el motor de baldosas en una superficie enorme y luego esa superficie es blitted en la pantalla" Sí, eso es un problema. Solo debe ajustar las cosas que deben ser bordadas: coloque cuadros delimitadores alrededor de los sprites y solo recorte los que realmente toquen la pantalla. – wisty

1

Puede intentar usar Psyco (http://psyco.sourceforge.net/introduction.html). A menudo hace una gran diferencia.

+0

Gracias, pero lo he intentado con Psyco y aunque acelera mucho los cálculos y la ejecución de programas, de lo que estoy hablando es de la representación gráfica, desafortunadamente no hace nada con el número de frames que pygame renderiza por segundo. Tal vez sea porque pygame es un contenedor de SDL, entonces ¿quizás todo el renderizado se hace en C? He usado SDL en C e incluso allí no era conocido por su velocidad. Pero logró mostrar 60-65 cuadros por segundo. – ApprenticeHacker

2

Al usar imágenes, es importante convertirlas con la función convertir() de la imagen. He leído que convertir() deshabilita alfa, que normalmente es bastante lento. También tuve problemas de velocidad hasta que usé una profundidad de color de 16 bits y la función de conversión para mis imágenes. Ahora mis FPS son alrededor de 150, incluso si blight una imagen grande en la pantalla.

image = image.convert()#video system has to be initialed 

También las rotaciones y escalas tardan mucho tiempo en calcular. Una gran imagen transformada se puede guardar en otra imagen si es inmutable.

Así que la idea es calcular una vez y reutilizar el resultado varias veces.

2

Primero, siempre use 'convert()' porque desactiva el alfa, lo que hace que el bliting sea más rápido. Luego solo actualice las partes de la pantalla que necesitan actualizarse.

global rects 

rects = [] 

rects.append(pygame.draw.line(screen, (0, 0, 0), (20, 20), (100, 400), 1)) 

pygame.display.update(rects) # pygame will only update those rects 

Nota:

Al mover un sprite que tiene que incluir en la lista de la rect de su última posición.

3

Al cargar imágenes, si necesita absolutamente transparencia u otros valores alfa, utilice el método Surface.convert_alpha(). Lo he estado usando para un juego que he estado programando, y ha sido un gran aumento en el rendimiento. por ejemplo: En el constructor, cargar sus imágenes usando:

self.srcimage = pygame.image.load(imagepath).convert_alpha() 

Por lo que yo puedo decir, cualquier transformación que haces a la imagen conserva el rendimiento Este método llama. Por ejemplo:

self.rotatedimage = pygame.transform.rotate(self.srcimage, angle).convert_alpha() 

se vuelve redundante si está utilizando una imagen que ha tenido convert_alpha() corrieron en él.

2

Todas estas son buenas sugerencias y funcionan bien, pero también hay que tener en cuenta dos cosas:

1) Blitting superficies sobre las superficies es más rápido que dibujar directamente. Por lo tanto, pre-dibujar imágenes fijas en las superficies (fuera del bucle principal del juego), luego ajustar la superficie a la pantalla principal será más eficiente. Por ejemplo:

# pre-draw image outside of main game loop 
image_rect = get_image("filename").get_rect() 
image_surface = pygame.Surface((image_rect.width, image_rect.height)) 
image_surface.blit(get_image("filename"), image_rect) 
...... 
# inside main game loop - blit surface to surface (the main screen) 
screen.blit(image_surface, image_rect) 

2) Asegúrese de no desperdiciar recursos dibujando cosas que el usuario no puede ver. por ejemplo:

if point.x >= 0 and point.x <= SCREEN_WIDTH and point.y >= 0 and point.y <= SCREEN_HEIGHT: 
    # then draw your item 

Estos son algunos conceptos generales que me ayudan a mantener el FPS alto.

Cuestiones relacionadas