You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据周边瓦片自动显示对应图像?(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()

关键说明

  1. 瓦片集适配:需将你的瓦片集按照mask值0-15的顺序排列(4行4列),如果瓦片集排列方式不同,调整tile_x和tile_y的计算逻辑即可。
  2. 坐标调整:原代码中坐标从1开始计数,所以绘制时用(col_idx+1)*tilesize对应原位置,若修改level的坐标逻辑,可直接使用col_idx*tilesize和row_idx*tilesize。
  3. 扩展优化:若需要支持斜向(四个角落)的瓦片检测,可在掩码中增加四位,扩展到256种状态,只需修改get_tile_mask函数添加角落检测逻辑即可。

内容的提问来源于stack exchange,提问作者Xseis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:01:00