Exploring Pac-Man Animation in Jetpack Compose

Xavier Jimenez Mulet
3 min readJul 28, 2023

Introduction:

In this post, we will explore an exciting animation using a custom shape of Pac-Man in Jetpack Compose. Pac-Man, a beloved gaming character from the past, will come to life with a delightful animation that showcases his iconic “eating” behavior. We’ll provide you with the necessary code snippets and explain the process step-by-step.

Setting up the Environment:

Before we dive into the animation, make sure you have the latest version of Jetpack Compose and Android Studio set up on your machine. You can find the code used in this tutorial on the GitHub repository here.

Creating the Pac-Man Shape:

To begin, let’s create a custom PacmanShape class that implements the Compose Shape interface. This shape will define the appearance of our Pac-Man character, with its characteristic mouth angle that opens and closes during the animation. The PacmanShape class contains a createOutline function where we define the shape's path, including the mouth angle based on the provided mouthAngle parameter.

class PacmanShape(
val mouthAngle: Float,
) : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
val path = Path().apply {
val eyeRadius = size.width / 12f
val eyeX = size.width * 0.5f
val eyeY = size.height * 0.25f
var angle = 360f - mouthAngle
if (angle <= 0f) {
angle = 0.1f
}
moveTo(size.width / 2f, size.height / 2f)
arcTo(Rect(0f, 0f, size.width, size.height), 30f, angle, forceMoveTo = false)
addOval(Rect(eyeX - eyeRadius, eyeY - eyeRadius, eyeX + eyeRadius, eyeY + eyeRadius))
close()
}
return Outline.Generic(path)
}
}

Creating the Pac-Man Animation:

Now, let’s create the Pac-Man animation using Jetpack Compose’s GraphicsLayer and rememberInfiniteTransition. In the PacmanAnimationComposable function, we define an animation that continuously changes the mouthAngle of the PacmanShape, creating the illusion of Pac-Man opening and closing his mouth. We use tween to control the animation duration and infiniteRepeatable to make it loop indefinitely

@Composable
fun PacmanAnimationComposable() {
val deltaXAnim = rememberInfiniteTransition()
val dx by deltaXAnim.animateFloat(
initialValue = 290f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(800, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(200.dp)
.graphicsLayer {
shadowElevation = 4.dp.toPx()
shape = PacmanShape(dx)
clip = true
}
.background(Color.Yellow)
)
}
}

Previewing the Animation:

We can preview the Pac-Man animation using the PacmanPreview function. Here, we simply use the PacmanShape with a fixed mouthAngle to display a static Pac-Man shape.

@Preview
@Composable
fun PacmanPreview() {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(200.dp)
.clip(PacmanShape(60f))
.background(Color.Yellow)
)
}
}

Conclusion:

In this post, we explored how to create an engaging Pac-Man animation using Jetpack Compose’s custom shape and animation capabilities. By adjusting the mouthAngle of the PacmanShape during the animation, we achieved the classic Pac-Man eating effect. You can find the complete code on our GitHub repository here. Now you have a fun and interactive Pac-Man animation that can be integrated into your Jetpack Compose projects! Happy coding! 🕹️👾

--

--