使用Pygame,是否有更快的方法来绘制数百个小方块?

时间:2015-12-16 01:00:59

标签: python pygame

我试图制作一个基于平铺的游戏,之前没有做过这样的事情,所以我一直在学习。但是,我的速度问题很严重,我想知道是否有人有任何解决方案/建议。我试图将重新计算的位和实际绘图分开,但是因为你现在只能移动相机,所以它必须同时进行这两项操作,并且如果你有一个小的,它的运行速度非常明显瓷砖和大分辨率。

我认为一个想法是将它分成块,所以你计算一个x * x区域,而不是检查每个瓷砖是否在屏幕范围内,你只检查瓷砖组,然后以某种方式在第一次绘制时缓存它,然后你最终从内存中绘制一个图像。但是当我用Google搜索时,我没有找到任何相关内容。

对于绘图部分,它运行到:

for tile in tile_dict:
    pygame.draw.rect(precalculated stuff)

使用与下图相同的tileize,在720p时以100fps运行,在1080p时以75fps运行。除了绘制正方形之外,这几乎没什么。每个块的颜色略有不同,所以我不能画出更大的正方形。我知道不要重新划分每一帧。

至于重新计算部分,它有点长,但仍然很容易理解。我计算哪些坐标位于屏幕的边缘,并使用它来构建所有屏幕图块的列表。然后我删除该区域之外的任何图块,如果图块已在屏幕上移动,则将该图块移动到新位置,并计算刚刚出现的任何图块。这个速度在720p时大约为90fps,在1080p时大约为45fps,这真的不太好。

def recalculate(self):
    overflow = 2
    x_min = self.cam.x_int + 1 - overflow
    y_min = self.cam.y_int + 1 - overflow
    x_max = self.cam.x_int + int(self.WIDTH / self.tilesize) + overflow
    y_max = self.cam.y_int + int(self.HEIGHT / self.tilesize) + overflow


    self.screen_coordinates = [(x, y) 
                               for x in range(x_min, x_max) 
                               for y in range(y_min, y_max)]


    #Delete the keys that have gone off screen
    del_keys = []
    for key in self.screen_block_data:
        if not x_min < key[0] < x_max or not y_min < key[1] < y_max:
            del_keys.append(key)
    for key in del_keys:
        del self.screen_block_data[key]


    #Rebuild the new list of blocks
    block_data_copy = self.screen_block_data.copy()
    for coordinate in self.screen_coordinates:

        tile_origin = ((coordinate[0] - self.cam.x_int) - self.cam.x_float, 
                       (coordinate[1] - self.cam.y_int) - self.cam.y_float)
        tile_location = tuple(i * self.tilesize for i in tile_origin)

        #Update existing point with new location
        if coordinate in self.screen_block_data:
            self.screen_block_data[coordinate][2] = tile_location
            continue

        block_type = get_tile(coordinate)

        #Generate new point info
        block_hash = quick_hash(*coordinate, offset=self.noise_level)

        #Get colour
        if coordinate in self.game_data.BLOCK_TAG:
            main_colour = CYAN   #in the future, mix this with the main colour
        else:
            main_colour = TILECOLOURS[block_type]
        block_colour = [min(255, max(0, c + block_hash)) for c in main_colour]
        self.screen_block_data[coordinate] = [block_type, 
                                              block_colour, 
                                              tile_location]

我意识到在上面写的内容中,我可能会将信息缓存到10x10区域或其他东西,以减少移动相机时需要做的事情,但仍然无法解决问题图。

我可以上传完整的代码,如果有人想尝试使用它(它可以拆分几个文件,所以可能更容易不在这里粘贴所有内容),但这里有一个截图,显示它当前的样子有点参考:

enter image description here

1 个答案:

答案 0 :(得分:0)

要提高绘制小方块的速度,可以将它们绘制到非屏幕表面(任何大小足以容纳所有方块的pygame表面),然后使用正确的坐标在屏幕上显示该表面。 这样你就不需要检查屏幕外是否有任何方块,只需要提供倒置的摄像机(视点)坐标(如果摄像机位置是[50,20]那么你应该用瓦片将表面点到[]上-50,-20])。