SnK
SnK

Reputation: 58

Rendering and refreshing tmx file map with python and pytmx

I am using pytmx to load my map with pygame, but some items needs to be set as sprites and displayed above the surface, so the layering doesn't stay, I will show you 2 examples, one with the player displaying on top of decorations (where the point layer in under the decorations) the other one is the door displaying above the walls.

I tried to refresh my map with my player and door object by rewriting make_map() and render(surface) functions from Renderer, but instead of passing object I iterated threw them to blit the one it was, it has displaying, but still not layered, and also half FPS goes down.

Si if anyone knows how to be able to keep the layering even with player and other object used to render animated sprites I would be glad to get your help please.

Player on top of the decorations Layering in my map editor Door in my game Door in the map editor

This is the code I tried to use to refresh map every time with layering (it was displaying, but it has the exact same results as if I draw only the surface and then draw sprites above) :


    def draw(self, display, camera = None):
        
        self.surface = self.make_map()
        self.rect = self.surface.get_rect()
        
        if not camera:
            display.blit(self.surface, self.rect)
        else:
            display.blit(self.surface, (self.rect.x - camera.offset.x, self.rect.y - camera.offset.y))
    
    def render(self, surface):
        
        tw = self.tmx_data.tilewidth
        th = self.tmx_data.tileheight
        
        if self.tmx_data.background_color:
            surface.fill(self.tmx_data.background_color)
        else:
            surface.fill((0, 0, 0))
            
        for layer in self.tmx_data.layers:
            if isinstance(layer, pytmx.TiledTileLayer):
                for x, y, image in layer.tiles():
                    if image:
                        surface.blit(image.convert_alpha() , (x * tw, y * th))

            elif isinstance(layer, pytmx.TiledObjectGroup):
                for tile_object in layer:
                    if tile_object.name == 'player':
                        surface.blit(self.level.game.player.image.convert_alpha(), (self.level.game.player.rect.x, self.level.game.player.rect.y))
                    
                    if tile_object.name == 'door':
                        for door in self.level.game.doors:
                            if door.type == tile_object.type:
                                surface.blit(door.image.convert_alpha(), (door.rect.x, door.rect.y))
                                
                                
            elif isinstance(layer, pytmx.TiledImageLayer):
                if image:
                    surface.blit(image , (0, 0))
        
    def make_map(self):
        temp_surface = pygame.Surface(self.renderer.size)
        self.render(temp_surface)
        return temp_surface
    

Upvotes: 0

Views: 407

Answers (1)

SnK
SnK

Reputation: 58

So I have found a way to get what I wanted, I had used pyagme sprites groups layeredUpdates, I added to my original map only floor, I created layered sprites with my other layers (walls,decorations) and then displayed with the layer

The map rendering


    def render(self, surface):

        tw = self.tmx_data.tilewidth
        th = self.tmx_data.tileheight
        
        if self.tmx_data.background_color:
            surface.fill(self.tmx_data.background_color)
        else:
            surface.fill((0, 0, 0))

        for layer in self.tmx_data.layers:
            if isinstance(layer, pytmx.TiledTileLayer):
                for x, y, image in layer.tiles():
                    if image:
                        if layer.name == 'walls' or 'wall' in layer.name:
                            Wall(self.game, x * tw, y * th, image.convert_alpha())
                        elif 'decoration' in layer.name:
                                Decoration(self.game, x * tw, y * th, image.convert_alpha())
                        else:
                            surface.blit(image.convert_alpha() , (x * tw, y * th))

            elif isinstance(layer, pytmx.TiledObjectGroup):
                pass

            elif isinstance(layer, pytmx.TiledImageLayer):
                if image:
                    surface.blit(image , (0, 0))

    def make_map(self):
        temp_surface = pygame.Surface(self.size)
        self.render(temp_surface)
        return temp_surface
    

The objects :


class Decoration(pygame.sprite.Sprite):
    def __init__(self, game, x, y, image, layer = DECORATION_TOP_LAYER):
        self.groups = game.all_sprites, game.decorations
        self._layer = layer
        pygame.sprite.Sprite.__init__(self, self.groups)
        

class Wall(pygame.sprite.Sprite):
    def __init__(self, game, x, y, image):
        self.groups = game.all_sprites, game.walls
        self._layer = WALL_LAYER
        pygame.sprite.Sprite.__init__(self, self.groups)
        
class Door(pygame.sprite.Sprite):
    def __init__(self, game, x, y, w, h, open_actions, animated_image, type):
        self._layer = DOOR_LAYER
        self.groups = game.all_sprites, game.doors
        pygame.sprite.Sprite.__init__(self, self.groups)
        

class NPC(pygame.sprite.Sprite):
    def __init__(self, game, x, y, w, h, animated_image):
        self.groups = game.all_sprites, game.NPCs
        self._layer = NPC_LAYER
        pygame.sprite.Sprite.__init__(self, self.groups)
        

And the thing that makes all works together is simply :


self.all_sprites = pygame.sprite.LayeredUpdates()

Upvotes: 0

Related Questions