libGDX实现精灵表纹理拆分算法异常问题求助
精灵表切割逻辑修复方案
你的代码核心问题是循环遍历子纹理索引时完全没有用x/y变量计算坐标,所有子纹理的坐标都写死为和spritesX/spritesY相关的常量,所以最终只会得到同一个位置的纹理区域。此外还有逻辑分支冗余、坐标规则适配错误、全局映射意外重置的问题,修复后的完整代码如下:
import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.TextureRegion import java.lang.Exception lateinit var AssetMap: MutableMap<String, Texture> // 初始化改为懒加载,避免每次加载精灵表清空之前的内容 lateinit var SheetAssets: MutableMap<String, MutableMap<String, TextureRegion>> object Assets { lateinit var fileHandle: FileHandle fun loadAssets() { loadAssets(DefaultAssetDirectory) } fun loadAssets(directory: String) { AssetMap = mutableMapOf() // 当前实现会在加载时重置映射 fileHandle = Gdx.files.local(directory) val fileList = fileHandle.list() for(file in fileList) { if(file.extension() == "png") try { AssetMap[file.nameWithoutExtension()] = Texture(directory+file.name()) } catch(e: Exception) { Gdx.app.error("Assets", "加载纹理失败: ${file.name()}", e) } } } /** * 适用于非常基础的精灵表 * 该函数无需传入名称列表,子纹理将按索引命名 * 函数默认从左上角(0,0)位置开始扫描 * @param directoryToSheet 精灵表的本地存储路径 * @param spaceBetweenX 仅为纹理之间的横向间隔,不包含纹理与边框的间隔 * @param spaceBetweenY 仅为纹理之间的纵向间隔,不包含纹理与边框的间隔 */ fun loadSheetAtlas(directoryToSheet: String, width: Int, height: Int, spaceBetweenX: Int, spaceBetweenY: Int, spritesX: Int, spritesY: Int) { loadSheetAtlas(directoryToSheet, null, width, height, spaceBetweenX, spaceBetweenY, spritesX, spritesY) } /** * 适用于非常基础的精灵表 * @param directoryToSheet 精灵表的本地存储路径 * @param names 子纹理名称列表,若为null则子纹理按索引命名 * @param spaceBetweenX 仅为纹理之间的横向间隔,不包含纹理与边框的间隔 * @param spaceBetweenY 仅为纹理之间的纵向间隔,不包含纹理与边框的间隔 */ fun loadSheetAtlas(directoryToSheet: String, names: List<String?>?, width: Int, height: Int, spaceBetweenX: Int, spaceBetweenY: Int, spritesX: Int, spritesY: Int) { // 仅在首次调用时初始化全局映射,避免清空之前加载的精灵表 if (!::SheetAssets.isInitialized) { SheetAssets = mutableMapOf() } val nameToConvert = Gdx.files.local(directoryToSheet).nameWithoutExtension() .replace(' ', '-') .lowercase() // 已加载过的精灵表直接跳过 if (SheetAssets.containsKey(nameToConvert)) return val sheet = Texture(directoryToSheet) val regionMap = mutableMapOf<String, TextureRegion>() var nameIndex = 0 for(y in 0 until spritesY) { for(x in 0 until spritesX) { val key = if (!names.isNullOrEmpty() && names[nameIndex] != null) { names[nameIndex]!! } else { nameIndex.toString() } // 计算子纹理坐标,适配libGDX纹理左下角为原点的规则 val xPos = x * (width + spaceBetweenX) // 从左上角开始计算,转换为libGDX的y坐标 val yPos = sheet.height - (y + 1) * height - y * spaceBetweenY regionMap[key] = TextureRegion(sheet, xPos, yPos, width, height) nameIndex++ } } SheetAssets[nameToConvert] = regionMap } }
关键修改说明
- 移除了冗余的
x == spritesX - 1分支逻辑,统一用循环变量计算坐标 - 横向坐标直接按
索引*(子纹理宽度+横向间隔)计算,符合边框无偏移的要求 - 纵向坐标适配libGDX左下角为原点的规则,转换了左上角排列的精灵表坐标
- 修复了每次调用
loadSheetAtlas都会清空所有已加载精灵表的问题 - 增加了异常日志输出,避免加载失败静默报错
内容的提问来源于stack exchange,提问作者random person
相关产品推荐
相关产品推荐

