-
-
Save virendersran01/2368915d3cc7eaef427396ebf8b6b3c7 to your computer and use it in GitHub Desktop.
RockPaperScissors Jetpack Compose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Stable | |
| data class Particle( | |
| val id: Int, // stable key | |
| val type: MutableState<RPS>, | |
| val x: MutableState<Float>, | |
| val y: MutableState<Float>, | |
| val dx: MutableState<Float>, | |
| val dy: MutableState<Float> | |
| ) | |
| @Composable | |
| fun RockPaperScissorsGame(modifier: Modifier) { | |
| val particleSizeDp = 48.dp | |
| val particleSizePx = with(LocalDensity.current) { particleSizeDp.toPx() } | |
| val rockPainter = painterResource(id = R.drawable.stone) | |
| val paperPainter = painterResource(id = R.drawable.paper) | |
| val scissorsPainter = painterResource(id = R.drawable.scissors) | |
| val particles = remember { | |
| mutableStateListOf<Particle>().apply { | |
| repeat(15) { | |
| add(randomParticle(RPS.ROCK, it)) | |
| } | |
| repeat(15) { | |
| add(randomParticle(RPS.PAPER, 100 + it)) | |
| } | |
| repeat(15) { | |
| add(randomParticle(RPS.SCISSORS, 200 + it)) | |
| } | |
| } | |
| } | |
| var gameWidth by remember { mutableStateOf(0f) } | |
| var gameHeight by remember { mutableStateOf(0f) } | |
| LaunchedEffect(Unit) { | |
| while (true) { | |
| particles.forEach { p -> | |
| p.x.value += p.dx.value | |
| p.y.value += p.dy.value | |
| // impact effect | |
| if (p.x.value < 0) { | |
| p.x.value = 0f | |
| p.dx.value *= -1 | |
| } | |
| if (p.x.value > gameWidth - particleSizePx) { | |
| p.x.value = gameWidth - particleSizePx | |
| p.dx.value *= -1 | |
| } | |
| if (p.y.value < 0) { | |
| p.y.value = 0f | |
| p.dy.value *= -1 | |
| } | |
| if (p.y.value > gameHeight - particleSizePx) { | |
| p.y.value = gameHeight - particleSizePx | |
| p.dy.value *= -1 | |
| } | |
| } | |
| // Collision | |
| particles.forEach { p1 -> | |
| particles.forEach { p2 -> | |
| if (p1 != p2 && | |
| distance(p1.x.value, p1.y.value, p2.x.value, p2.y.value) < particleSizePx | |
| ) { | |
| val winner = winner(p1.type.value, p2.type.value) | |
| if (winner != null) { | |
| if (winner == p1.type.value) p2.type.value = winner | |
| else p1.type.value = winner | |
| } | |
| } | |
| } | |
| } | |
| delay(16) | |
| } | |
| } | |
| Column { | |
| Row( | |
| modifier | |
| .fillMaxWidth() | |
| .height(56.dp), | |
| horizontalArrangement = Arrangement.SpaceEvenly | |
| ) { | |
| Text( | |
| "Rock: ${particles.count { it.type.value == RPS.ROCK }}", | |
| fontSize = 24.sp | |
| ) | |
| Text( | |
| "Paper: ${particles.count { it.type.value == RPS.PAPER }}", | |
| fontSize = 24.sp | |
| ) | |
| Text( | |
| "Scissors: ${particles.count { it.type.value == RPS.SCISSORS }}", | |
| fontSize = 24.sp | |
| ) | |
| } | |
| Box( | |
| Modifier | |
| .fillMaxSize() | |
| .onGloballyPositioned { | |
| gameWidth = it.size.width.toFloat() | |
| gameHeight = it.size.height.toFloat() | |
| } | |
| ) { | |
| particles.forEach { p -> | |
| val painter = when (p.type.value) { | |
| RPS.ROCK -> rockPainter | |
| RPS.PAPER -> paperPainter | |
| RPS.SCISSORS -> scissorsPainter | |
| } | |
| Image( | |
| painter = painter, | |
| contentDescription = null, | |
| modifier = Modifier | |
| .size(particleSizeDp) | |
| .offset { | |
| IntOffset( | |
| p.x.value.toInt(), | |
| p.y.value.toInt() | |
| ) | |
| } | |
| ) | |
| } | |
| } | |
| } | |
| } | |
| // The winning rate of scissors will be very high :) | |
| fun randomParticle(type: RPS, id: Int): Particle { | |
| val (xRange, yRange) = when (type) { | |
| RPS.ROCK -> { | |
| // Bottom Left random position | |
| (50..300) to (800..1100) | |
| } | |
| RPS.PAPER -> { | |
| // Top Right r-p | |
| (800..1100) to (50..300) | |
| } | |
| RPS.SCISSORS -> { | |
| // Bottom Right r-p | |
| (800..1100) to (800..1100) | |
| } | |
| } | |
| return Particle( | |
| id = id, | |
| type = mutableStateOf(type), | |
| x = mutableFloatStateOf(xRange.random().toFloat()), | |
| y = mutableFloatStateOf(yRange.random().toFloat()), | |
| dx = mutableFloatStateOf(listOf(-4f, -3f, 3f, 4f).random()), | |
| dy = mutableFloatStateOf(listOf(-4f, -3f, 3f, 4f).random()) | |
| ) | |
| } | |
| fun winner(a: RPS, b: RPS): RPS? { | |
| return when { | |
| a == b -> null | |
| a == RPS.ROCK && b == RPS.SCISSORS -> a | |
| a == RPS.SCISSORS && b == RPS.PAPER -> a | |
| a == RPS.PAPER && b == RPS.ROCK -> a | |
| b == RPS.ROCK && a == RPS.SCISSORS -> b | |
| b == RPS.SCISSORS && a == RPS.PAPER -> b | |
| b == RPS.PAPER && a == RPS.ROCK -> b | |
| else -> null | |
| } | |
| } | |
| fun distance(x1: Float, y1: Float, x2: Float, y2: Float): Float { | |
| return sqrt((x1 - x2).pow(2) + (y1 - y2).pow(2)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment