package com.example.composesokobantemplatev2 import android.graphics.BitmapFactory import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.example.composesokobantemplatev2.ui.theme.ComposeSokobanTemplateV2Theme import kotlin.math.roundToInt class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { ComposeSokobanTemplateV2Theme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> GameScreen(modifier = Modifier.padding(innerPadding)) } } } } } private const val LEVEL_WIDTH = 10 private const val LEVEL_HEIGHT = 10 // Data levelu private val levelData = intArrayOf( 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 3, 3, 2, 1, 0, 1, 0, 1, 0, 1, 3, 2, 3, 2, 0, 1, 0, 1, 0, 2, 3, 3, 2, 4, 0, 1, 0, 1, 0, 1, 3, 2, 3, 2, 0, 1, 0, 1, 0, 2, 3, 3, 2, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) @Composable fun GameScreen(modifier: Modifier = Modifier) { Box( modifier = modifier ) { GameLevelCanvas(levelData = levelData.toList()) } } @Composable fun GameLevelCanvas(levelData: List, modifier: Modifier = Modifier) { val context = LocalContext.current val tiles = remember { arrayOf( BitmapFactory.decodeResource(context.resources, R.drawable.empty).asImageBitmap(), // 0 BitmapFactory.decodeResource(context.resources, R.drawable.wall).asImageBitmap(), // 1 BitmapFactory.decodeResource(context.resources, R.drawable.box).asImageBitmap(), // 2 BitmapFactory.decodeResource(context.resources, R.drawable.goal).asImageBitmap(), // 3 BitmapFactory.decodeResource(context.resources, R.drawable.hero).asImageBitmap(), // 4 BitmapFactory.decodeResource(context.resources, R.drawable.boxok).asImageBitmap() // 5 ) } Canvas(modifier = modifier.fillMaxSize()) { val tileWidthPx = size.width / LEVEL_WIDTH val tileHeightPx = size.height / LEVEL_HEIGHT val tileSize = minOf(tileWidthPx, tileHeightPx) for (y in 0 until LEVEL_HEIGHT) { for (x in 0 until LEVEL_WIDTH) { val tileIndex = levelData[y * LEVEL_WIDTH + x] val img: ImageBitmap = tiles[tileIndex.coerceIn(0, tiles.lastIndex)] drawImage( image = img, dstOffset = IntOffset( x = (x * tileSize).roundToInt(), y = (y * tileSize).roundToInt() ), dstSize = IntSize( width = tileSize.roundToInt(), height = tileSize.roundToInt() ) ) } } } } @Preview(showBackground = true, showSystemUi = true) @Composable fun GameLevelCanvasPreview() { ComposeSokobanTemplateV2Theme { GameScreen() } }