如何使用pytmx加载地图图层并将部分图层转换为Rect碰撞体
pytmx 地图加载与碰撞体实现方案
基础绘制功能修复
原代码存在3个常见问题会导致绘制失败:
- 未过滤gid为0的空瓦片,空瓦片没有对应图像,直接调用blit会触发空对象报错
- 瓦片坐标计算时硬编码了
*16的尺寸,没有适配tmx文件中实际设置的瓦片宽高 - 加载地图时未开启pygame的像素格式适配,可能出现透明区域显示异常
修复后的基础绘制代码如下:
import pygame import pytmx pygame.init() W, H = 800, 400 FPS = 60 win = pygame.display.set_mode((W, H), 0, 32) pygame.display.set_caption('trying to make this work somewhow') # 加载地图时开启pixelalpha适配,解决透明显示问题 game_map = pytmx.load_pygame('map/map.tmx', pixelalpha=True) # 取地图本身设置的瓦片尺寸,避免硬编码适配问题 tile_width = game_map.tilewidth tile_height = game_map.tileheight run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False win.fill((146, 244, 200)) for layer in game_map.visible_layers: for x, y, gid in layer: # 过滤空瓦片 if gid == 0: continue tile = game_map.get_tile_image_by_gid(gid) if tile: win.blit(tile, (x * tile_width, y * tile_height)) pygame.display.update() pygame.quit()
碰撞层转换实现
按照以下步骤即可将指定图层转为Rect碰撞体:
- 先在Tiled编辑器中对需要作为碰撞的图层做标记:可以直接将图层命名为
collision,或者给图层添加自定义布尔属性is_collision并设为true - 初始化时遍历目标图层的所有瓦片,生成对应的Rect对象存入碰撞列表,后续直接用该列表和玩家对象做碰撞检测即可
完整的带碰撞检测的代码示例:
import pygame import pytmx pygame.init() W, H = 800, 400 FPS = 60 win = pygame.display.set_mode((W, H), 0, 32) pygame.display.set_caption('tmx map with collision') # 加载地图 game_map = pytmx.load_pygame('map/map.tmx', pixelalpha=True) tile_width = game_map.tilewidth tile_height = game_map.tileheight # 生成碰撞列表 collision_rects = [] for layer in game_map.layers: # 这里用图层名判断,也可以换成自定义属性判断逻辑 if layer.name == 'collision': for x, y, gid in layer: if gid != 0: rect = pygame.Rect( x * tile_width, y * tile_height, tile_width, tile_height ) collision_rects.append(rect) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False win.fill((146, 244, 200)) # 绘制所有可见图层 for layer in game_map.visible_layers: for x, y, gid in layer: if gid == 0: continue tile = game_map.get_tile_image_by_gid(gid) if tile: win.blit(tile, (x * tile_width, y * tile_height)) # 调试用:可以把碰撞框绘制出来确认位置是否正确 for rect in collision_rects: pygame.draw.rect(win, (255,0,0), rect, 2) pygame.display.update() pygame.quit()
内容的提问来源于stack exchange,提问作者Tomoe
相关产品推荐
相关产品推荐

