如何根据周边瓦片自动显示对应图像?(Pygame实现)
Pygame瓦片地图自动匹配邻接瓦片图像实现方案
问题背景
我用Pygame开发瓦片地图,目前通过for循环绘制level数组中的瓦片:
level = [ ['1','1','1','1','1','1','1','1','1','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','1','1','1','0','0','0','1'], ['1','0','0','0','1','0','0','0','0','1'], ['1','0','0','0','1','1','0','0','0','1'], ['1','0','0','0','0','1','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','1','1','1','1','1','1','1','1','1'], ]
我有一张包含所有瓦片样式的PNG图,手动设置角落等瓦片显示的方式效率极低,修改地图后需要重新配置。想实现一种算法,让每个瓦片根据上下左右的邻接瓦片情况自动显示对应图像,比如左上角的瓦片能检测下方和右侧的瓦片,自动匹配正确的图像。
完整测试代码如下:
import pygame # Initialize Pygame pygame.init() # Set the size of the window size = (360, 360) screen = pygame.display.set_mode(size) # Set the title of the window pygame.display.set_caption("TILE MAP AAAaaAH") tilesize = 30 level = [ ['1','1','1','1','1','1','1','1','1','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','1','1','1','0','0','0','1'], ['1','0','0','0','1','0','0','0','0','1'], ['1','0','0','0','1','1','0','0','0','1'], ['1','0','0','0','0','1','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','1','1','1','1','1','1','1','1','1'], ] tiles = [] def build_level(): x = 0 y = 0 for row in level: y += 1 x = 0 for tile in row: x += 1 if tile == '1': build = pygame.Rect(x*tilesize, y*tilesize, tilesize, tilesize) tiles.append(build) if tile == '0': pass build_level() def draw_level(): for tile in tiles: pygame.draw.rect(screen, (50, 50, 50), tile) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Main Loop screen.fill((50, 50, 250)) draw_level() pygame.display.update() pygame.quit()
实现方案
核心思路
给每个瓦片生成一个邻接掩码,通过检测上下左右的瓦片是否为障碍物(这里是'1'),将检测结果转换为一个二进制数,用这个数值作为索引从瓦片集中选取对应图像。
每个方向对应二进制的一位:
- 上:对应二进制第4位(数值8)
- 右:对应二进制第3位(数值4)
- 下:对应二进制第2位(数值2)
- 左:对应二进制第1位(数值1)
组合后得到0-15的数值,对应16种基础瓦片状态,足够覆盖大部分地图场景。
修改后的完整代码
import pygame pygame.init() size = (360, 360) screen = pygame.display.set_mode(size) pygame.display.set_caption("Auto-Tile Map") tilesize = 30 level = [ ['1','1','1','1','1','1','1','1','1','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','1','1','1','0','0','0','1'], ['1','0','0','0','1','0','0','0','0','1'], ['1','0','0','0','1','1','0','0','0','1'], ['1','0','0','0','0','1','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','0','0','0','0','0','0','0','0','1'], ['1','1','1','1','1','1','1','1','1','1'], ] # 加载瓦片集(替换为你的瓦片图本地路径) # 假设瓦片集按4行4列排列,对应mask 0-15的顺序 tile_set = pygame.image.load("tile_set.png").convert_alpha() def get_tile_mask(row_idx, col_idx): """获取当前瓦片的邻接掩码,返回0-15的整数""" mask = 0 # 检测上方瓦片 if row_idx > 0 and level[row_idx-1][col_idx] == '1': mask |= 8 # 检测右侧瓦片 if col_idx < len(level[row_idx])-1 and level[row_idx][col_idx+1] == '1': mask |= 4 # 检测下方瓦片 if row_idx < len(level)-1 and level[row_idx+1][col_idx] == '1': mask |= 2 # 检测左侧瓦片 if col_idx > 0 and level[row_idx][col_idx-1] == '1': mask |= 1 return mask def draw_level(): for row_idx, row in enumerate(level): for col_idx, tile in enumerate(row): if tile == '1': mask = get_tile_mask(row_idx, col_idx) # 计算瓦片在集中的坐标 tile_x = (mask % 4) * tilesize tile_y = (mask // 4) * tilesize # 截取对应瓦片图像 tile_surface = tile_set.subsurface(pygame.Rect(tile_x, tile_y, tilesize, tilesize)) # 绘制到屏幕(对应原代码的坐标逻辑) screen.blit(tile_surface, ((col_idx+1)*tilesize, (row_idx+1)*tilesize)) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False screen.fill((50, 50, 250)) draw_level() pygame.display.update() pygame.quit()
关键说明
- 瓦片集适配:需将你的瓦片集按照mask值0-15的顺序排列(4行4列),如果瓦片集排列方式不同,调整
tile_x和tile_y的计算逻辑即可。 - 坐标调整:原代码中坐标从1开始计数,所以绘制时用
(col_idx+1)*tilesize对应原位置,若修改level的坐标逻辑,可直接使用col_idx*tilesize和row_idx*tilesize。 - 扩展优化:若需要支持斜向(四个角落)的瓦片检测,可在掩码中增加四位,扩展到256种状态,只需修改
get_tile_mask函数添加角落检测逻辑即可。
内容的提问来源于stack exchange,提问作者Xseis
相关产品推荐
相关产品推荐

