我需要帮助来实现一种算法,该算法将从 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++
}
}
}
考虑:
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++
}
}
}