【问题标题】:Is there a faster way to blit many images on Pygame?有没有更快的方法在 Pygame 上对许多图像进行 blit 处理?
【发布时间】:2018-04-08 12:34:05
【问题描述】:

我有一个“地图”/轨道:

track_data = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]

这些数字中的每一个都代表一个图像。正如您将在课堂上看到的那样,我在每个循环中对它们中的每一个进行了 blit。如果我只对它们进行一次blit 并且不填充背景以提高性能,那么移动的物体(汽车)会以刷子般的方式(显然)绘制屏幕。所以,我必须在每一帧都画出来。问题是:这该死的太慢了。有没有更快的方法来blit?

class Track:

    TRACK_SIZE = 16

    START = 0
    DIRT = 1
    ROAD = 2

    DIRT_IMAGE = "gfx/dirt.png"
    ROAD_IMAGE = "gfx/road.png"

    def __init__(self):
        self.data = test.track_data
        self.spawnpoints = test.track_spawnpoints
        self.waypoints = test.track_waypoints
        self.actors = []
        self.spawn_positions = {}
        self.actor_dimensions = [
            options["RESOLUTION"][0] / 16,
            options["RESOLUTION"][1] / 16
        ]
        self.updated = False
        for row in self.data:
            actor_row = []
            for column in row:
                if column == Track.START:
                    pass
                elif column == Track.DIRT:
                    actor_row.append(pygame.image.load(Track.DIRT_IMAGE))
                elif column == Track.ROAD:
                    actor_row.append(pygame.image.load(Track.ROAD_IMAGE))
            self.actors.append(actor_row)
        occurence_counter = 0
        for y in range(Track.TRACK_SIZE):
            for x in range(Track.TRACK_SIZE):
                if self.spawnpoints[y][x] != 0:
                    self.spawn_positions[occurence_counter] = (
                        x*int(self.actor_dimensions[0]) + Car.WIDTH,
                        y*int(self.actor_dimensions[1]) + Car.HEIGHT
                    )
                    occurence_counter += 1

    def draw(self, surface):
        if not self.updated:
            for y in range(Track.TRACK_SIZE):
                for x in range(Track.TRACK_SIZE):
                    surface.blit(
                        self.actors[y][x], 
                        [x*int(self.actor_dimensions[0]), y*int(self.actor_dimensions[1])]
                    ) # Here <<<

【问题讨论】:

  • 没有 blit 比没有 blit 快。你应该看看脏矩形动画概念。 pygame.org/docs/tut/newbieguide.html(在页面的前三分之一左右)。它可以真正加快你的代码速度;)
  • 哦,非常感谢。不敢相信我跳过了一个叫做“新手指南”的材料哈哈哈,非常有用。

标签: python pygame pygame-surface


【解决方案1】:

原来解决这个问题很容易。我所要做的就是创建一个屏幕大小、轨道大小的中间表面,并将所有地面图像blit一次,然后在主循环上blit中间轨道表面而不是256 张单独的图像。

class Track:

    TRACK_SIZE = 16

    DIRT = 1
    ROAD = 2

    DIRT_IMAGE = "gfx/dirt.png"
    ROAD_IMAGE = "gfx/road.png"

    def __init__(self):
        self.ground_data = test.track_ground_data
        self.spawnpoints = test.track_spawnpoints
        self.waypoints = test.track_waypoints
        self.actors = []
        self.ground_positions = {}
        self.spawn_positions = {}
        self.waypoint_positions = {}
        self.actor_dimensions = [
            options["RESOLUTION"][0] / 16,
            options["RESOLUTION"][1] / 16
        ]
        self.surface = pygame.Surface((options["RESOLUTION"][0], options["RESOLUTION"][1]), pygame.SRCALPHA, 32)
        for row in self.ground_data:
            actor_row = []
            for column in row:
                if column == Track.DIRT:
                    actor_row.append(pygame.image.load(Track.DIRT_IMAGE))
                elif column == Track.ROAD:
                    actor_row.append(pygame.image.load(Track.ROAD_IMAGE))
            self.actors.append(actor_row)
        for y in range(Track.TRACK_SIZE):
            for x in range(Track.TRACK_SIZE):
                if self.ground_data[y][x] != 0:
                    self.ground_positions[(
                        x*int(self.actor_dimensions[0]),
                        y*int(self.actor_dimensions[1])
                    )] = self.ground_data[y][x]
                if self.spawnpoints[y][x] != 0:
                    self.spawn_positions[self.spawnpoints[y][x]] = (
                        x*int(self.actor_dimensions[0]) + Car.WIDTH,
                        y*int(self.actor_dimensions[1]) + Car.HEIGHT
                    )
                if self.waypoints[y][x] != 0:
                    self.waypoint_positions[self.waypoints[y][x]] = (
                        x*int(self.actor_dimensions[0]) + Car.WIDTH,
                        y*int(self.actor_dimensions[1]) + Car.HEIGHT
                    )
        # Blitting the track images to the track surface for greater performance.
        for y in range(Track.TRACK_SIZE):
            for x in range(Track.TRACK_SIZE):
                self.surface.blit(
                    self.actors[y][x], 
                    [x*int(self.actor_dimensions[0]), y*int(self.actor_dimensions[1])]
                )

    def draw(self, surface):
        surface.blit(self.surface, (0, 0))

【讨论】:

    【解决方案2】:

    我参加聚会有点晚了,但也会有巨大的性能提升:

    DIRT_IMAGE = pygame.image.load("gfx/dirt.png").convert() # if you dont have transparency
    ROAD_IMAGE = pygame.image.load("gfx/road.png").convert_alpha # if you have transparency
    
    
    actor_row.append(DIRT_IMAGE)
    actor_row.append(ROAD_IMAGE )
    

    1) 您不必经常加载图像,而只需加载一次(这有助于在开始时加载时间)

    2) 在图像上使用“.convert()”可以极大地提升整个“游戏周期”的性能,或者无论你经常对它们进行 Blit,尤其是在大范围内对许多图像进行 Blit 时

    【讨论】:

      猜你喜欢
      • 2019-06-28
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多