我需要帮助来实现一种算法,该算法将从 libGDX 中的纹理解析特定纹理

I need help on implementing an algorithm that will parse specific textures from a texture in libGDX

考虑:

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
import kotlin.math.floor

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 = mapOf<String, Texture>().toMutableMap() // Current implementation resets the map at load
        fileHandle = Gdx.files.local(directory)
        var fileList = fileHandle.list()
        for(file in fileList)
        {
            if(file.extension() == "png")
                try
                {
                    AssetMap[file.nameWithoutExtension()] = Texture(directory+file.name())
                }
                catch(e: Exception) {

                }
        }
    }

    /**
     * For very basic sprite sheets.
     * Since you won't input a name List in this function, they will be named by their index.
     * The function will probably start scanning from top left 0,0
     * @param directoryToSheet local directory to sheet
     * @param spaceBetweenX only the space between textures, doesnt work forspace between the texture and the border
     * @param spaceBetweenY only the space between textures, doesnt work forspace between the texture and the border
     */
    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)
    }

    /**
     * For very basic sprite sheets.
     * Since you won't input a name List in this function, they will be named by their index.
     * @param directoryToSheet local directory to sheet
     * @param names if this is null, they will be named by their index
     * @param spaceBetweenX only the space between textures, doesnt work forspace between the texture and the border
     * @param spaceBetweenY only the space between textures, doesnt work forspace between the texture and the border
     */
    fun loadSheetAtlas(directoryToSheet: String, names: List<String?>?, width: Int, height: Int, spaceBetweenX: Int, spaceBetweenY: Int, spritesX: Int, spritesY: Int)
    {
        SheetAssets = mutableMapOf<String, MutableMap<String,TextureRegion>?>()
        var nameToConvert = Gdx.files.local(directoryToSheet).nameWithoutExtension()
        nameToConvert = nameToConvert.replace(' ', '-').toLowerCase()
        var sheet = Texture(directoryToSheet)
        var nameIndex = 0
        if(!SheetAssets.keys.contains(nameToConvert)) // To see if we have parsed it already
        {
            SheetAssets[nameToConvert] = mutableMapOf<String, TextureRegion>()
            for(x in 0 until spritesX)
            {
                for(y in 0 until spritesY) // When I put a -1 to spritesX/Y, the keycount becomes 121 for 12,12?
                {   // I check for if 'names' is null every single loop. It can be optimised to check for once, but that'd be premature optimisation
                    var keyToAdd = if((names != null) && (names[nameIndex] != null) ) names[nameIndex]!! else nameIndex.toString()
                    if(x == spritesX - 1)
                    {
                        var textureToAdd = TextureRegion(sheet,
                            ((spritesX+spaceBetweenX))-spaceBetweenX,
                            ((spritesY+spaceBetweenY))-spaceBetweenY,
                            width,height)
                        SheetAssets[nameToConvert]!![keyToAdd] = textureToAdd
                    }
                    else // These will work if textures use bottom left origin point
                    {
                        var textureToAdd = TextureRegion(sheet,  // These don’t work. Continue from here
                            ((spritesX+spaceBetweenX)*spritesX),
                            ((spritesY+spaceBetweenY)*spritesY),
                            width,height)
                        SheetAssets[nameToConvert]!![keyToAdd] = textureToAdd
                    }
                    nameIndex++
                }
            }
        }
    }
}

这是我写的代码。由于某种原因,它仅 returns 来自整个纹理中特定区域的特定纹理。但是,宽度和高度是正确的。

现在解释一下这个问题,基本上可以解决为xPos = texture.width / texture size % texture size something。但这里的问题是存在抵消。在纹理之间偏移并且绝对不在纹理和边界之间。你可以在上面看到我的代码。我尝试添加偏移量、减去偏移量等,但它似乎不起作用...有帮助吗?

此外,对于当前的实现,可变内部唯一的东西是在 144,144 内找到的 textureRegion,宽度:16,height:16 originpoint:topleft 的 spritesheet

我觉得这叫 spritesheet cutting 或者 spritesheet cutter。

代码说明

根据您的解释,这是我能做的最好的。我认为您将如何定义区域过于复杂化。这符合你的描述。没有理由将最后一行与其余行区别对待。

您还应该将 SheetAssets 设为 val,而不是每次调用此函数时都重新定义的 lateinit var。那就是泄漏所有旧纹理并使它们无法访问。

并且我在早期 return 中使用了 if 语句来减少嵌套代码。我使用 getOrPut?: 来消除一些多余的空断言。

val SheetAssets = mutableMapOf<String, MutableMap<String,TextureRegion>>()

//...

fun loadSheetAtlas(directoryToSheet: String, names: List<String?>?, width: Int, height: Int, spaceBetweenX: Int, spaceBetweenY: Int, spritesX: Int, spritesY: Int)
{
    val nameToConvert = Gdx.files.local(directoryToSheet).nameWithoutExtension()
        .replace(' ', '-').toLowerCase()
    if (nameToConvert in SheetAssets.keys) {
        return
    }
    val sheet = Texture(directoryToSheet)
    var nameIndex = 0
    for(x in 0 until spritesX)
    {
        for(y in 0 until spritesY)
        {   
            val keyToAdd = names?.get(nameIndex) ?: nameIndex.toString()            
            val outMap = SheetAssets.getOrPut(nameToConvert) { mutableMapOf() }
            outMap[keyToAdd] = TextureRegion(
                sheet,
                x * (spaceBetweenX + width),
                y * (spaceBetweenY + height),
                width,
                height
            )
            nameIndex++
        }
    }

}