2

I am trying to understand the tilemaps in pygame, and to learn how to use Tiled Map Editor, but I can't succeed to load the map in the pygame. Here is the code:

import pygame
import pytmx

pygame.init()

display = pygame.display.set_mode((600,400))
clock = pygame.time.Clock()

gameMap = pytmx.TiledMap("map.tmx")

while(True):

    clock.tick(60)
    keys = pygame.key.get_pressed()

    for event in pygame.event.get():
        if(event.type == pygame.QUIT):
            quit()

    if(keys[pygame.K_ESCAPE]):
        quit()

    for layer in gameMap.visible_layers:
            for x, y, gid, in layer:
                tile = gameMap.get_tile_image_by_gid(gid)
                if(tile != None):
                    display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight))

    pygame.display.update()

It keep giving me this error:

Traceback (most recent call last): File "main.py", line 27, in display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight)) TypeError: argument 1 must be pygame.Surface, not tuple

I know that when I print the tile in console this is what I get

(a tuple): ('img/NES - Super Mario Bros - Tileset.png', (0, 144, 16, 16), TileFlags(flipped_horizontally=False, flipped_vertically=False, flipped_diagonally=False)).

What is the simplest method to successfully load a tilemap in pygame and what am I doing wrong?

Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51
user193464
  • 380
  • 1
  • 6
  • 25
  • I can confirm your error. `display` is a `Surface` object, `tile` is not. The error is telling you that you are passing the wrong kind of object as the arg to `display.blit`. `tile` is `: ('Tiled Images/background.png', (0, 0, 160, 96), TileFlags(flipped_horizontally=False, flipped_vertically=False, flipped_diagonally=False))` You get some activity to screen if you replace `tile` with `display`. – Shawn Mehan Aug 31 '17 at 23:48
  • Thank you. So how to make it work? – user193464 Aug 31 '17 at 23:51
  • I've never used this before. I'm looking at it now. If you put in a `time.sleep(6)` after the `display.blit` you will see the pygame window render to your screen.... – Shawn Mehan Aug 31 '17 at 23:58
  • The window appears, but I wanted to render the tiles of the map in the window. – user193464 Sep 01 '17 at 00:02
  • I know. Give me a moment....I'm learning this as I go.... – Shawn Mehan Sep 01 '17 at 00:05
  • I am waiting. Thank you very much for helping. – user193464 Sep 01 '17 at 00:09

2 Answers2

2

use:

gameMap = pytmx.load_pygame("map.tmx")

instead of:

gameMap = pytmx.TiledMap("map.tmx")
Bluebot
  • 166
  • 15
1

I think that the following covers most of the mechanics of rendering the mapSurface and drawing something on it with update and loadMap. I don't have any real TMX files to test with. ymmv. Good luck.

import time
import pygame
import pytmx


class TiledMap():
""" This is creating the surface on which you make the draw updates """
    def __init__(self):
        self.gameMap = pytmx.load_pygame("map.tmx", pixelalpha=True)
        self.mapwidth = self.gameMap.tilewidth * self.gameMap.width
        self.mapheight = self.gameMap.tileheight * self.gameMap.height

    def render(self, surface):
        for layer in self.gameMap.visible_layers:
            if isinstance(layer, pytmx.TiledTileLayer):
                for x, y, gid in layer:
                    tile = self.gameMap.get_tile_image_by_gid(gid)
                    if tile:
                        surface.blit(tile, (x * self.gameMap.tilewidth, y * self.gameMap.tileheight))

    def make_map(self):
        mapSurface = pygame.Surface((self.mapwidth, self.mapheight))
        self.render(mapSurface)
        return mapSurface

pygame.init()


class Display():
""" This is the class that makes the changes that you want to display. You would add most of your changes here. """

    def __init__(self):

        self.displayRunning = True
        self.displayWindow = pygame.display.set_mode((600, 400))
        self.clock = pygame.time.Clock()

    def update(self):

        pygame.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        pygame.display.update()

    def loadMap(self):

        self.map = TiledMap()
        self.map_img = self.map.make_map()
        self.map_rect = self.map_img.get_rect()

    def displayLoop(self):

        self.clock.tick()
        self.update()
        self.loadMap()

# Here is the start of the main driver


runDisplay = Display()

runDisplay.update()
runDisplay.loadMap()
time.sleep(60)

If you want it to run in a loop then you would change that bottom driver block to something like:

runDisplay = Display()
while runDisplay.displayRunning is True:
    runDisplay.displayLoop()
Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51
  • Wow. Thank you. Now it's working. It loads the map. Thank you very muuuch. I reallly thought that it wouldn't work. – user193464 Sep 01 '17 at 07:18
  • But do you know why in my code the tile wasn'y considered a pygame.Surface and in your example it is? – user193464 Sep 01 '17 at 07:58