From cd97b5c4ab0355e3713dbbd8a12a225126fd11ce Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 8 Mar 2019 18:49:38 +0900 Subject: [PATCH] rudimentary minimap draw only --- src/net/torvald/terrarum/GdxColorMap.kt | 18 ++++- .../terrarum/blockstats/MinimapComposer.kt | 77 ++++++++++++++++--- .../modulebasegame/ui/UIInventoryFull.kt | 9 ++- .../terrarum/worlddrawer/BlocksDrawerNew.kt | 34 +------- .../terrarum/worlddrawer/CreateTileAtlas.kt | 68 ++++++++++++++++ 5 files changed, 160 insertions(+), 46 deletions(-) diff --git a/src/net/torvald/terrarum/GdxColorMap.kt b/src/net/torvald/terrarum/GdxColorMap.kt index 8ea289eb8..f03e63084 100644 --- a/src/net/torvald/terrarum/GdxColorMap.kt +++ b/src/net/torvald/terrarum/GdxColorMap.kt @@ -12,6 +12,8 @@ import javax.naming.OperationNotSupportedException class GdxColorMap { constructor(imageFile: FileHandle) { + AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}") + val pixmap = Pixmap(imageFile) width = pixmap.width height = pixmap.height @@ -21,13 +23,21 @@ class GdxColorMap { pixmap.getPixel(it % pixmap.width, it / pixmap.width) } - - AppLoader.printdbg(this, "Loading colormap from ${imageFile.name()}; PixmapFormat: ${pixmap.format}; Dimension: $width x $height") - - pixmap.dispose() } + constructor(pixmap: Pixmap, disposePixmap: Boolean = true) { + width = pixmap.width + height = pixmap.height + is2D = pixmap.height > 1 + + data = kotlin.IntArray(pixmap.width * pixmap.height) { + pixmap.getPixel(it % pixmap.width, it / pixmap.width) + } + + if (disposePixmap) pixmap.dispose() + } + constructor(color: Color) { data = intArrayOf(color.toIntBits()) width = 1 diff --git a/src/net/torvald/terrarum/blockstats/MinimapComposer.kt b/src/net/torvald/terrarum/blockstats/MinimapComposer.kt index d56161686..f4b2da5fa 100644 --- a/src/net/torvald/terrarum/blockstats/MinimapComposer.kt +++ b/src/net/torvald/terrarum/blockstats/MinimapComposer.kt @@ -1,12 +1,16 @@ package net.torvald.terrarum.blockstats -import com.badlogic.gdx.Gdx -import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.utils.GdxRuntimeException +import com.badlogic.gdx.utils.Queue import net.torvald.terrarum.AppLoader +import net.torvald.terrarum.AppLoader.printdbg +import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.gameworld.GameWorld -import net.torvald.terrarum.worlddrawer.toRGBA +import net.torvald.terrarum.worlddrawer.BlocksDrawer +import net.torvald.terrarum.worlddrawer.CreateTileAtlas object MinimapComposer { @@ -32,7 +36,6 @@ object MinimapComposer { } var tempTex = Texture(1,1,Pixmap.Format.RGBA8888) - val minimap = Pixmap(Gdx.files.internal("./assets/testimage.png")) // total size of the minimap. Remember: textures can be mosaic-ed to display full map. var totalWidth = 0 var totalHeight = 0 @@ -45,14 +48,20 @@ object MinimapComposer { const val LIVETILE_SIZE = 64 const val DISPLAY_CANVAS_WIDTH = 2048 const val DISPLAY_CANVAS_HEIGHT = 1024 + val minimap = Pixmap(DISPLAY_CANVAS_WIDTH, DISPLAY_CANVAS_HEIGHT, Pixmap.Format.RGBA8888) const val TILES_IN_X = DISPLAY_CANVAS_WIDTH / LIVETILE_SIZE const val TILES_IN_Y = DISPLAY_CANVAS_HEIGHT / LIVETILE_SIZE - private val displayPixmap = Pixmap(DISPLAY_CANVAS_WIDTH, DISPLAY_CANVAS_HEIGHT, Pixmap.Format.RGBA8888) // numbers inside of it will change a lot - private val tileSlot = Array(TILES_IN_Y) { IntArray(TILES_IN_X) } + private val tilemap = Array(TILES_IN_Y) { y -> IntArray(TILES_IN_X) { x -> y * TILES_IN_X + x } } // pixmaps inside of this will never be redefined private val liveTiles = Array(TILES_IN_X * TILES_IN_Y) { Pixmap(LIVETILE_SIZE, LIVETILE_SIZE, Pixmap.Format.RGBA8888) } + // indices are exacly the same as liveTiles + private val liveTilesMeta = Array(TILES_IN_X * TILES_IN_Y) { LiveTileMeta(revalidate = true) } + private val updaterQueue = Queue(TILES_IN_X * TILES_IN_Y * 2) + private var currentThreads = Array(maxOf(1, Terrarum.THREADS.times(2).div(3))) { + Thread() + } init { totalWidth = minimap.width @@ -60,24 +69,74 @@ object MinimapComposer { } fun update() { + // make the queueing work + // enqueue first + for (y in 0 until tilemap.size) { + for (x in 0 until tilemap[0].size) { + if (liveTilesMeta[tilemap[y][x]].revalidate) { + liveTilesMeta[tilemap[y][x]].revalidate = false + updaterQueue.addLast(createUpdater(x, y)) + printdbg(this, "Queueing tilemap update ($x,$y); queue size now: ${updaterQueue.size}") + } + } + } + // consume the queue + for (k in 0 until currentThreads.size) { + if (currentThreads[k].state == Thread.State.TERMINATED && !updaterQueue.isEmpty) { + currentThreads[k] = Thread(updaterQueue.removeFirst(), "MinimapLivetilePainter") + printdbg(this, "Consuming from queue; queue size now: ${updaterQueue.size}") + } + if (currentThreads[k].state == Thread.State.NEW) { + currentThreads[k].start() + } + } + + + // assign tiles to the tilemap + // TODO } + fun renderToBackground() { + for (y in 0 until TILES_IN_Y) { + for (x in 0 until TILES_IN_X) { + minimap.drawPixmap(liveTiles[tilemap[y][x]], x * LIVETILE_SIZE, y * LIVETILE_SIZE) + } + } + } + + private val HQRNG = net.torvald.random.HQRNG() + private fun createUpdater(tileSlotIndexX: Int, tileSlotIndexY: Int) = Runnable { - val pixmap = liveTiles[tileSlot[tileSlotIndexY][tileSlotIndexX]] + val pixmap = liveTiles[tilemap[tileSlotIndexY][tileSlotIndexX]] val topLeftX = topLeftCoordX + LIVETILE_SIZE * tileSlotIndexX val topLeftY = topLeftCoordY + LIVETILE_SIZE * tileSlotIndexY for (y in topLeftY until topLeftY + LIVETILE_SIZE) { for (x in if (tileSlotIndexY >= TILES_IN_X / 2) (topLeftX + LIVETILE_SIZE - 1) downTo topLeftX else topLeftX until topLeftX + LIVETILE_SIZE) { - val color = Color.WHITE // TODO - pixmap.drawPixel(x - topLeftX, y - topLeftY, color.toRGBA()) + val tileTerr = world.getTileFromTerrain(x, y) ?: throw Error("OoB: $x, $y") + val wallTerr = world.getTileFromWall(x, y) ?: Block.AIR + val colTerr = CreateTileAtlas.terrainTileColourMap.get(tileTerr % 16, tileTerr / 16) + val colWall = CreateTileAtlas.terrainTileColourMap.get(wallTerr % 16, wallTerr / 16).mul(BlocksDrawer.wallOverlayColour) + + if (colTerr.a < 1f) { + pixmap.setColor(colWall) + pixmap.drawPixel(x - topLeftX, y - topLeftY) + } + pixmap.setColor(colTerr) + pixmap.drawPixel(x - topLeftX, y - topLeftY) } } } fun dispose() { liveTiles.forEach { it.dispose() } + minimap.dispose() + try { + tempTex.dispose() + } + catch (e: GdxRuntimeException) {} } + private data class LiveTileMeta(var revalidate: Boolean) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryFull.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryFull.kt index e08453667..3a99e10ac 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryFull.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryFull.kt @@ -216,6 +216,10 @@ class UIInventoryFull( transitionalUpdateUIs.forEach { it.update(delta) } + if (currentScreen > 1f + epsilon) { + MinimapComposer.setWorld(Terrarum.ingame!!.world) + MinimapComposer.update() + } } private val gradStartCol = Color(0x404040_60) @@ -393,6 +397,9 @@ class UIInventoryFull( // render minimap batch.end() + + MinimapComposer.renderToBackground() + minimapFBO.inAction(minimapCamera, batch) { // whatever. MinimapComposer.tempTex.dispose() @@ -421,7 +428,7 @@ class UIInventoryFull( batch.begin() - //Terrarum.fontSmallNumbers.draw(batch, "$minimapPanX, $minimapPanY; x$minimapZoom", 10f, 10f) + Terrarum.fontSmallNumbers.draw(batch, "$minimapPanX, $minimapPanY; x$minimapZoom", minimapScrOffX + (Terrarum.WIDTH - MINIMAP_WIDTH) / 2, -10f + itemList.posY) batch.projectionMatrix = camera.combined diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt index 58eff3e09..f8a0aa903 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt @@ -129,43 +129,13 @@ internal object BlocksDrawer { printdbg(this, "Making terrain and wall item textures...") - // create item_wall images - fun maskTypetoTileIDForItemImage(maskType: Int) = when(maskType) { - CreateTileAtlas.RenderTag.MASK_47 -> 17 - CreateTileAtlas.RenderTag.MASK_PLATFORM -> 7 - else -> 0 - } - - val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) - val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) - - CreateTileAtlas.tags.toMap().forEach { t, u -> - val tilePosFromAtlas = u.tileNumber + maskTypetoTileIDForItemImage(u.maskType) - val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE - val srcY = (tilePosFromAtlas / TILES_IN_X) * TILE_SIZE - val destX = (t % 16) * TILE_SIZE - val destY = (t / 16) * TILE_SIZE - itemTerrainPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) - itemWallPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) - } - // darken things for the wall - for (y in 0 until itemWallPixmap.height) { - for (x in 0 until itemWallPixmap.width) { - val c = Color(itemWallPixmap.getPixel(x, y)).mulAndAssign(wallOverlayColour).toRGBA() - itemWallPixmap.drawPixel(x, y, c) - } - } // test print //PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/terrainitem.tga"), itemTerrainPixmap, false) - val itemTerrainTexture = Texture(itemTerrainPixmap) - val itemWallTexture = Texture(itemWallPixmap) - itemTerrainPixmap.dispose() - itemWallPixmap.dispose() - tileItemTerrain = TextureRegionPack(itemTerrainTexture, TILE_SIZE, TILE_SIZE) - tileItemWall = TextureRegionPack(itemWallTexture, TILE_SIZE, TILE_SIZE) + tileItemTerrain = TextureRegionPack(CreateTileAtlas.itemTerrainTexture, TILE_SIZE, TILE_SIZE) + tileItemWall = TextureRegionPack(CreateTileAtlas.itemWallTexture, TILE_SIZE, TILE_SIZE) diff --git a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt index 7f5bc8112..fdd9001cb 100644 --- a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt +++ b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt @@ -4,11 +4,14 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.utils.GdxRuntimeException +import net.torvald.terrarum.GdxColorMap import net.torvald.terrarum.ModMgr import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.gameworld.GameWorld +import net.torvald.terrarum.mulAndAssign import net.torvald.terrarum.toInt import kotlin.math.roundToInt @@ -35,6 +38,9 @@ object CreateTileAtlas { lateinit var atlasWinter: Pixmap lateinit var atlasSpring: Pixmap lateinit var atlasFluid: Pixmap + lateinit var itemTerrainTexture: Texture + lateinit var itemWallTexture: Texture + lateinit var terrainTileColourMap: GdxColorMap internal lateinit var tags: HashMap private set private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) // 'update' block @@ -176,6 +182,68 @@ object CreateTileAtlas { fluidMasterPixmap.dispose() + // create item_wall images + + fun maskTypetoTileIDForItemImage(maskType: Int) = when(maskType) { + CreateTileAtlas.RenderTag.MASK_47 -> 17 + CreateTileAtlas.RenderTag.MASK_PLATFORM -> 7 + else -> 0 + } + + val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) + val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) + val terrainColormapPixmap = Pixmap(16, TILES_IN_X, Pixmap.Format.RGBA8888) + + CreateTileAtlas.tags.toMap().forEach { t, u -> + val tilePosFromAtlas = u.tileNumber + maskTypetoTileIDForItemImage(u.maskType) + val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE + val srcY = (tilePosFromAtlas / TILES_IN_X) * TILE_SIZE + val destX = (t % 16) * TILE_SIZE + val destY = (t / 16) * TILE_SIZE + itemTerrainPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) + itemWallPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) + } + // darken things for the wall + for (y in 0 until itemWallPixmap.height) { + for (x in 0 until itemWallPixmap.width) { + val c = Color(itemWallPixmap.getPixel(x, y)).mulAndAssign(BlocksDrawer.wallOverlayColour).toRGBA() + itemWallPixmap.drawPixel(x, y, c) + } + } + // create terrain colourmap + val pxCount = TILE_SIZE * TILE_SIZE + for (id in 0 until BlockCodex.MAX_TERRAIN_TILES) { + val tx = (id % 16) * TILE_SIZE + val ty = (id / 16) * TILE_SIZE + var r = 0; var g = 0; var b = 0; var a = 0 + // average out the whole block + for (y in ty until ty + TILE_SIZE) { + for (x in tx until tx + TILE_SIZE) { + val data = itemTerrainPixmap.getPixel(x, y) + r += (data ushr 24) and 255 + g += (data ushr 16) and 255 + b += (data ushr 8) and 255 + a += data and 255 + } + } + + terrainColormapPixmap.drawPixel(tx / TILE_SIZE, ty / TILE_SIZE, + (r / pxCount).shl(24) or + (g / pxCount).shl(16) or + (b / pxCount).shl(8) or + (a / pxCount) + ) + } + + //PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/terrain_colormap.tga"), terrainColormapPixmap, false) + //PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/terrainitem.tga"), itemTerrainPixmap, false) + + terrainTileColourMap = GdxColorMap(terrainColormapPixmap) + itemTerrainTexture = Texture(itemTerrainPixmap) + itemWallTexture = Texture(itemWallPixmap) + itemTerrainPixmap.dispose() + itemWallPixmap.dispose() + initialised = true } }