Very buggy map drawing
This commit is contained in:
parent
4b07ce505f
commit
9c65627445
4 changed files with 99 additions and 11 deletions
|
|
@ -23,6 +23,7 @@ import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableFloatStateOf
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -72,6 +73,8 @@ class MainActivity : ComponentActivity() {
|
||||||
@Composable
|
@Composable
|
||||||
fun Main(vm: TileViewModel = viewModel()) {
|
fun Main(vm: TileViewModel = viewModel()) {
|
||||||
val sliderValue = rememberSaveable { mutableFloatStateOf(1F) }
|
val sliderValue = rememberSaveable { mutableFloatStateOf(1F) }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val tileContainer = TileContainer(vm, coroutineScope)
|
||||||
KtHeightMapTheme {
|
KtHeightMapTheme {
|
||||||
Box(modifier = Modifier.background(color = colorScheme.background)) {
|
Box(modifier = Modifier.background(color = colorScheme.background)) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -84,6 +87,7 @@ fun Main(vm: TileViewModel = viewModel()) {
|
||||||
gridColor = colorScheme.primary,
|
gridColor = colorScheme.primary,
|
||||||
backColor = colorScheme.background,
|
backColor = colorScheme.background,
|
||||||
scale = sliderValue,
|
scale = sliderValue,
|
||||||
|
tileContainer = tileContainer,
|
||||||
modifier = Modifier.padding(innerPadding),
|
modifier = Modifier.padding(innerPadding),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package com.mirenkov.ktheightmap
|
||||||
|
|
||||||
import androidx.compose.foundation.Canvas
|
import androidx.compose.foundation.Canvas
|
||||||
import androidx.compose.foundation.gestures.detectDragGestures
|
import androidx.compose.foundation.gestures.detectDragGestures
|
||||||
import androidx.compose.foundation.gestures.rememberTransformableState
|
|
||||||
import androidx.compose.foundation.gestures.transformable
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableFloatState
|
import androidx.compose.runtime.MutableFloatState
|
||||||
|
|
@ -13,6 +11,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
|
||||||
|
|
@ -21,6 +20,7 @@ fun MapCanvas(
|
||||||
backColor: Color,
|
backColor: Color,
|
||||||
gridColor: Color,
|
gridColor: Color,
|
||||||
scale: MutableFloatState,
|
scale: MutableFloatState,
|
||||||
|
tileContainer: TileContainer,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val offsetX = rememberSaveable { mutableFloatStateOf(0F) }
|
val offsetX = rememberSaveable { mutableFloatStateOf(0F) }
|
||||||
|
|
@ -40,25 +40,43 @@ fun MapCanvas(
|
||||||
size = size
|
size = size
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val tileOffsetX = offsetX.floatValue.toInt() / TILE_SIZE.toInt()
|
||||||
|
val tileOffsetY = offsetY.floatValue.toInt() / TILE_SIZE.toInt()
|
||||||
|
|
||||||
val strippedOffsetX = offsetX.floatValue % TILE_SIZE
|
val strippedOffsetX = offsetX.floatValue % TILE_SIZE
|
||||||
val strippedOffsetY = offsetY.floatValue % TILE_SIZE
|
val strippedOffsetY = offsetY.floatValue % TILE_SIZE
|
||||||
|
|
||||||
val level = scale.floatValue.toInt()
|
val level = scale.floatValue.toInt()
|
||||||
val strippedScale = scale.floatValue + 1 - level
|
|
||||||
val actualTileSize = TILE_SIZE * strippedScale
|
|
||||||
|
|
||||||
val offset = Offset(strippedOffsetX, strippedOffsetY)
|
val offset = Offset(strippedOffsetX, strippedOffsetY)
|
||||||
val grid = size / actualTileSize
|
|
||||||
|
val grid = size / TILE_SIZE
|
||||||
|
|
||||||
val gridWidth = grid.width.toInt()
|
val gridWidth = grid.width.toInt()
|
||||||
val gridHeight = grid.height.toInt()
|
val gridHeight = grid.height.toInt()
|
||||||
|
|
||||||
|
val tiles = tileContainer.getTiles(tileOffsetX, tileOffsetY, tileOffsetX + gridWidth, tileOffsetY + gridHeight, level)
|
||||||
|
|
||||||
for (cellX in 0 .. gridWidth + 2) {
|
for (cellX in 0 .. gridWidth + 2) {
|
||||||
val offsetX = actualTileSize * (cellX - 1)
|
val tileX = tileOffsetX + cellX
|
||||||
|
val offsetX = TILE_SIZE * (cellX - 1)
|
||||||
for (cellY in 0 .. gridHeight + 2) {
|
for (cellY in 0 .. gridHeight + 2) {
|
||||||
val offsetY = actualTileSize * (cellY - 1)
|
val tileY = tileOffsetY + cellY
|
||||||
|
val offsetY = TILE_SIZE * (cellY - 1)
|
||||||
|
|
||||||
|
val bitmap = tiles.find { it.x == tileX && it.y == tileY && it.level == level }?.getBitmap()
|
||||||
|
|
||||||
|
bitmap?.let {
|
||||||
|
val imageBitmap = bitmap.asImageBitmap()
|
||||||
|
drawImage(
|
||||||
|
image = imageBitmap,
|
||||||
|
topLeft = offset + Offset(offsetX, offsetY)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
drawRect(
|
drawRect(
|
||||||
color = gridColor,
|
color = gridColor,
|
||||||
size = Size(actualTileSize, actualTileSize),
|
size = Size(TILE_SIZE, TILE_SIZE),
|
||||||
topLeft = offset + Offset(offsetX, offsetY),
|
topLeft = offset + Offset(offsetX, offsetY),
|
||||||
style = Stroke(width = 4F)
|
style = Stroke(width = 4F)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
65
app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt
Normal file
65
app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.mirenkov.ktheightmap
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
class TileContainer(private val vm: TileViewModel, private val coroutineScope: CoroutineScope) {
|
||||||
|
private val tiles: MutableList<Tile> = mutableListOf()
|
||||||
|
|
||||||
|
private var startX = 0
|
||||||
|
private var startY = 0
|
||||||
|
|
||||||
|
private var endX = 0
|
||||||
|
private var endY = 0
|
||||||
|
|
||||||
|
private var level = 1
|
||||||
|
|
||||||
|
fun getTiles(_startX: Int, _startY: Int, _endX: Int, _endY: Int, _level: Int): List<Tile> {
|
||||||
|
val newParams = arrayOf( _startX, _startY, _endX, _endY, _level )
|
||||||
|
val oldParams = arrayOf( startX, startY, endX, endY, level )
|
||||||
|
var isInvalid = false
|
||||||
|
for (i in 0 until newParams.size) {
|
||||||
|
if (oldParams[i] != newParams[i]) {
|
||||||
|
isInvalid = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInvalid) {
|
||||||
|
updateTileList(_startX, _startY, _endX, _endY, _level)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateValues(_startX, _startY, _endX, _endY, _level)
|
||||||
|
|
||||||
|
return tiles
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTileList(_startX: Int, _startY: Int, _endX: Int, _endY: Int, _level: Int) {
|
||||||
|
tiles.removeIf {
|
||||||
|
it.level != _level ||
|
||||||
|
it.x < _startX ||
|
||||||
|
it.x > _endX ||
|
||||||
|
it.y < _startY ||
|
||||||
|
it.y > _endY
|
||||||
|
}
|
||||||
|
for (x in _startX .. _endX) {
|
||||||
|
for (y in _startY .. _endY) {
|
||||||
|
if (tiles.find { it.x == x && it.y == y && it.level == _level } == null) {
|
||||||
|
val tile = vm.repository.getTile(x, y, _level)
|
||||||
|
if (tile == null) {
|
||||||
|
tiles.add(Tile(x, y, _level))
|
||||||
|
} else {
|
||||||
|
tiles.add(tile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateValues(_startX: Int, _startY: Int, _endX: Int, _endY: Int, _level: Int) {
|
||||||
|
startX = _startX
|
||||||
|
startY = _startY
|
||||||
|
endX = _endX
|
||||||
|
endY = _endY
|
||||||
|
level = _level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package com.mirenkov.ktheightmap
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.future.future
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class TileRepository(private val tileDao: TileDao) {
|
class TileRepository(private val tileDao: TileDao) {
|
||||||
|
|
@ -12,11 +13,11 @@ class TileRepository(private val tileDao: TileDao) {
|
||||||
coroutineScope.launch(Dispatchers.IO) { tileDao.pushTile(tile) }
|
coroutineScope.launch(Dispatchers.IO) { tileDao.pushTile(tile) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTile(x: Int, y: Int, level: Int): Tile? {
|
fun getTile(x: Int, y: Int, level: Int): Tile? {
|
||||||
val tileDeferred = coroutineScope.async(Dispatchers.IO) {
|
val tileFuture = coroutineScope.future(Dispatchers.IO) {
|
||||||
tileDao.getTile(x, y, level)
|
tileDao.getTile(x, y, level)
|
||||||
}
|
}
|
||||||
return tileDeferred.await()
|
return tileFuture.join()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearTiles() {
|
fun clearTiles() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue