Untitled
unknown
plain_text
a year ago
8.7 kB
5
Indexable
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlin.math.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BlockPuzzleTheme {
BlockPuzzleGame()
}
}
}
}
@Composable
fun BlockPuzzleTheme(content: @Composable () -> Unit) {
MaterialTheme(
colors = darkColors(), // Or lightColors()
content = content
)
}
@Composable
fun BlockPuzzleGame() {
var score by remember { mutableStateOf(0) }
var highScore by remember { mutableStateOf(0) }
var combo by remember { mutableStateOf(0) }
val boardState = remember { mutableStateOf(Board(10, 20)) }
val currentBlocks = remember { mutableStateOf(generateBlocks(3)) }
val nextBlock = remember { mutableStateOf(generateBlock()) }
var gameOver by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
if (gameOver) {
Text("Game Over!", style = MaterialTheme.typography.h5)
Button(onClick = {
boardState.value = Board(10, 20)
currentBlocks.value = generateBlocks(3)
nextBlock.value = generateBlock()
score = 0
combo = 0
gameOver = false
}) {
Text("Play Again")
}
} else {
Text("Score: $score High Score: $highScore Combo: $combo", style = MaterialTheme.typography.h6)
BoardView(boardState.value)
Spacer(Modifier.height(16.dp))
Text("Next:", style = MaterialTheme.typography.h6)
BlockView(nextBlock.value, Modifier.size(120.dp))
Row {
currentBlocks.value.forEachIndexed { index, block ->
DraggableBlock(block, index, currentBlocks) { dropPosition ->
val successfulDrop = boardState.value.placeBlock(block, dropPosition)
if (successfulDrop) {
score += 10 * (combo + 1)
combo++
if (score > highScore) {
highScore = score
}
currentBlocks[index] = nextBlock.value
nextBlock.value = generateBlock()
boardState.value.clearFullRows()
if (boardState.value.isGameOver(currentBlocks.value[index])) {
gameOver = true
}
} else {
combo = 0
}
}
}
}
}
}
}
@Composable
fun DraggableBlock(block: Block, index: Int, currentBlocks: MutableState<MutableList<Block>>, onDrop: (Position) -> Unit) {
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
val animatedOffsetX by animateDpAsState(targetValue = offsetX.dp)
val animatedOffsetY by animateDpAsState(targetValue = offsetY.dp)
val density = LocalDensity.current
val modifier = Modifier
.offset { IntOffset(animatedOffsetX.roundToPx(), animatedOffsetY.roundToPx()) }
.pointerInput(Unit) {
detectDragGestures(
onDragEnd = {
onDrop(Position((offsetX / density.density).roundToInt() / 30, (offsetY / density.density).roundToInt() / 30))
},
onDrag = { change, dragAmount ->
offsetX += dragAmount.x
offsetY += dragAmount.y
}
)
}
BlockView(block = block, modifier = modifier)
Spacer(modifier = Modifier.width(10.dp))
}
@Composable
fun BlockView(block: Block, modifier: Modifier = Modifier) {
Column(modifier = modifier) {
block.shape.groupBy { it.y }.forEach { (_, cells) ->
Row {
cells.forEach { cell ->
Box(
modifier = Modifier
.size(30.dp)
.background(block.color)
)
}
}
}
}
}
data class Block(val shape: List<Position>, val color: Color)
data class Position(val x: Int, val y: Int)
class Board(val width: Int, val height: Int) {
private val grid = Array(height) { Array(width) { Color.Transparent } }
fun placeBlock(block: Block, position: Position): Boolean {
// ... (same as before)
val shape = block.shape
for (cell in shape) {
val x = cell.x + position.x
val y = cell.y + position.y
if (x < 0 || x >= width || y < 0 || y >= height || grid[y][x] != Color.Transparent) {
return false
}
}
for (cell in shape) {
val x = cell.x + position.x
val y = cell.y + position.y
grid[y][x] = block.color
}
return true
}
fun clearFullRows() {
// ... (same as before)
val newGrid = Array(height) { Array(width) { Color.Transparent } }
var newRow = height - 1
for (row in height - 1 downTo 0) {
if (grid[row].all { it != Color.Transparent }) {
continue
} else {
newGrid[newRow] = grid[row]
newRow--
}
}
for (i in 0 until height){
grid[i] = newGrid[i]
}
}
fun getCellColor(x: Int, y: Int): Color {
return grid[y][x]
}
fun isGameOver(nextBlock: Block): Boolean { // No valid placement found, game over
for (x in 0 until width) {
for (y in 0 until height) {
if (canPlaceBlock(nextBlock, Position(x, y))) {
return false
}
}
}
return true
}
private fun canPlaceBlock(block: Block, position: Position): Boolean { // Invalid placement
// ... (same as before)
val shape = block.shape
for (cell in shape) {
val x = cell.x + position.x
val y = cell.y + position.y
if (x < 0 || x >= width || y < 0 || y >= height || grid[y][x] != Color.Transparent) {
return false
}
}
return true
}
}
@Composable
fun BoardView(board: Board) {
Column {
for (y in 0 until board.height) {
Row {
for (x in 0 until board.width) {
Surface(
modifier = Modifier
.size(30.dp)
.border(1.dp, Color.DarkGray),
color = board.getCellColor(x, y)
) {}
}
}
}
}
}
// Block shapes and colors:
val shapes = listOf(
listOf(Position(0, 0), Position(1, 0), Position(0, 1), Position(1, 1)), // Square
listOf(Position(0, 0), Position(1, 0), Position(2, 0), Position(3, 0)), // Line
listOf(Position(0, 0), Position(1, 0), Position(2, 0), Position(2, 1)), // L-shape
listOf(Position(0, 0), Position(0, 1), Position(1, 1), Position(2, 1)),
listOf(Position(0, 0), Position(1, 0), Position(1, 1), Position(2, 1)),
listOf(Position(1,0),Position(0,1),Position(1,1), Position(2,1))
// Add more shapes...
)
val colors = listOf(
Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Magenta, Color.Cyan
)
fun generateBlock(): Block {
val randomShape = shapes.random()
val randomColor = colors.random()
return Block(randomShape, randomColor)
}
fun generateBlocks(count: Int): MutableList<Block> = mutableListOf<Block>().apply {
repeat(count) { add(generateBlock()) }
}Editor is loading...
Leave a Comment