如何使对象在pygame中移动,而不使渲染变慢?

2024-10-03 02:42:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在设计一个应用程序,使用pygame,其中我有许多圆圈通过线连接起来,数字文本写在其中。这些圆圈是绿色、蓝色和红色的,而其他的东西是黑色的。背景是白色的。(把它想象成一个网络图)

我的目标:我正在尝试运行一个动画,在该动画中,用户选择两个圆(我们称它们为节点),我找出发送方节点(绿色)到接收方节点(红色)之间的最短路径。因此,在这个动画中,我在连接两个相邻节点(可能是中间节点)的线(或边)顶部制作另一个移动圆

for e.g, the circle moves from node 2 to node 11 here

到目前为止一切都很好,以下是我正在做的代码:

def runPathAnimation(path, colortype):
    for i in range(len(path)-1):
        #Calculation of the center of the nodes
        x1, y1 = (gmd[path[i]].getNodePosition())[0], (gmd[path[i]].getNodePosition())[1]
        x2, y2 = (gmd[path[i+1]].getNodePosition())[0], (gmd[path[i+1]].getNodePosition())[1]
        #Get the slope
        m = (y1-y2)/(x1-x2) if x1 != x2 else 'undefined'
        if str(m) != 'undefined':
            c = y2-(m*x2)
            if m > 0.5 or (m <= -1 and m >= -1.5):
                for y in range(min(y1,y2),max(y1,y2)):
                    #using the equation of the line
                    x = int((y-c)/m)
                    #redrawEverything(path)                                     #OPTION 1
                    #TRY REDRAW LINE                                            #TODO
                    pyg.draw.rect(screen, (255, 255, 255), (x-10,y-10,20,20))   #OPTION 2
                    pyg.draw.circle(screen, colortype, (x,y), 10)               #Moving circle
                    pyg.display.update()                                        #Update Display
                    #NEED: Redraw!
            #The logic repeats....
            else:
                for x in range(min(x1,x2),max(x1,x2)):
                    y = int(m*x+c)
                    #redrawEverything(path)
                    #TRY REDRAW LINE
                    pyg.draw.rect(screen, (255, 255, 255), (x-10,y-10,20,20))
                    pyg.draw.circle(screen, colortype, (x,y), 10)
                    pyg.display.update()
                    #NEED: Redraw!
        else:
            cy = range(min(y1,y2),max(y1,y2))
            if y1 > y2:
                cy = reversed(cy)
            for y in cy:
                #redrawEverything(path)
                #TRY REDRAW LINE
                pyg.draw.rect(screen, (255, 255, 255), (x1-10,y-10,20,20))
                pyg.draw.circle(screen, colortype, (x1,y), 10)
                pyg.display.update()
                #NEED: Redraw!

我的问题:我简单地用另一个位置更新一个圆的方法存在很大的滞后,而不会干扰它所涵盖的任何内容。我有两个选择:

  1. 选项1:更新屏幕上的所有内容(当然,它没有给我一个好的性能)
  2. 选项2:仅更新屏幕的实际使用部分。然而,即使使用这种方法,我也无法实现屏幕更新的良好性能。我想稍后添加一个功能来控制动画的速度,它的速度可能比我现在代码的最高性能还要快

正如您所看到的,到目前为止,我没有任何time.sleep()。我希望提高代码的性能,然后能够添加time.sleep()以获得更受控制的动画。我当前的pygame应用程序已经与另一个进程并行运行,我使用multiprocessing库实现了这个进程

问题:如何加快速度

我的python版本:3.7.0,pygame版本:1.9.6

PS:对不起,问题太长了


Tags: thepathinfor节点range动画screen
2条回答

试用 pygame.time.Clock().tick(**) 这是一个命令,允许您选择要运行程序的FPS,从而提高渲染速度。如果您决定使用这个,请在我写星号的地方放置一个整数,表示FPS

所以,我找到了一个解决办法!基本上,由于pygame自身的渲染能力,我无法使代码运行得更快,即使HW模式也不能大大提高速度

解决方案(更多的解决方法):

我添加了一层等待期,在这一层中,pygame拍摄渲染屏幕的快照,并将图像存储在自行创建的缓存中,而不更新屏幕。后来,我有了一个平滑可操作的屏幕,可以用来观看动画

代码如下:

def runPathAnimation(path, colortype):
    index = 0
    images = []
    for i in range(len(path)-1):
        x1, y1 = (gmd[path[i]].getNodePosition())[0], (gmd[path[i]].getNodePosition())[1]
        x2, y2 = (gmd[path[i+1]].getNodePosition())[0], (gmd[path[i+1]].getNodePosition())[1]
        m = (y1-y2)/(x1-x2) if x1 != x2 else 'undefined'

        cx, cy = range(min(x1,x2),max(x1,x2)), range(min(y1,y2),max(y1,y2))
        if y1 > y2:
            cy = reversed(cy) 
        if x1 > x2:
            cx = reversed(cx)

        if str(m) != 'undefined':
            con = y2-(m*x2)
            if m > 0.5 or (m <= -1 and m >= -1.5):
                for y in cy:
                    ev = pyg.event.get()
                    x = int((y-con)/m)
                    images.append(loadpath(x,y,path,colortype,index))
                    index += 1
                    r = pyg.draw.rect(screen, colortype, (md.WIDTH_NETWORKPLOT-250,md.PLOT_AREA[1]+30,index/5,20), 2)
                    pyg.display.update(r)
            else:
                for x in cx:
                    ev = pyg.event.get()
                    y = int(m*x+con)
                    images.append(loadpath(x,y,path,colortype,index))
                    index += 1
                    r = pyg.draw.rect(screen, colortype, (md.WIDTH_NETWORKPLOT-250,md.PLOT_AREA[1]+30,index/5,20), 2)
                    pyg.display.update(r)
        else:
            for y in cy:
                ev = pyg.event.get()
                images.append(loadpath(x1,y,path,colortype,index))
                index += 1
                r = pyg.draw.rect(screen, colortype, (md.WIDTH_NETWORKPLOT-250,md.PLOT_AREA[1]+30,index/5,20), 2)
                pyg.display.update(r)
        print('Loading...'+str((i+1)/len(path)*100)+'%')

    runAnimation(images)

def runAnimation(images):
    animate = True
    img = 0
    print('Start!')
    while animate:
        ev = pyg.event.get()
        pyg.event.pump()
        keys = pyg.key.get_pressed()
        if keys[pyg.K_LEFT]:
            img -= 1
            if img < 0:
                img = 0
        if keys[pyg.K_RIGHT]:
            img += 1
            if img >= len(images) - 2:
                img = len(images) - 2
        if keys[pyg.K_q]:
            animate = False
        screen.blit(images[img],(0,0))
        pyg.display.update((0, 0, md.WIDTH_NETWORKPLOT, md.PLOT_AREA[1]))

PS:在我的代码中,md.xxx是我的matplotlibpygame屏幕的维度

重要提示:这只是一个解决办法,不是解决方案

相关问题 更多 >