如何在pygame中导入tmx地图?

时间:2019-02-12 19:43:14

标签: python pygame tiles pytmx

我在Tiled Editor程序中制作了一个* tmx映射。然后,我尝试将其导入到我的游戏中。当我将变量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

我认为这与我的图层有关。我的地图只有一层。仍然我的脚本不起作用。我还对地图使用了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 :(得分: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)

顺便说一句,请原谅我的语言。希望能工作。

编辑:您可以在pygame中查看此视频的详细信息,以导入tmx映射。视频链接:https://www.youtube.com/watch?v=QIXyj3WeyZM

答案 1 :(得分:1)

我认为@gurbuz的答案已经涵盖了大部分内容,因此我将提供几乎相同的答案,但要自己动手;)

因此,您的TMX地图定义了一个纹理平铺的网格,该网格构成了一个充满地图/级别/所有内容的屏幕。就像陶瓷地砖一样,它们每个都单独处理,然后分别放置在地板上。

问题中的代码看起来正确,可以在地图的第0层中找到(0,0 /左上)单个磁贴并将其绘制到屏幕上。我怀疑这会为layer=1产生错误,因为地图仅包含一层。但是没有地图,就不可能知道。

要显示整个地图,必须遍历.tmx文件中定义的每个图块,并将它们放置在表面上。然后可以将该表面简单地.blit〜设置为pygame窗口。

我拼凑了这个基本功能,该功能可以加载整个地图,并将其渲染到表面上。这是一种幼稚的方法,因为此图像可能巨大。但这只是为了说明如何遍历地图元素并绘制它们。

# 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

因此,一旦将地图“转换”为一个表面,就可以将这个表面简单地涂在pygame屏幕上:

# 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地图元素。记录下要显示的地图子坐标很容易,然后生成-在需要查看时说右边一栏。