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

使用Tiled与Pygame加载精灵表时地图旋转翻转问题求助

地图加载旋转翻转与精灵表错误修复

问题描述

用Tiled生成4个CSV格式游戏地图文件,加载基础层(草地、泥土等)时地图旋转翻转,完全无法识别,同时精灵表加载的图像不正确,调整变量后仍未解决。

相关截图

  • 预期地图效果:
    不含植被的游戏地图
  • 实际运行效果:
    运行效果截图
  • 使用的精灵表:
    精灵表截图

原代码

import pygame,sys
from pygame.locals import *
import csv

running = True
pygame.init()
screen = pygame.display.set_mode((1280, 900))

def load_sprite_sheet(x_range, y_range, sprite_w, sprite_h):
    x_coord = 16 * x_range
    y_coord = 16 * y_range
    width = sprite_w
    height = sprite_h

    sheet = pygame.image.load("assets/TileMap/tilemap_packed.png").convert_alpha()
    single_image = sheet.subsurface((x_coord, y_coord, width, height))
    print(x_coord, y_coord)

    return single_image

grass_layout = "assets/TileMap/layout_grass.csv"

grasses = {
    "0": load_sprite_sheet(0, 0, 16, 16),
    "1": load_sprite_sheet(1, 0, 16, 16),
    "3": load_sprite_sheet(2, 0, 16, 16),
    "12": load_sprite_sheet(0, 1, 16, 16),
    "13": load_sprite_sheet(1, 1, 16, 16),
    "14": load_sprite_sheet(2, 1, 16, 16),
    "24": load_sprite_sheet(0, 2, 16, 16),
    "25": load_sprite_sheet(1, 2, 16, 16),
    "26": load_sprite_sheet(2, 2, 16, 16),
    "36": load_sprite_sheet(0, 3, 16, 16),
    "37": load_sprite_sheet(1, 3, 16, 16),
    "38": load_sprite_sheet(2, 3, 16, 16),
    "39": load_sprite_sheet(3, 3, 16, 16),
    "40": load_sprite_sheet(4, 3, 16, 16),
    "41": load_sprite_sheet(5, 3, 16, 16),
    "42": load_sprite_sheet(6, 3, 16, 16),
    "43": load_sprite_sheet(7, 3, 16, 16),
}

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            pygame.quit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
                pygame.quit()

    screen.fill('BLUE')

    with open(grass_layout, 'r') as csv_file:
        grasses_map = csv.reader(csv_file)
        for x_index, row in enumerate(grasses_map, 0):
            for y_index, col in enumerate(row, 0):
                if col in grasses.keys():
                    screen.blit(grasses[col], (x_index * 16, y_index * 16))

    pygame.display.update()

问题分析与修复

1. 地图旋转翻转问题

原因:Tiled导出的CSV按行从上到下存储地图,每行对应地图的横向一行;但原代码把行索引当作x坐标、列索引当作y坐标绘制,直接导致地图旋转90度,同时颠倒了横向顺序。

修复方法:将行索引对应y轴坐标,列索引对应x轴坐标,修正绘制逻辑:

with open(grass_layout, 'r') as csv_file:
    grasses_map = csv.reader(csv_file)
    # 行索引对应y轴,列索引对应x轴
    for y_index, row in enumerate(grasses_map):
        for x_index, col in enumerate(row):
            if col in grasses:
                screen.blit(grasses[col], (x_index * 16, y_index * 16))

2. 精灵表加载错误问题

原因:从精灵表截图和ID映射来看,Tiled的tile ID规则是 ID = 行号 * 每行tile数量 + 列号(这里每行有12个tile,所以ID间隔为12),你的映射逻辑本身正确,但存在两个潜在问题:

  • 部分tile ID未在grasses字典中定义,导致对应位置无法渲染;
  • 若精灵表存在内边距/外边距,x_coord和y_coord的计算需要额外加上间距值。

修复建议:

  • 检查Tiled导出设置,确保CSV的tile ID从0开始,且与精灵表排列顺序一致;
  • 若精灵表有间距,修改load_sprite_sheet函数加入间距计算(比如每个tile间有2像素间距,就把x_coord = 16 * x_range + 2 * x_range);
  • 补全所有需要用到的tile ID映射,避免遗漏导致的空白。

修改后的完整代码

import pygame,sys
from pygame.locals import *
import csv

running = True
pygame.init()
screen = pygame.display.set_mode((1280, 900))

def load_sprite_sheet(x_range, y_range, sprite_w, sprite_h):
    x_coord = 16 * x_range
    y_coord = 16 * y_range
    width = sprite_w
    height = sprite_h

    sheet = pygame.image.load("assets/TileMap/tilemap_packed.png").convert_alpha()
    single_image = sheet.subsurface((x_coord, y_coord, width, height))
    return single_image

grass_layout = "assets/TileMap/layout_grass.csv"

grasses = {
    "0": load_sprite_sheet(0, 0, 16, 16),
    "1": load_sprite_sheet(1, 0, 16, 16),
    "2": load_sprite_sheet(2, 0, 16, 16),  # 补全遗漏的ID
    "3": load_sprite_sheet(3, 0, 16, 16),
    "12": load_sprite_sheet(0, 1, 16, 16),
    "13": load_sprite_sheet(1, 1, 16, 16),
    "14": load_sprite_sheet(2, 1, 16, 16),
    "24": load_sprite_sheet(0, 2, 16, 16),
    "25": load_sprite_sheet(1, 2, 16, 16),
    "26": load_sprite_sheet(2, 2, 16, 16),
    "36": load_sprite_sheet(0, 3, 16, 16),
    "37": load_sprite_sheet(1, 3, 16, 16),
    "38": load_sprite_sheet(2, 3, 16, 16),
    "39": load_sprite_sheet(3, 3, 16, 16),
    "40": load_sprite_sheet(4, 3, 16, 16),
    "41": load_sprite_sheet(5, 3, 16, 16),
    "42": load_sprite_sheet(6, 3, 16, 16),
    "43": load_sprite_sheet(7, 3, 16, 16),
}

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            pygame.quit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
                pygame.quit()

    screen.fill('BLUE')

    with open(grass_layout, 'r') as csv_file:
        grasses_map = csv.reader(csv_file)
        for y_index, row in enumerate(grasses_map):
            for x_index, col in enumerate(row):
                if col in grasses:
                    screen.blit(grasses[col], (x_index * 16, y_index * 16))

    pygame.display.update()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 03:09:56