如何在 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 地图元素。很容易记录显示了地图的哪些子坐标,然后去生成-需要看到的时候就说右边那一栏。
我在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 地图元素。很容易记录显示了地图的哪些子坐标,然后去生成-需要看到的时候就说右边那一栏。