2011-06-18 10 views
9

Piszę proste odgórne rpg w Pygame i stwierdziłem, że jest dość powolny ... Chociaż nie spodziewam się, aby Python lub Pygame pasowały do ​​FPS gier z kompilowanymi językami, takimi jak C/C++ lub zdarzenie Bajty Skompilowane, takie jak Java, ale wciąż obecny FPS pygame jest jak 15. Próbowałem renderować 16-bitowe bitmapy zamiast PNG lub 24 bitmapy, które lekko podniosły prędkość, a następnie w desperacji zamieniłem wszystko na czarno-białe monochromatyczne bitmapy a to spowodowało, że FPS wyniósł 35. Ale nie więcej. Teraz, zgodnie z większością książek Game Development, które przeczytałem, aby użytkownik był całkowicie zadowolony z grafiki graficznej, FPS gry 2d powinien mieć co najmniej 40, więc czy istnieje JAKIKOLWIEK sposób na zwiększenie prędkości pygame?Każdy sposób na przyspieszenie Pythona i Pygame?

+9

Masz już profilowane? –

+0

profilowana? przepraszam, nie rozumiem. plz wyjaśnij, co próbujesz powiedzieć. – ApprenticeHacker

+4

Problem najprawdopodobniej leży w kodzie (jak we wszystkich projektach). Profilowanie polega na ustaleniu, gdzie. Wpisz "profilowanie python" w polu wyszukiwania [lub przejdź tutaj] (http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script). –

Odpowiedz

13

Zastosowanie Psyco dla python2:

import psyco 
psyco.full() 

Również umożliwić doublebuffering. Na przykład:

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

Można również wyłączyć alfa jeśli nie trzeba go:

screen.set_alpha(None) 

Zamiast przerzucanie całego ekranu za każdym razem, śledzić zmienionych obszarów i aktualizuje tylko te, . Na przykład coś mniej więcej takiego (główna pętla):

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) 

Większość (wszystkich?) Funkcji rysujących zwraca rect.

Można również ustawić tylko niektóre dozwolone zdarzeń, bardziej szybkiej obsługi zdarzeń:

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

Ponadto, nie przeszkadza w tworzeniu bufor ręcznie i nie użyć flagi hwaccel, ponieważ mam doświadczenie problemy z tym w niektórych konfiguracjach.

Używając tego, osiągnąłem dość dobry FPS i gładkość dla małej platformy 2d.

+1

Dzięki, flaga DOUBLEBUF dała mi ostatni impuls, którego potrzebowałem do osiągnięcia celu 40 FPS. Spróbuję renderować seperate rects, ale skoro wszystkie sprite'y mojego RPG są najpierw podsycane przez silnik kafli na ogromną powierzchnię, a następnie ta powierzchnia jest zasłonięta na ekranie, nie zrobi to wielkiej różnicy. Dzięki! W końcu dostałem 40 FPS, które chciałem.^_^ – ApprenticeHacker

+2

"wszystkie sprite'y mojego RPG są najpierw pobudzane przez silnik kafli na olbrzymią powierzchnię, a następnie ta powierzchnia jest rozbryzgana na ekranie" Tak, to jest problem. Powinieneś tylko zabrudzić rzeczy, które trzeba zabezpieczyć - ułóż obwiednie wokół duszków i wymieszaj tylko te, które faktycznie dotykają ekranu. – wisty

1

Możesz spróbować użyć Psyco (http://psyco.sourceforge.net/introduction.html). Często robi dużą różnicę.

+0

Dzięki, ale wypróbowałem Psyco i chociaż przyspiesza ono wykonywanie obliczeń i programów, to o czym mówię, to renderowanie grafiki, niestety nie ma to wpływu na liczbę ramek renderowanych na sekundę. Może być, ponieważ pygame jest wrapperem SDL, więc może cały rendering jest wykonywany w C? Użyłem SDL w C i nawet tam nie był znany z szybkości. Ale udało się wyświetlić 60-65 klatek na sekundę. – ApprenticeHacker

2

Podczas korzystania z obrazów ważne jest, aby przekonwertować je za pomocą funkcji convert() obrazu. Przeczytałem, że convert() wyłącza alfa, która zwykle jest dość powolna. Też miałem problemy z szybkością, dopóki nie użyłem głębi kolorów 16 bitów i funkcji konwertowania dla moich obrazów. Teraz mój FPS wynosi około 150, nawet jeśli zbryzguję duży obraz na ekranie.

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

Również obracanie i skalowanie zajmuje dużo czasu. Duży, przekształcony obraz można zapisać na innym obrazie, jeśli jest niezmienny.

Pomysł polega na tym, aby raz obliczyć wyniki i wykorzystać je wielokrotnie.

2

Po pierwsze, zawsze używaj "convert()", ponieważ wyłącza alfa, co powoduje szybsze blending. Następnie aktualizuj tylko te części ekranu, które wymagają aktualizacji.

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 

Uwaga:

Podczas przenoszenia ikonki trzeba uwzględnić w wykazie rect z ostatniej pozycji.

3

Podczas ładowania obrazów, jeśli absolutnie potrzebujesz przezroczystości lub innych wartości alfa, użyj metody Surface.convert_alpha(). Używałem go do gry, którą programowałem, i to było ogromny wzrost wydajności. np: W konstruktorze załadować swoje zdjęcia przy użyciu:

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

O ile mogę powiedzieć, wszelkie transformacje zrobić z obrazem zachowuje przy wykonywaniu tej metody połączenia. Np:

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

staje się zbędna, jeśli używasz obrazu, który miał convert_alpha() zabrakło na nim.

2

Wszystkie one są świetne sugestie i działa dobrze, ale należy również pamiętać o dwóch rzeczach:

1) blittingiem powierzchnie na powierzchni jest szybszy niż rysowanie bezpośrednio. Wcześniejsze rysowanie utrwalonych obrazów na powierzchniach (poza główną pętlą gry), a następnie blaknięcie powierzchni do ekranu głównego będzie bardziej wydajne. Na przykład:

# 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) Upewnij się, że nie marnujesz zasobów, rysując rzeczy, których użytkownik nie widzi. na przykład:

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

Oto kilka ogólnych koncepcji, które pomagają utrzymać wysoką wartość FPS.

Powiązane problemy