首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指定屏幕上的所有像素

问指定屏幕上的所有像素
EN

Stack Overflow用户
提问于 2015-08-23 04:40:12
回答 2查看 101关注 0票数 0

我正试着逐像素地改变我的屏幕。我知道我不应该这样做,因为它是没有效率的,但我只是尝试构建我自己版本的3D引擎(有趣)学习的目的。

在下面的代码中,我注意到Pygame可以非常快地改变整个屏幕(METHOD=1),像素变化的方法要慢得多。我尝试直接使用Surface.fill (METHOD=2),但速度非常慢。然后我尝试了(METHOD=3) pygame.surfarray.blit_array和blit非常快,但是我在python中的双循环非常慢。我觉得很奇怪,因为它是一个简单的双循环,用整数填充一个numpy数组,我认为它不会成为瓶颈。

编辑:通过@BlackJack建议,我使用了METHOD=4,它基本上将循环发送到Cython模块中。我遵循分期付款,如:含芘的Cython和我遵循了在tutorial.html中显示的优化技术

循环时间大大改善了!100倍更快!如果我看看我能管理多少个FPS,我就会看到:

  • 方法2: 01.89 fps
  • 方法3: 04.83 fps
  • 方法4: 444.4 fps

下面是我的工作示例(假设Cython已经正确安装和工作,这不是一件简单的事情)。不需要预编译模块,因为我使用的是pyximport

PyGameTest.py

代码语言:javascript
复制
from __future__ import division
import pygame, random, time
import numpy as np
import pyximport
pyximport.install(setup_args={'include_dirs': np.get_include()})
import FastLoops

#n = r*256^2 + g*256 + b
IRED=256*256*150
IGRN=256*150
IBLU=150
arr=[IRED,IGRN,IBLU]

BLK=0

RESX=600
RESY=600

TARGFPS=60

# initialize game engine
pygame.init()
# set screen width/height and caption
Surface = pygame.display.set_mode([RESX, RESY])
pygame.display.set_caption('My Game')
# initialize clock. used later in the loop.
clock = pygame.time.Clock()
 
METHOD=4

i0=0
t0=time.time()
nl=0
# Loop until the user clicks close button
done = False
while done == False:
    # write event handlers here
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    if METHOD==1:   
        col=arr[random.randint(0,2)]
        Surface.fill(col)
        Surface.fill(BLK,pygame.Rect(i0,i0,10,10))
    
    elif METHOD==2:
        for i in range(RESX):
            if i<i0:
                col=IBLU
            else:
                col=IGRN
            for j in range(RESY):
                Surface.fill(col,pygame.Rect(i,j,1,1))
      
    elif METHOD==3:
        myarray = np.zeros([RESX, RESY], dtype=np.int32)
        for i in range(RESX):
            if i<i0:
                col=IBLU
            else:
                col=IGRN
            for j in range(RESY):
                myarray[i,j]=col
        pygame.surfarray.blit_array(Surface,myarray)

        
    elif METHOD==4:
        myarray = FastLoops.Loop(RESX,RESY,IBLU,IRED,i0)
        pygame.surfarray.blit_array(Surface,myarray)

    nl+=1     
    i0+=RESX/TARGFPS
    if i0>=RESX:
        t1=time.time()
        fps=round(nl/(t1-t0),2)
        print 'METHOD '+str(METHOD)+':'
        print '    Time = ' + str(round(t1-t0,2)) + 's for ' + str(nl) + ' frames'
        print '    FPS  = '+str(fps)
        i0=0
        t0=time.time()
        nl=0
        
    # display what’s drawn. this might change.
    pygame.display.update()
    # run at 20 fps
    clock.tick(TARGFPS)
 
# close the window and quit
pygame.quit()

FastLoops.pyx

代码语言:javascript
复制
from __future__ import division
import numpy as np
cimport numpy as np
cimport cython

DTYPE = np.int32
ctypedef np.int32_t DTYPE_t

@cython.boundscheck(False) # turn of bounds-checking for entire function
def Loop(int RESX, int RESY, long IBLU, long IGRN, int i0):
    cdef int i, j
    cdef np.ndarray[DTYPE_t, ndim=2] myarray = np.zeros([RESX, RESY], dtype=DTYPE)
    for i in range(RESX):
        if i<i0:
            col=IBLU
        else:
            col=IGRN
        for j in range(RESY):
            myarray[i,j]=col
            
            
    return myarray
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-23 12:42:42

可以预期,纯python循环比调用用C实现的函数或方法要慢得多,甚至可能会被图形硬件加速。

如果可能的话,尝试使用Numpy方法,因为这些方法是用C实现的,或者使用用C或Fortran实现的库。

如果您确实需要单像素级访问,您可以尝试用Cython编写慢部分,并将代码编译到Python的扩展模块中。

票数 1
EN

Stack Overflow用户

发布于 2015-08-27 12:47:07

免责声明:我是Pythran项目的开发者之一。

如果Cython还不够,您可以尝试一下毕斯兰。在特定的测试用例中,以下代码:

代码语言:javascript
复制
import numpy as np

#pythran export Loop(int, int, int, int, int)
def Loop(RESX, RESY, IBLU, IGRN, i0):
    myarray = np.empty((RESX, RESY), dtype=np.int32)
    for i in range(RESX):
        if i < i0:
            col = IBLU
        else:
            col = IGRN
        myarray[i, :] = IBLU if i < i0 else IGRN

    return myarray

给了我一个关于Cython的x2加速。

使用numpy样式(并且可以改进)

代码语言:javascript
复制
import numpy as np

#pythran export Loop(int, int, int, int, int)
def Loop(RESX, RESY, IBLU, IGRN, i0):
    myarray = np.empty((RESX, RESY), dtype=np.int32)
    for i in range(RESX):
        myarray[:, :] = IBLU if i < i0 else IGRN

    return myarray

给了我一次x3加速。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32163215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档