如何在 pygame 中导入 tmx 地图?

How to import an tmx map in pygame?

我在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

因为tile似乎只有(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 地图的详细视频。视频 link:https://www.youtube.com/watch?v=QIXyj3WeyZM

我认为@gurbuz 的回答已经涵盖了大部分内容,所以我将提出大致相同的答案,但有我自己的看法;)

因此,您的 TMX 地图定义了一个纹理瓷砖网格,这些瓷砖构成了一个充满 map/level/whatever 的屏幕。就像陶瓷地砖一样,每块都单独处理,单独铺在地板上。

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

要显示整个地图,有必要遍历 .tmx 文件中定义的每个图块,并将它们放置在表面上。这个表面然后可以简单地 .blit~ted 到 pygame window.

我拼凑了这个加载整个地图并将其渲染到表面的基本函数。这是一种天真的做法,因为这张图片可能 巨大 。但它的目的是说明如何遍历地图的元素并绘制它们。

# 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

所以一旦地图 "converted" 到一个表面,就可以简单地将这个表面 blit 到 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 地图元素。很容易记录显示了地图的哪些子坐标,然后去生成-需要看到的时候就说右边那一栏。