2011-06-18 34 views
9

我在Pygame上寫了一個簡單的自頂向下RPG,我發現它很慢....雖然我並不期望python或pygame匹配用C/C++或事件編譯語言編寫的遊戲的FPS字節編譯的像Java一樣,但是目前的pygame FPS仍然是15.我嘗試渲染16色位圖而不是PNG或24位圖,這會稍微提高速度,然後在絕望中我將所有東西都切換成黑白單色位圖這使得FPS達到了35.但是沒有更多。現在根據我讀過的大多數遊戲開發書籍,對於用戶對遊戲圖形完全滿意,2D遊戲的FPS至少應該是40,那麼是否有任何提高pygame速度的方法?任何加快Python和Pygame的方法?

+9

你有沒有簡介? –

+0

配置尚未?對不起,我不明白。 PLZ解釋你想說的話。 – ApprenticeHacker

+4

問題很可能出在您的代碼中(如在所有項目中)。分析是找出在哪裏的行爲。在搜索框中鍵入「python profiling」[或轉到此處](http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script)。 –

回答

13

使用Psyco是,對於python2:

import psyco 
psyco.full() 

而且,使doublebuffering。例如:

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

你也可以關閉阿爾法,如果你不需要它:

screen.set_alpha(None) 

而是每一次翻轉整個屏幕,保持已改變區域的跟蹤和只更新那些。例如,一些大致是這樣的(主循環):

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) 

大多數(?全部)繪圖函數返回一個矩形。

也只能設置一些允許事件,更快捷事件處理:

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

而且,我不會手動創建一個緩衝的麻煩和不使用hwaccel的標誌,因爲我已經經歷在某些設置上存在問題。

使用這個,我已經達到了相當好的FPS和光滑度,適用於小型2D平臺。

+1

謝謝,DOUBLEBUF標誌爲我提供了40個FPS球門所需的最終提升。我會嘗試渲染單獨的反射,但是因爲我的RPG的所有精靈都先由瓦片引擎傳播到一個巨大的表面上,然後這個表面在屏幕上傳播,它不會產生很大的不同。謝謝!我終於得到了我想要的40 FPS。^_^ – ApprenticeHacker

+2

「我的RPG的所有精靈首先由瓦片引擎傳送到一個巨大的表面上,然後該表面在屏幕上傳送」 是的,這是一個問題。你只應該去掉那些需要點點滴滴的東西 - 將邊界框放在精靈周圍,並且只會觸碰真正觸摸屏幕的東西。 – wisty

1

你可以嘗試使用Psyco(http://psyco.sourceforge.net/introduction.html)。它通常會造成相當大的差異。

+0

謝謝,但我已經嘗試過Psyco,雖然它加快了計算和程序執行的速度,但我所說的是圖形渲染,不幸的是它對每秒pygame渲染的幀數沒有任何影響。也許是因爲它是因爲pygame是SDL的封裝,所以也許所有的渲染都是用C完成的?我在C中使用了SDL,甚至在那裏它的速度並不出名。但它確實設法顯示每秒60-65幀。 – ApprenticeHacker

2

使用圖像時,使用圖像的convert()函數進行轉換非常重要。 我讀過convert()禁用通常很慢的alpha。 我也有速度問題,直到我用我的圖像顏色深度爲16位和轉換函數。現在我的FPS在150左右,即使我在屏幕上放大圖片。

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

此外,旋轉和縮放需要花費大量的時間來計算。如果不可變,一張大的轉換圖像可以保存在另一張圖像中。

所以這個想法是計算一次並重復使用結果多次。

2

首先,總是使用'​​convert()',因爲它會禁用使blint更快的alpha。 然後只更新需要更新的屏幕部分。

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 

注:

當移動必須在列表中包括一個從最後一個位置RECT一個精靈。

3

加載圖像時,如果您絕對需要透明度或其他alpha值,請使用Surface.convert_alpha()方法。我一直在使用它來進行我一直在編程的遊戲,並且它的性能有了巨大的提升。 E.G:在你的構造,使用加載圖片:

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

據我所知,你的圖像任何轉換保留了性能調用此方法。 E.G:

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

,如果您使用的是已convert_alpha()運行在其上的圖像變得多餘。

2

所有這些都是很好的建議,工作好,但你也應該記住兩兩件事:

1)阻擊器表面到表面上是直接繪製得更快。因此,將固定圖像預先繪製到表面上(主遊戲循環外部),然後將表面塗抹到主屏幕上將會更加高效。例如:

# 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)確保您沒有通過繪製用戶看不到的東西來浪費資源。例如:

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

這些是幫助我保持FPS高的一些通用概念。