code: def _draw_surfaces(self, surface, offset, surfaces):
          
          surface_blit = surface.blit
          ox, oy = offset
          left, top = self._tile_view.topleft
          hit = self._layer_quadtree.hit
          get_tile = self.data.get_tile_image
          tile_layers = tuple(self.data.visible_tile_layers)
          dirty = list()
          dirty_append = dirty.append
  
          # TODO: check to avoid sorting overhead
          # sort layers, then the y value
          def sprite_sort(i):
              return i[2], i[1][1] + i[0].get_height()
  
          surfaces.sort(key=sprite_sort)
  
          layer_getter = itemgetter(2)
          for layer, group in groupby(surfaces, layer_getter):
              del dirty[:]
  
              for i in group:
                  try:
                      flags = i[3]
                  except IndexError:
                      dirty_append(surface_blit(i[0], i[1]))
                  else:
                      dirty_append(surface_blit(i[0], i[1], None, flags))
  
              # TODO: make set of covered tiles, in the case where a cluster
              # of sprite surfaces causes excessive over tile overdrawing
              for dirty_rect in dirty:
                  for r in hit(dirty_rect.move(ox, oy)):
                      x, y, tw, th = r
                      for l in [i for i in tile_layers if gt(i, layer)]:
  
                          if self.tall_sprites and l == layer + 1:
                              if y - oy + th <= dirty_rect.bottom - self.tall_sprites:
                                  continue
  
                          tile = get_tile(x // tw + left, y // th + top, l)
                          tile and surface_blit(tile, (x - ox, y - oy))
docs: Draw surfaces onto buffer, then redraw tiles that cover them
  
          :param surface: destination
          :param offset: offset to compensate for buffer alignment
          :param surfaces: sequence of surfaces to blit