Как импортировать карту TMX в Pygame?

Я сделал карту *tmx в программе Tiled Editor. Затем я попытался импортировать его в свою игру. Когда я меняю переменную layers в 0 это работает, но на экране только 1 плитка. Я хочу напечатать всю карту на моем экране. Но я получаю следующую ошибку.

Traceback (most recent call last):
  File "C:\Users\LL\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pytmx\pytmx.py", line 512, in get_tile_image
    layer = self.layers[layer]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\LL\Desktop\Erik\RPG_project\RPG project\data\main.py", line 143, in <module>
    game_initialize()
  File "C:\Users\LL\Desktop\Erik\RPG_project\RPG project\data\main.py", line 117, in game_initialize
    map_setup()
  File "C:\Users\LL\Desktop\Erik\RPG_project\RPG project\data\main.py", line 140, in map_setup
    image = tmxdata.get_tile_image(0, 0, 2)
  File "C:\Users\LL\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pytmx\pytmx.py", line 514, in get_tile_image
    raise ValueError
ValueError

Я думаю, что это связано с моими слоями. У меня есть только 1 слой для моей карты. Тем не менее мой сценарий не работает. Я также использую Base64 (сжатый) для моей карты. И 32 пикселя большие плитки.

from pytmx import load_pygame

def map_setup():
    global image

    # Getting / Importing the map
    tmxdata = load_pygame("Tile_files\\mymap2.tmx")

    image = tmxdata.get_tile_image(0, 0, 1) # x, y, layer

2 ответа

Потому что плитка кажется только (0,0) позиции. Вы должны дать петли слоев. Я написал этот код, возможно, поможет вам.

from pytmx import load_pygame, TiledTileLayer

def map_setup():
    global image

    # Getting / Importing the map
    tmxdata = load_pygame("Tile_files\\mymap2.tmx")
    width = tmxdata.width * tmxdata.tilewidth
    height = tmxdata.height * tmxdata.tileheight

    ti = tmxdata.get_tile_image_by_gid
    for layer in tmxdata.visible_layers:
        if isinstance(layer, TiledTileLayer):
            for x, y, gid, in layer:
                tile = ti(gid)
                if tile:
                    image = tmxdata.get_tile_image(x, y, layer)

Кстати, извините за мой язык. Надеюсь, работает.

Изменить: Вы можете посмотреть это видео подробно для импорта карты TMX в Pygame. Ссылка на видео: https://www.youtube.com/watch?v=QIXyj3WeyZM

Я думаю, что ответ @ gurbuz уже охватил большую часть этого, так что я представлю почти тот же ответ, но со своим собственным спином;)

Таким образом, ваша карта TMX определяет сетку текстурированных плиток, которые составляют экран, полный карты / уровня / чего угодно. Точно так же, как керамическая плитка для пола, каждая из них обрабатывается индивидуально и укладывается на пол индивидуально.

Код в вопросе выглядит правильным, чтобы найти одну (0,0 / верхнюю левую) отдельную плитку в нулевом слое карты и нарисовать ее на экране. Я подозреваю, что это вызывает ошибку для layer=1 потому что карта содержит только один слой. Но без карты это невозможно узнать.

Чтобы показать всю карту, необходимо перебрать все плитки, определенные в .tmx файл, и поместите их на поверхность. Эта поверхность может быть просто .blit Тед в окно пигмея.

Я собрал воедино эту основную функцию, которая загружает всю карту, отображая ее на поверхности. Это наивный способ сделать это, потому что это изображение может быть огромным. Но это служит для иллюстрации того, как пройти элементы карты и нарисовать их.

# Convert HTML-like colour hex-code to integer triple tuple
# E.g.: "#892da0" -> ( 137, 45, 160 )
def hexToColour( hash_colour ):
    red   = int( hash_colour[1:3], 16 )
    green = int( hash_colour[3:5], 16 )
    blue  = int( hash_colour[5:7], 16 )
    return ( red, green, blue )

# Given a loaded pytmx map, create a single image which holds a 
# rendered version of the whole map.
def renderWholeTMXMapToSurface( tmx_map ):
    width  = tmx_map.tilewidth  * tmx_map.width
    height = tmx_map.tileheight * tmx_map.height

    # This surface could be huge
    surface = pygame.Surface( ( width, height ) )

    # Some maps define a base-colour, if so, fill the background with it
    if ( tmx_map.background_color ):
        colour = tmx_map.background_color
        if ( type( colour ) == str and colour[0].startswith( '#' ) ):
            colour = hexToColour( colour )
            surface.fill( colour )
        else:
            print( "ERROR: Background-colour of [" + str( colour ) + "] not handled" )

    # For every layer defined in the map
    for layer in tmx_map.visible_layers:
        # if the Layer is a grid of tiles
        if ( isinstance( layer, pytmx.TiledTileLayer ) ):
            for x, y, gid in layer:
                tile_bitmap = tmx_map.get_tile_image_by_gid(gid)
                if ( tile_bitmap ):
                    surface.blit( tile_bitmap, ( x * tmx_map.tilewidth, y * tmx_map.tileheight ) )
        # if the Layer is a big(?) image
        elif ( isinstance( layer, pytmx.TiledImageLayer ) ):
            image = get_tile_image_by_gid( layer.gid )
            if ( image ):
                surface.blit( image, ( 0, 0 ) )
        # Layer is a tiled group (woah!)
        elif ( isinstance( layer, pytmx.TiledObjectGroup ) ):
            print( "ERROR: Object Group not handled" )

    return surface

Поэтому, когда карта "преобразована" в поверхность, можно просто перетянуть эту поверхность на экран пигмея:

# Before the main loop starts
tmx_map   = pytmx.load_pygame( "test.tmx", pixelalpha=True )
map_image = renderWholeTMXMapToSurface( tmx_map )

# Main loop
while not finished:
    ...
    pygame_screen.blit( map_image, ( 0, 0 ) )
    ...

Лучший способ сделать это - загрузить только элементы карты TMX, необходимые для отображения. Легко записать, какие подкоординаты карты отображаются, а затем перейти к генерации - скажем, в правом столбце, когда это должно появиться.

Другие вопросы по тегам