The Canvas composable isn’t limited to graphics; it’s also used in creating interactive and immersive game experiences directly within your app. Let’s look at a simple game concept — a bouncing ball.

Bouncing Ball Game
@Composable
fun BouncingBallGame() {
val position = remember { mutableStateOf(Offset(300f, 0f)) }
val velocity = remember { mutableStateOf(Offset(3f, 3f)) }

LaunchedEffect(Unit) {
while (true) {
position.value += velocity.value
// change > condition to size of screen,
// here just using a static value for demo purposes
if (position.value.x < 0f || position.value.x > 1000f) {
velocity.value = Offset(-velocity.value.x, velocity.value.y)
}
if (position.value.y < 0f || position.value.y > 1200f) {
velocity.value = Offset(velocity.value.x, -velocity.value.y)
}
delay(16L)
}
}

Column(
modifier = Modifier.background(
brush = Brush.horizontalGradient(
listOf(
Color.Red,
Color.Blue
)
)
)
) {
Canvas(
modifier = Modifier
.height(460.dp)
.fillMaxWidth()
) {
drawCircle(
brush = Brush.horizontalGradient(listOf(Color.Blue, Color.Red)),
center = position.value,
radius = 60f
)
}

Divider(thickness = 5.dp, color = Color.Red)

Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(
colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
onClick = {
val random = (-1..1).random()
if (random != 0) {
velocity.value += Offset(random * 10f, random * 10f)
}
},
) {
Text(text = "Change Bounce")
}

Text(
text = "Velocity: ${velocity.value.x}, ${velocity.value.y}",
color = Color.White,
)
}
}
}

Key Concepts —

  • Position and Velocity State — The ball’s position (position) and velocity (velocity) are defined as mutable state using the mutableStateOf function. The position state variable controls the ball’s movement on the canvas. Velocity does not necessarily need to be a state variable unless we are using it (ex. displaying velocity in a Text).
Text(
text = "Velocity: ${velocity.value.x}, ${velocity.value.y}",
color = Color.White,
)
  • LaunchedEffect Animation Loop — The LaunchedEffect is used to create an infinite animation loop. Inside the loop, the ball’s position is updated by adding the velocity to it. When the ball reaches the screen edges, its velocity is reversed to simulate bouncing.
  • Canvas Composable: The Canvas composable is used to draw the bouncing ball. The drawCircle function is used to draw the ball at the current position with a gradient brush.
  • Change Bounce Button — The Button allows users to change the ball’s velocity, simulating a change in bounce behavior.

Source link