是否可以使用Surface.copy()复制表面的特定部分?

时间:2019-05-03 12:10:01

标签: python animation pygame updating surface

我是脏矩形动画的新手,我目前正在尝试存储主显示表面窗口的快照,但是我只想存储将要变光的区域,以便可以调用下一个帧而不是重新散布整个背景。

我查看了Surface.copy()的文档,但它没有参数,除pygame.pixelcopy()以外,我找不到任何类似的东西,据我所知,这不是我想要的东西。如果Surface.copy()不是我想要的,请告诉我其他选择。

import pygame, time
pygame.init()
screen = pygame.display.set_mode((500, 500))

screen.fill((128, 128, 128))
pygame.display.update()

#immagine a complex pattern being blit to the screen here
pygame.draw.rect(screen, (128, 0, 0), (0, 0, 50, 50))
pygame.draw.rect(screen, (0, 128, 0), (50, 0, 50, 50))
pygame.draw.rect(screen, (0, 0, 128), (200, 0, 50, 50))

#my complex background area that i want to save ()
area_to_save = pygame.Rect(0, 0, 100, 50)

rest_of_background = pygame.Rect(200, 0, 50, 50)

#updating for demo purposes
dirty_rects = [area_to_save, rest_of_background]
for rect in dirty_rects:
    pygame.display.update(rect)
temp_screen = screen.copy()

time.sleep(3)
#after some events happen and I draw the item thats being animated onto the background
item_to_animate = pygame.Rect(35, 10, 30, 30)
pygame.draw.rect(screen, (0, 0, 0), item_to_animate)
pygame.display.update(item_to_animate)

time.sleep(3)
item_to_animate = pygame.Rect(50, 60, 30, 30)
pygame.draw.rect(screen, (0, 0, 0), item_to_animate)
#now that the item has moved, draw back old frame, which draws over the whole surface
screen.blit(temp_screen, (0, 0))
pygame.display.update()

#I understand swapping the drawing of the new item location to after temp_surface blit
#will provide me the desired outcome in this scenario but this is a compressed version of my problem
#so for simplicity sake, is there a way of not saving the whole surface, only those rects defined?

我希望这段代码的输出将显示我的背景3秒钟,然后黑色正方形覆盖图案,然后再过3秒钟,黑色正方形出现在我的图案下面。

P.S .:我是这个网站的新手,请告诉我是否做错了事!

编辑:对于任何想知道此解决方案(先在背景上划掉一个项目之前先保存背景,然后在新项目位置被遮盖之前重新绘制所保存的背景)的方法,是否比重新绘制整个背景然后再使该项目更有效,在方格图案上使用简单的方形动画并每次重绘整个背景,会使我的整体fps从1000(重绘背景前)降低到平均500左右,降低了约50%。在使用脏矩形时,上面的这种方法可以达到900 fps。

2 个答案:

答案 0 :(得分:0)

您可以使用subsurface指定要复制的区域,然后在返回的Surface上调用copy

但是请注意,这可能根本不会提高游戏的性能,因为在周围复制很多Surface并不是免费的。只需尝试检查一下自己是否真的更好,然后每帧绘制一个背景表面即可。

还请注意,您绝对不要在游戏中使用time.sleep。尽管sleep阻止了您的游戏进程,但您的游戏无法处理事件,因此您例如目前无法退出游戏。另外,如果您不通过调用pygame.event.get处理事件,则可能不会重绘游戏窗口;而且由于您从未致电pygame.event.get而使事件队列满了,您的游戏就会冻结。

答案 1 :(得分:0)

您想做的事可以通过pygame.Surface.blit()来实现。

创建一个具有确定大小的表面,并在该表面上blit占据屏幕区域。注意,bilt的第三个参数是一个可选参数,用于选择源曲面的矩形区域:

# create a surface with size 'area_to_save.size'
temp_screen = pygame.Surface(area_to_save.size)

# blit the rectangular area 'area_to_save' from 'screen' to 'temp_screen' at (0, 0) 
temp_screen.blit(screen, (0, 0), area_to_save)