2013-11-05 14 views
7

Đây là mã. 5000 nảy hình vuông màu đỏ quay. (16x16 png) Trên phiên bản pygame tôi nhận được 30 fps nhưng 10 fps với pyglet. Isnt OpenGl được cho là nhanh hơn cho loại điều này?Tại sao pyglet quá chậm so với pygame?

phiên bản pygame:

import pygame, sys, random 
from pygame.locals import * 
import cProfile 

# Set FPS 
FPS = 60.0 
clock = pygame.time.Clock() 

# Set window 
WINDOWWIDTH= 800 
WINDOWHEIGHT = 600 

pygame.init() 
screen = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT)) 

screen.fill((0,0,0)) 
background = screen.copy().convert() 
image = pygame.image.load("square.png").convert() 

class Square(object): 
    def __init__(self,x,y): 
     self.x = x 
     self.y = y 
     self.v_x = random.randint(1,100) 
     self.v_y = random.randint(1,100) 
     self.v_r = random.randint(-100,100) 
     self.rotation = 0 

    def __rep__(self): 
     return "Square %d,%d"%(self.x,self.y) 

    def update(self,dt): 
     if self.x > WINDOWWIDTH: 
      self.v_x *= -1 
     elif self.x < 0: 
      self.v_x *= -1 
     if self.y > WINDOWHEIGHT: 
      self.v_y *= -1 
     elif self.y < 0: 
      self.v_y *= -1 

     self.x += self.v_x * dt 
     self.y += self.v_y * dt 
     self.rotation += self.v_r * dt 

    def draw(self): 
     screen.blit(pygame.transform.rotate(image,self.rotation),(self.x,self.y)) 


sqrs = [] 
for _ in range(5000): 
    sqrs.append(Square(random.randint(0,WINDOWWIDTH-1),random.randint(0,WINDOWHEIGHT-1))) 


def main_loop(): 
    tick = 0.0 
    elapsed = 0.0 

    while elapsed < 10.0: 
     dt = tick/1000.0 
     # Events 
     for event in pygame.event.get(): 
      if event.type == QUIT: 
       pygame.quit() 
       sys.exit() 

     # Logic 
     for s in sqrs: 
      s.update(dt) 

     # Drawing 
     screen.blit(background,(0,0)) 
     for s in sqrs: 
      s.draw() 

     pygame.display.update() 
     pygame.display.set_caption('test program FPS: %s'%(clock.get_fps())) 
     tick = clock.tick(FPS) 
     elapsed += tick/1000.0 
    pygame.quit() 

cProfile.run("main_loop()") 
i = input("...") 

pyglet phiên bản:

import cProfile 
import pyglet, random 
# Disable error checking for increased performance 
pyglet.options['debug_gl'] = False 

from pyglet import clock 

clock.set_fps_limit(60) 

WINDOWWIDTH = 800 
WINDOWHEIGHT = 600 
FPS = 60.0 

batch = pyglet.graphics.Batch() 
window = pyglet.window.Window(WINDOWWIDTH,WINDOWHEIGHT) 
fps_display = pyglet.clock.ClockDisplay() 

image = pyglet.resource.image("square.png") 

class Square(pyglet.sprite.Sprite): 
    def __init__(self,x,y): 
     pyglet.sprite.Sprite.__init__(self,img = image,batch=batch) 
     self.x = x 
     self.y = y 
     self.v_x = random.randint(1,100) 
     self.v_y = random.randint(1,100) 
     self.v_r = random.randint(-100,100) 

    def update(self,dt): 
     if self.x > WINDOWWIDTH: 
      self.v_x *= -1 
     elif self.x < 0: 
      self.v_x *= -1 
     if self.y > WINDOWHEIGHT: 
      self.v_y *= -1 
     elif self.y < 0: 
      self.v_y *= -1 

     self.x += self.v_x * dt 
     self.y += self.v_y * dt 
     self.rotation += self.v_r * dt 

sqrs = [] 
for _ in range(5000): 
    sqrs.append(Square(random.randint(0,WINDOWWIDTH-1),random.randint(0,WINDOWHEIGHT-1))) 

elapsed = 0.0 

def update(dt): 
    global elapsed 
    elapsed += dt 
    if elapsed >= 10.0: 
     clock.unschedule(update) 
     window.close() 
    else: 
     for s in sqrs: 
      s.update(dt) 

@window.event 
def on_draw(): 
    window.clear() 
    batch.draw() 
    fps_display.draw() 


clock.schedule_interval(update, 1.0/FPS) 

if __name__ == '__main__': 
    cProfile.run("pyglet.app.run()") 
    c = input("...") 

cProfile kết quả cho pygame:

  5341607 function calls in 9.429 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 9.429 9.429 <string>:1(<module>) 
    1335000 2.259 0.000 2.259 0.000 pygame-test.py:32(update) 
    1335000 1.323 0.000 5.969 0.000 pygame-test.py:46(draw) 
     1 0.772 0.772 9.429 9.429 pygame-test.py:55(main_loop) 
     1 0.000 0.000 9.429 9.429 {built-in method exec} 
     267 0.020 0.000 0.020 0.000 {built-in method get} 
     1 0.237 0.237 0.237 0.237 {built-in method quit} 
    1335000 3.479 0.000 3.479 0.000 {built-in method rotate} 
     267 0.013 0.000 0.013 0.000 {built-in method set_caption} 
     267 0.067 0.000 0.067 0.000 {built-in method update} 
    1335267 1.257 0.000 1.257 0.000 {method 'blit' of 'pygame.Surface' objects} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     267 0.000 0.000 0.000 0.000 {method 'get_fps' of 'Clock' objects} 
     267 0.001 0.000 0.001 0.000 {method 'tick' of 'Clock' objects} 

Pyglet cProfile đầu ra: - Rất lâu, đây là đầu ra một phần, đầy đủ phiên bản here.

  9982775 function calls (9982587 primitive calls) in 10.066 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     123 0.000 0.000 0.000 0.000 <frozen importlib._bootstrap>:1596(_handle_fromlist) 
     1 0.000 0.000 10.067 10.067 <string>:1(<module>) 
     11 0.000 0.000 0.000 0.000 __init__.py:1055(_ensure_string_data) 
     11 0.000 0.000 0.000 0.000 __init__.py:1061(_get_gl_format_and_type) 
     58 0.000 0.000 0.000 0.000 __init__.py:1140(clear) 
     75 0.000 0.000 0.012 0.000 __init__.py:1148(dispatch_event) 
     1 0.000 0.000 10.067 10.067 __init__.py:115(run) 
    ... 
     1 0.000 0.000 0.000 0.000 lib.py:124(decorate_function) 
    1108 0.005 0.000 0.005 0.000 lib_wgl.py:80(__call__) 
    285000 1.409 0.000 9.872 0.000 pyglet-test.py:29(update) 
     58 0.105 0.002 9.982 0.172 pyglet-test.py:49(update) 
    ... 
    855000 5.436 0.000 7.551 0.000 sprite.py:378(_update_position) 
    285000 0.172 0.000 2.718 0.000 sprite.py:441(_set_x) 
    851800 0.177 0.000 0.177 0.000 sprite.py:445(<lambda>) 
    285000 0.174 0.000 2.670 0.000 sprite.py:451(_set_y) 
    851115 0.155 0.000 0.155 0.000 sprite.py:455(<lambda>) 
    285000 0.182 0.000 2.692 0.000 sprite.py:461(_set_rotation) 
    285000 0.051 0.000 0.051 0.000 sprite.py:465(<lambda>) 
    ... 
    4299 0.007 0.000 0.025 0.000 vertexattribute.py:308(get_region) 
     1 0.000 0.000 0.000 0.000 vertexattribute.py:380(__init__) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:384(enable) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:387(set_pointer) 
     1 0.000 0.000 0.000 0.000 vertexattribute.py:461(__init__) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:466(enable) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:469(set_pointer) 
     1 0.000 0.000 0.000 0.000 vertexattribute.py:501(__init__) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:508(enable) 
     116 0.000 0.000 0.000 0.000 vertexattribute.py:511(set_pointer) 
     3 0.000 0.000 0.000 0.000 vertexbuffer.py:293(__init__) 
     348 0.000 0.000 0.001 0.000 vertexbuffer.py:311(bind) 
     348 0.000 0.000 0.001 0.000 vertexbuffer.py:314(unbind) 
     3 0.000 0.000 0.000 0.000 vertexbuffer.py:381(__init__) 
     348 0.001 0.000 0.004 0.000 vertexbuffer.py:388(bind) 
    4299 0.006 0.000 0.016 0.000 vertexbuffer.py:420(get_region) 
     3 0.000 0.000 0.000 0.000 vertexbuffer.py:424(resize) 
    4299 0.002 0.000 0.002 0.000 vertexbuffer.py:460(__init__) 
    855232 0.735 0.000 1.053 0.000 vertexbuffer.py:466(invalidate) 
    ... 
    855058 0.687 0.000 1.762 0.000 vertexdomain.py:581(_get_vertices) 
    ... 
    4300 0.002 0.000 0.002 0.000 {built-in method POINTER} 
    ... 
    841451 0.162 0.000 0.162 0.000 {built-in method cos} 
    ... 
2417/2415 0.000 0.000 0.000 0.000 {built-in method len} 
    855489 0.142 0.000 0.142 0.000 {built-in method max} 
    855469 0.176 0.000 0.176 0.000 {built-in method min} 
    465/407 0.000 0.000 0.000 0.000 {built-in method next} 
    ... 
    841451 0.072 0.000 0.072 0.000 {built-in method radians} 
     62 0.000 0.000 0.000 0.000 {built-in method setattr} 
    841451 0.120 0.000 0.120 0.000 {built-in method sin} 
    ... 
+0

Đầu vào (...) 'trên pyglet là gì? – ninMonkey

+0

Đầu vào() trong python chuẩn. 'foo = input ('Vui lòng nhập một giá trị:')' –

Trả lời

2

Nút cổ chai ở chế độ xoay vòng pyglet. Nếu bạn nhận xét dòng 'self.rotation' trong phương thức Square update(), khung hình/giây của bạn sẽ gần gấp đôi.

2

Hình ảnh Pyglet (và sprites) có thể được xoay quanh một neo tùy ý. Nếu bạn nhìn vào pyglet/sprite.py, bạn sẽ thấy rằng điều này được thực hiện bằng cách sử dụng mô-đun toán học Python, đó là lý do tại sao nó khá chậm. Dường như có chỗ để tối ưu hóa ở đây, bằng cách quay các sprites bằng cách sử dụng OpenGL glRotate hoặc thậm chí là một shader đỉnh.

+2

Vâng đây cũng là kết luận của tôi. Tôi thấy tiêu chuẩn pyglet/sprite rendering cách quá unoptimized cho bất kỳ sử dụng thực tế. Tôi đã có thể nhận được sự gia tăng 100% trong FPS bằng cách giảm bớt các cuộc gọi đến sprite._update_position. Bạn thấy đấy, nó được gọi là mọi thời điểm một x hoặc y hoặc xoay mới được thiết lập; nó thực tế hơn nhiều để gọi nó một lần ngay trước phương thức draw(). –

Các vấn đề liên quan