You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.0 KiB
137 lines
4.0 KiB
4 years ago
|
package org.jetbrains.compose.demo.falling
|
||
|
|
||
4 years ago
|
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||
4 years ago
|
import androidx.compose.foundation.layout.*
|
||
|
import androidx.compose.material.Button
|
||
|
import androidx.compose.material.Slider
|
||
|
import androidx.compose.material.Text
|
||
|
import androidx.compose.runtime.*
|
||
|
import androidx.compose.ui.Modifier
|
||
|
import androidx.compose.ui.graphics.Color
|
||
|
import androidx.compose.ui.layout.onSizeChanged
|
||
4 years ago
|
import androidx.compose.ui.platform.LocalDensity
|
||
|
import androidx.compose.ui.unit.*
|
||
4 years ago
|
import kotlin.random.Random
|
||
|
|
||
|
class Game {
|
||
|
private var previousTimeNanos: Long = Long.MAX_VALUE
|
||
|
private val colors = arrayOf(
|
||
|
Color.Red, Color.Blue, Color.Cyan,
|
||
|
Color.Magenta, Color.Yellow, Color.Black
|
||
|
)
|
||
|
private var startTime = 0L
|
||
|
|
||
4 years ago
|
var size by mutableStateOf(Pair(0.dp, 0.dp))
|
||
4 years ago
|
|
||
|
var pieces = mutableStateListOf<PieceData>()
|
||
|
private set
|
||
|
|
||
|
var elapsed by mutableStateOf(0L)
|
||
|
var score by mutableStateOf(0)
|
||
3 years ago
|
private var clicked by mutableStateOf(0)
|
||
4 years ago
|
|
||
|
var started by mutableStateOf(false)
|
||
|
var paused by mutableStateOf(false)
|
||
|
var finished by mutableStateOf(false)
|
||
|
|
||
|
var numBlocks by mutableStateOf(5)
|
||
|
|
||
|
fun start() {
|
||
|
previousTimeNanos = System.nanoTime()
|
||
|
startTime = previousTimeNanos
|
||
|
clicked = 0
|
||
|
started = true
|
||
|
finished = false
|
||
|
paused = false
|
||
|
pieces.clear()
|
||
|
repeat(numBlocks) { index ->
|
||
|
pieces.add(PieceData(this, index * 1.5f + 5f, colors[index % colors.size]).also { piece ->
|
||
|
piece.position = Random.nextDouble(0.0, 100.0).toFloat()
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun togglePause() {
|
||
|
paused = !paused
|
||
|
previousTimeNanos = System.nanoTime()
|
||
|
}
|
||
|
|
||
|
fun update(nanos: Long) {
|
||
|
val dt = (nanos - previousTimeNanos).coerceAtLeast(0)
|
||
|
previousTimeNanos = nanos
|
||
|
elapsed = nanos - startTime
|
||
|
pieces.forEach { it.update(dt) }
|
||
|
}
|
||
|
|
||
|
fun clicked(piece: PieceData) {
|
||
|
score += piece.velocity.toInt()
|
||
|
clicked++
|
||
|
if (clicked == numBlocks) {
|
||
|
finished = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Composable
|
||
4 years ago
|
@Preview
|
||
4 years ago
|
fun FallingBallsGame() {
|
||
|
val game = remember { Game() }
|
||
4 years ago
|
val density = LocalDensity.current
|
||
4 years ago
|
Column {
|
||
|
Text(
|
||
|
"Catch balls!${if (game.finished) " Game over!" else ""}",
|
||
|
fontSize = 50.sp,
|
||
|
color = Color(218, 120, 91)
|
||
|
)
|
||
|
Text("Score ${game.score} Time ${game.elapsed / 1_000_000} Blocks ${game.numBlocks}", fontSize = 35.sp)
|
||
|
Row {
|
||
|
if (!game.started) {
|
||
|
Slider(
|
||
|
value = game.numBlocks / 20f,
|
||
|
onValueChange = { game.numBlocks = (it * 20f).toInt().coerceAtLeast(1) },
|
||
|
modifier = Modifier.width(100.dp)
|
||
|
)
|
||
|
}
|
||
|
Button(onClick = {
|
||
|
game.started = !game.started
|
||
|
if (game.started) {
|
||
|
game.start()
|
||
|
}
|
||
|
}) {
|
||
|
Text(if (game.started) "Stop" else "Start", fontSize = 40.sp)
|
||
|
}
|
||
|
if (game.started) {
|
||
|
Spacer(Modifier.padding(5.dp))
|
||
|
Button(onClick = {
|
||
|
game.togglePause()
|
||
|
}) {
|
||
|
Text(if (game.paused) "Resume" else "Pause", fontSize = 40.sp)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (game.started) {
|
||
|
Box(modifier = Modifier
|
||
|
.fillMaxWidth()
|
||
4 years ago
|
.fillMaxHeight()
|
||
4 years ago
|
.onSizeChanged {
|
||
4 years ago
|
with(density) {
|
||
|
game.size = it.width.toDp() to it.height.toDp()
|
||
|
}
|
||
4 years ago
|
}
|
||
|
) {
|
||
|
game.pieces.forEachIndexed { index, piece -> Piece(index, piece) }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LaunchedEffect(Unit) {
|
||
|
while (true) {
|
||
|
withFrameNanos {
|
||
|
if (game.started && !game.paused && !game.finished)
|
||
|
game.update(it)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|