?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

import java.io.File
import java.util.*
import kotlin.collections.ArrayList

// gradlew desktop:dist for jar create in path ..../ desktop / build / libs
// автор тайледа 100% редактор делал изначально не для геймдэва - он не логичен пиздец !!!
// есть выделение части слоя, но его нельзя двигать блять !!! Нужно удалять выделение и вставлять куда требуется !!!!
// ятаворотибал
const val LEVEL_WIDTH = 16
const val LEVEL_HEIGHT = 12
@ExperimentalUnsignedTypes
class TiledConversion(val map: File, val dstSpriteStorage: String, val dstLevelsStorage: String) {

    val mapString = map.readText(Charsets.ISO_8859_1)

    val mapProperties = "(<map)\\s.+(>)?".toRegex().find(mapString)?.value ?: error("Wrong map properties.")
    val mapWidth =
        "(?<= width=\")\\d+(?=\")?".toRegex().find(mapProperties)?.value?.toInt() ?: error("Wrong map WIDTH:")
    val mapHeight =
        "(?<= height=\")\\d+(?=\")?".toRegex().find(mapProperties)?.value?.toInt() ?: error("Wrong map HEIGHT:")
    val columns = mapWidth / LEVEL_WIDTH
    val rows = mapHeight / LEVEL_HEIGHT
    val mapLine = columns * LEVEL_WIDTH


    val tilesId =
        "(?<=tile id=\")\\d+(?!\")?".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(mapString).toList()
            .map { it.value.toInt() }
    val tileset =
        "(?<=source=\")[a-zA-Z0-9_./]+(?!\")?".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(mapString).toList()
            .map { it.value }
    val mapData =
        "(?<=<data encoding=\"csv\">)[0-9,\\s]+(?=</data>)?".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(mapString)
            .toList().map { it.value.split(",").map { d -> d.trim().toInt() } }

    val wallsLayer = mapData[0]

    //    val objectsLayer = MutableList(mapData[1].size) { mapData[1][it] }
    val objectsLayer = mapData[1].toMutableList().map { it - 1 }

    val levelAsmData = StringBuilder()
    var levelAddressesOffset = 0
    val levelAddresses = StringBuilder("LEVELS_MAP:\tdw ")

    fun exec() {
        val spritesAsmData = StringBuilder()
        val spritesAddressesOffset = ArrayList<Int>()


        println("Tiles ID`s:")
        val indices = getIndices()
        indices.forEachIndexed { newId, arrayInt ->
            arrayInt.forEach { oldId ->
                Collections.replaceAll(objectsLayer, oldId, newId)
            }
        }
        prtLine()
        val names =
            "(?:../)\\S+(?=\"/>)".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(mapString).map { it.value }.toList()
        val labels = names.map {
            val r = it.split("/")
            r.last().toUpperCase().replace(".", "_")
        }
        var imgId = 0
        var offset = 0
        indices.forEachIndexed { id, arrayInt ->
            spritesAddressesOffset.add(offset)
            spritesAsmData.append("${labels[imgId]}_ID:\tequ $id\n")
            arrayInt.forEach { _ ->
//                val file = File(names[imgId]).readLines(Charsets.ISO_8859_1)
                val file = File(names[imgId]).readText(Charsets.ISO_8859_1).split("\n")
//                println(f.size)
                val width = file[1].toInt()
                val height = file[2].toInt()
                offset += (width / 8) * height
                val data = file[3].toByteArray(Charsets.ISO_8859_1).map { it.toUByte().inv() }.toString()
                    .replace("[\\[\\] ]+".toRegex(), "")
                spritesAsmData.append("${labels[imgId]}:\tdb $data\n")
                imgId++
            }
        }

        val spritesResult = StringBuilder()
        spritesResult.append(
            "SPRITE_MAP:\tdw ${
                spritesAddressesOffset.toString().replace("[\\[\\] ]+".toRegex(), "")
            }\n"
        ).append(spritesAsmData)
        println(spritesResult)
        prtLine()


        val layers = ArrayList<Pair<List<Int>, List<Int>>>()
        repeat(rows) { r ->
            repeat(columns) { c ->
//                val startLevelAddress = r * (mapWidth * LEVEL_HEIGHT) + c * LEVEL_WIDTH
//                val levelId = r * rows + c
                layers.add(
                    Pair(
                        cut(wallsLayer, mapWidth, c, r),
                        cut(objectsLayer, mapWidth, c, r)
                    )
                )
            }
        }

        // отбрасываем пустые уровни
        layers.filter { it.second.any { int -> int != -1 } }.forEach {
            levelAsmData.append(tiledConvertToASMFile(it.first, it.second))
        }


        val levelsResult = StringBuilder()
        levelsResult.append(levelAddresses.dropLast(1)).append("\nLEVELS_BEGIN:").append(levelAsmData)
        println(levelsResult)

        saveFile(dstSpriteStorage, spritesResult)
        saveFile(dstLevelsStorage, levelsResult)

    }

    //-----------------------------------------------------------

    private fun tiledConvertToASMFile(walls: List<Int>, objects: List<Int>): String {
        val wallsString = StringBuilder("\n\tdb ")
        val objectsString = StringBuilder("\n\tdb ")

        levelAddresses.append("$levelAddressesOffset,")
        repeat(24) { line ->
            var byte = 0
            var value = 32768
            repeat(8) { b ->
                val id = b + (line * 8)
                byte = if (walls[id] == 0) byte else byte or value
                value = value shr 1

                if (objects[id] != -1) {
                    objectsString.append("$id,${objects[id]},")     // -1 !?!
                    levelAddressesOffset += 2
                }

            }
            wallsString.append("${byte shr 8 and 255},")
        }
        objectsString.append("255")
        levelAddressesOffset += 24 + 1      // +1 =255 завершающий байт

        return "${wallsString.dropLast(1)}${objectsString}"
    }


    private fun getIndices(): ArrayList<ArrayList<Int>> {
        val indices = ArrayList<ArrayList<Int>>()
        val tileset = "(?<=<tileset).+(?=</tileset>)".toRegex(RegexOption.DOT_MATCHES_ALL).find(mapString)?.value
            ?: error("Tileset is empty !!!")

        // индексы из тайлсета, они отличаются от индексов карты - на карте эти индексы +1 (захуярить афтора Tiled map editor)
        val tileIds =
            "(?<=<tile id=\")\\d+(?=\">)".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(tileset).map { it.value.trim() }
                .toList()

        val tileNames =
            "(?<=source=\")\\S+(?=\")".toRegex(RegexOption.DOT_MATCHES_ALL).findAll(tileset).map { it.value.trim() }
                .toList()


        var preName: String? = null
//        var count = 0
        tileNames.forEachIndexed { id, name ->
            val n = "\\S+(?=_\\d+)".toRegex().find(name)?.value ?: name
            if (n != preName) {
                indices.add(arrayListOf())
                preName = n
//                println(count++)
//                println("$preName, $n")
            }
            indices.last().add(tileIds[id].trimIndent().toInt())
        }

        indices.forEachIndexed { id, i ->
            println("$id: ${i.toString()}")
        }
        return indices
    }

    // вырезает (чанк) уровень 16х12 из карты
    private fun cut(
        src: List<Int>, srcWidth: Int, x: Int, y: Int
    ): List<Int> {
        val a = ArrayList<Int>()
        val id = y * (srcWidth * LEVEL_HEIGHT) + x * LEVEL_WIDTH
        repeat(LEVEL_HEIGHT) { h ->
            repeat(LEVEL_WIDTH) { w ->
                a.add(src[id + h * srcWidth + w])
            }
        }
        return a
    }

    private fun prtLine() {
        println("----------------------------------------------------------------------------------------------")
    }

    private fun saveFile(fileName: String, data: StringBuilder) = File(fileName).writeText(data.toString())

}