From 928029e6e4bb2993be4b27d50ebc6efe467473ee Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 12 Apr 2023 19:53:12 +0900 Subject: [PATCH] BlockStats is upgraded to TileSurvey --- .../torvald/terrarum/blockstats/BlockStats.kt | 59 -------------- .../torvald/terrarum/blockstats/TileSurvey.kt | 78 +++++++++++++++++++ .../terrarum/modulebasegame/TerrarumIngame.kt | 4 +- .../terrarum/worlddrawer/FeaturesDrawer.kt | 26 +++++-- 4 files changed, 99 insertions(+), 68 deletions(-) delete mode 100644 src/net/torvald/terrarum/blockstats/BlockStats.kt create mode 100644 src/net/torvald/terrarum/blockstats/TileSurvey.kt diff --git a/src/net/torvald/terrarum/blockstats/BlockStats.kt b/src/net/torvald/terrarum/blockstats/BlockStats.kt deleted file mode 100644 index 59be109b9..000000000 --- a/src/net/torvald/terrarum/blockstats/BlockStats.kt +++ /dev/null @@ -1,59 +0,0 @@ -package net.torvald.terrarum.blockstats - -import com.jme3.math.FastMath -import net.torvald.terrarum.App -import net.torvald.terrarum.INGAME -import net.torvald.terrarum.Terrarum -import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE -import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF -import net.torvald.terrarum.gameitems.ItemID -import net.torvald.terrarum.modulebasegame.TerrarumIngame -import net.torvald.terrarum.worlddrawer.BlocksDrawer - -/** - * Created by minjaesong on 2016-02-01. - */ -object BlockStats { - - private val tilestat = HashMap() - - /** - * Update tile stats from tiles on screen - */ - fun update() { - tilestat.clear() - - // Get stats on no-zoomed screen area. In other words, will behave as if screen zoom were 1.0 - // no matter how the screen is zoomed. - val map = (INGAME.world) - val player = (Terrarum.ingame!! as TerrarumIngame).actorNowPlaying - if (player == null) return - - val renderWidth = FastMath.ceil(App.scr.wf) - val renderHeight = FastMath.ceil(App.scr.hf) - - val noZoomCameraX = Math.round(FastMath.clamp( - player.hitbox.centeredX.toFloat() - renderWidth / 2, TILE_SIZEF, map.width * TILE_SIZE - renderWidth - TILE_SIZEF)) - val noZoomCameraY = Math.round(FastMath.clamp( - player.hitbox.centeredY.toFloat() - renderHeight / 2, TILE_SIZEF, map.width * TILE_SIZE - renderHeight - TILE_SIZEF)) - - val for_x_start = noZoomCameraX / TILE_SIZE - val for_y_start = noZoomCameraY / TILE_SIZE - val for_y_end = BlocksDrawer.clampHTile(for_y_start + (renderHeight / TILE_SIZE) + 2) - val for_x_end = BlocksDrawer.clampWTile(for_x_start + (renderWidth / TILE_SIZE) + 2) - - for (y in for_y_start..for_y_end - 1) { - for (x in for_x_start..for_x_end - 1) { - val tileWall = map.getTileFromWall(x, y) - val tileTerrain = map.getTileFromTerrain(x, y) - tilestat[tileWall] = 1 + (tilestat[tileWall] ?: 0) - tilestat[tileTerrain] = 1 + (tilestat[tileTerrain] ?: 0) - } - } - } - - fun getCount(vararg tiles: ItemID): Int { - return tiles.fold(0) { acc, key -> acc + (tilestat[key] ?: 0) } - } - -} diff --git a/src/net/torvald/terrarum/blockstats/TileSurvey.kt b/src/net/torvald/terrarum/blockstats/TileSurvey.kt new file mode 100644 index 000000000..500313db9 --- /dev/null +++ b/src/net/torvald/terrarum/blockstats/TileSurvey.kt @@ -0,0 +1,78 @@ +package net.torvald.terrarum.blockstats + +import com.jme3.math.FastMath +import net.torvald.terrarum.App +import net.torvald.terrarum.INGAME +import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.gameworld.GameWorld +import net.torvald.terrarum.modulebasegame.TerrarumIngame +import kotlin.math.ceil +import kotlin.math.floor + +/** + * Created by minjaesong on 2016-02-01. + */ +object TileSurvey { + + data class SurveyProposal( + val surveyIdentifier: String, + val width: Int, + val height: Int, + val spatialGranularity: Int, // 1: survey every (w*h) tile, 2: survey every other (w*h/4) tile ... + val temporalGranularity: Int, // 1: survey every frame, 2: every other frame ... + val predicate: (GameWorld, Int, Int) -> Boolean + ) + + private val proposals = HashMap() + private val results = HashMap>() // (matching tiles/actually surveyed tiles) + + fun submitProposal(proposal: SurveyProposal) { + proposals[proposal.surveyIdentifier] = proposal + } + + fun withdrawProposal(surveyIdentifier: String) { + proposals.remove(surveyIdentifier) + results.remove(surveyIdentifier) + } + + /** + * Update tile stats from tiles on screen + */ + fun update() { + + // Get stats on no-zoomed screen area. In other words, will behave as if screen zoom were 1.0 + // no matter how the screen is zoomed. + val world = INGAME.world + val player = (Terrarum.ingame!! as TerrarumIngame).actorNowPlaying + if (player == null) return + + proposals.forEach { (_, proposal) -> + + if (INGAME.WORLD_UPDATE_TIMER % proposal.temporalGranularity == 0) { + val for_x_start = floor(player.intTilewiseHitbox.centeredX - proposal.width / 2.0).toInt() + val for_y_start = floor(player.intTilewiseHitbox.centeredY - proposal.height / 2.0).toInt() + val for_x_end = ceil(player.intTilewiseHitbox.centeredX + proposal.width / 2.0).toInt() + val for_y_end = ceil(player.intTilewiseHitbox.centeredY + proposal.height / 2.0).toInt() + + var akku = 0 + + for (y in for_y_start until for_y_end step proposal.spatialGranularity) { + for (x in for_x_start until for_x_end step proposal.spatialGranularity) { + if (proposal.predicate(world, x, y)) akku += 1 + } + } + + val surveyedTileCount = + (proposal.width * proposal.height) / (proposal.spatialGranularity * proposal.spatialGranularity) + val ratio = akku.toDouble() / surveyedTileCount + + results[proposal.surveyIdentifier] = ratio to akku + } + } + } + + fun getRawCount(surveyIdentifier: String) = results[surveyIdentifier]?.second + fun getRatio(surveyIdentifier: String) = results[surveyIdentifier]?.first + fun getRatioAndRawCount(surveyIdentifier: String) = results[surveyIdentifier] + +} diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index b834944a0..cc0d182ba 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -11,7 +11,7 @@ import net.torvald.terrarum.Terrarum.getWorldSaveFiledesc import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.blockproperties.BlockPropUtil -import net.torvald.terrarum.blockstats.BlockStats +import net.torvald.terrarum.blockstats.TileSurvey import net.torvald.terrarum.blockstats.MinimapComposer import net.torvald.terrarum.concurrent.ThreadExecutor import net.torvald.terrarum.console.AVTracker @@ -800,7 +800,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { WeatherMixer.update(delta, actorNowPlaying, world) } measureDebugTime("BlockStats.update") { - BlockStats.update() + TileSurvey.update() } // fill up visibleActorsRenderFront for wires but not on every update measureDebugTime("Ingame.FillUpWiresBuffer*") { diff --git a/src/net/torvald/terrarum/worlddrawer/FeaturesDrawer.kt b/src/net/torvald/terrarum/worlddrawer/FeaturesDrawer.kt index 0d72289a2..1c21e510b 100644 --- a/src/net/torvald/terrarum/worlddrawer/FeaturesDrawer.kt +++ b/src/net/torvald/terrarum/worlddrawer/FeaturesDrawer.kt @@ -9,7 +9,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF import net.torvald.terrarum.blendMul import net.torvald.terrarum.blendNormalStraightAlpha import net.torvald.terrarum.blockproperties.Block -import net.torvald.terrarum.blockstats.BlockStats +import net.torvald.terrarum.blockstats.TileSurvey import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.ui.Toolkit import kotlin.math.roundToInt @@ -42,6 +42,19 @@ object FeaturesDrawer { Block.SAND_DESERT , Block.SAND_RED) + init { + TileSurvey.submitProposal( + TileSurvey.SurveyProposal( + "basegame.FeaturesDrawer.coldTiles", 72, 48, 2, 2 + ) { world, x, y -> TILES_COLD.contains(world.getTileFromTerrain(x, y)) } + ) + TileSurvey.submitProposal( + TileSurvey.SurveyProposal( + "basegame.FeaturesDrawer.warmTiles", 72, 48, 2, 2 + ) { world, x, y -> TILES_WARM.contains(world.getTileFromTerrain(x, y)) } + ) + } + fun update(delta: Float) { } @@ -50,13 +63,12 @@ object FeaturesDrawer { * usually targeted for the environmental temperature (desert/winterland), hence the name. */ fun drawEnvOverlay(batch: SpriteBatch) { - val onscreen_tiles_max = FastMath.ceil(App.scr.height * App.scr.width / FastMath.sqr(TILE_SIZEF)) * 2 - val onscreen_tiles_cap = onscreen_tiles_max / 4f - val onscreen_cold_tiles = BlockStats.getCount(*TILES_COLD).toFloat() - val onscreen_warm_tiles = BlockStats.getCount(*TILES_WARM).toFloat() + val onscreen_tiles_cap = 0.3 + val onscreen_cold_tiles = (TileSurvey.getRatio("basegame.FeaturesDrawer.coldTiles") ?: 0.0).coerceAtMost(onscreen_tiles_cap) + val onscreen_warm_tiles = (TileSurvey.getRatio("basegame.FeaturesDrawer.warmTiles") ?: 0.0).coerceAtMost(onscreen_tiles_cap) - val colTemp_cold = colTempLinearFunc(onscreen_cold_tiles / onscreen_tiles_cap) - val colTemp_warm = colTempLinearFunc(-(onscreen_warm_tiles / onscreen_tiles_cap)) + val colTemp_cold = colTempLinearFunc((onscreen_cold_tiles / onscreen_tiles_cap).toFloat()) + val colTemp_warm = colTempLinearFunc(-(onscreen_warm_tiles / onscreen_tiles_cap).toFloat()) colTemp = colTemp_warm + colTemp_cold - ENV_COLTEMP_NOON val zoom = Terrarum.ingame?.screenZoom ?: 1f