Press enter or click to view image in full size
The idea of building a complex game without a dedicated game engine sounds, to many, like a Sisyphean task. In the world of Compose Multiplatform (CMP), the common narrative revolves around sleek business apps, elegant UIs, and shared logic for forms and lists. But what if you wanted to build an entire open-world roguelike card game, complete with intricate animations, deep combat, and responsive mini-games, all while staying purely within the Kotlin ecosystem?
That’s precisely the challenge I embraced with Arcana. This isn’t just another mobile app; it’s a full-fledged roguelike deckbuilder where you explore a vibrant town, battle in dungeons, duel in a colosseum, and even gamble in a casino — all powered by Compose Multiplatform.
Press enter or click to view image in full size
The “Why”: A Developer’s Yearning for Native Control
My journey began with a question: Do I really need to learn a massive, proprietary game engine just to see if my idea works?
I had a clear vision for Arcana, but I also had a specific set of requirements. I needed the game to be truly multiplatform — targeting Android, iOS, and Desktop simultaneously — without maintaining three separate codebases. While traditional engines like Unity or Godot are the “standard” choice, they come with a steep learning curve and a heavy footprint.
As a developer already comfortable in the Kotlin ecosystem, I wanted to “test the waters” first. I wanted to see if I could achieve high-performance gameplay using the tools I already loved. Compose Multiplatform (CMP) was the perfect candidate. It offered:
- Platform Reach: The ability to hit mobile (Android/iOS) and Desktop from a single project.
- Low Friction: I could start building immediately without spending months mastering a complex game engine’s specialized UI systems or physics pipelines.
- Native Control: I wanted the game to feel like a part of the OS, with the snappiness and battery efficiency that only native-level frameworks can provide.
This was my high point of conviction — the realization that I didn’t need to leave my comfort zone to build something ambitious. I decided to treat Compose not just as a UI library, but as the foundation of my game’s world.
Press enter or click to view image in full size
The “How”: Building a Game, Composable by Composable
Instead of game objects and MonoBehaviour scripts, Arcana is built with Composables. Every card, every enemy, every building in the town, and every UI element is a Composable function that reacts to state changes.
1. Crafting the World: The “Pokemon-style” Exploration
My vision was an open world where players could freely roam, Pokémon-style, to access different game modes. This wasn’t just a menu; it was a map.
- Initial Low Point: My first attempts at drawing the entire town on a single
Canvaswere clunky. Performance dipped, and managing interaction felt like fighting the framework. - The Breakthrough: I realized Compose excels at composing smaller, independent elements. The town became a grid of Composables. Each building, character, and environmental detail (trees, fences) is its own Composable, dynamically loaded and animated as the player character moves across the map. This allowed for efficient rendering and easy interaction.
- Asset Acquisition: Crucially, I relied heavily on Patreon subscriptions to artists specializing in pixel art and RPG tilesets. This was a huge time-saver. Buildings, environmental entries, and even animations were sourced from these incredible creators, allowing me to focus on the code.
Press enter or click to view image in full size
2. The Heart of the Game: Roguelike Card Combat
This is where Compose Multiplatform truly shined.
- Declarative Animations: Animating cards flying across the screen, enemies taking damage, or status effects applying was incredibly straightforward using Compose’s animation APIs (
animateFloatAsState,rememberInfiniteTransition,Modifier.graphicsLayer). Sprite sheet animations, often a headache in traditional UIs, became simple by cyclingImageBitmapframes within aCanvasComposable, allowing for fluid character and spell effects. - State Management: The complex state of a roguelike (player health, energy, deck, discard, enemy intent, numerous buffs/debuffs) was managed elegantly with Kotlin’s data classes and flows. Every change in game state automatically triggered a recomposition of the relevant UI elements, keeping the UI in perfect sync with the game logic. No manual UI updates needed!
3. Mini-Games and Dynamic UI: The “Casino” Factor
A key differentiator for Arcana is its variety, including mini-games like Blackjack in the town’s casino.
- Seamless Integration: The ability to render a completely different game mode (a card table, dice rolls) using the exact same UI framework (Compose) within the same application was a testament to CMP’s flexibility. It felt like a native app switching screens, not a mini-game loading a separate engine.
- No “Engine” Jitter: In many mobile games, mini-games feel like “afterthoughts” with different UI styles. In Arcana, because everything is a Composable, the transition from the Town to the Blackjack table is visually seamless.
Press enter or click to view image in full size
The Performance Question
The biggest skepticism around using Compose for games often centers on performance. Here’s how Arcana thrives:
- Skia Under the Hood: Compose Multiplatform leverages Skia, a high-performance graphics library, for its rendering. This means that while you write Kotlin UI, the actual drawing is incredibly efficient.
- Smart Recomposition: Compose’s intelligent recomposition engine ensures that only the parts of the UI that actually change are redrawn. My low point during development was seeing unexpected recompositions. The high point was learning to optimize by using
remember,key, and stable data structures, turning those performance issues into efficient updates. - Sprite Sheets are Key: For character and enemy animations, using efficient sprite sheets rendered on a
Canvasprovided maximum performance. This kept redraws light and fast, offloading complex animation logic from Compose’s UI tree to direct canvas drawing. - Asset Efficiency: Another high point was realizing that high-quality, pre-made assets (again, from Patreon subscriptions for game characters, buildings, and environmental art) were already optimized for performance and consistency, further reducing my workload.
Press enter or click to view image in full size
Knowing the Limits: The 2D Sweet Spot
While I’m incredibly proud of what Arcana achieves, I want to be clear about the scope. I chose Compose Multiplatform because it was the perfect tool for this specific job: a 2D, state-heavy card game with top-down exploration.
If you are considering CMP for your own project, here is my honest take on where the “engine-less” approach shines and where it might struggle:
- Where it wins (2D & State): If your game relies on complex UI, deep logic (like card battlers or strategy games), and 2D sprite-work, CMP is a powerhouse. It treats your game world as a reactive system, which is a dream for debugging.
- The 3D Barrier: I have not tested this architecture for 3D, and frankly, I wouldn’t recommend it. Compose is built for drawing 2D hierarchies. Trying to implement a 3D renderer or complex lighting pipelines in pure Compose would likely be an exercise in frustration compared to using a dedicated engine like Unity or Godot.
- Performance Ceilings: For ultra-fast action games (like bullet-hell shooters or high-fidelity platformers), the overhead of the Compose runtime might eventually hit a ceiling. My success with 60FPS comes from the fact that a Roguelike Card Game allows for “breathing room” in the rendering cycle.
My advice? If you’re building a 2D RPG, a puzzle game, or a card battler, CMP is a serious contender. If you’re building the next Elden Ring, stick to the specialized engines. Know your tool, and know your target.
What I Learned: Compose Multiplatform’s Game-Changing Potential
Building Arcana has been a monumental journey, and it has fundamentally changed my perspective on Compose Multiplatform:
- It’s More Than UI: CMP is a powerful, expressive framework capable of handling complex game logic, intricate animations, and diverse interaction models.
- Kotlin is a Game Dev Language: If you love Kotlin, you no longer need to switch to C# or C++ for 2D game development.
- Community & Tooling: The evolving tooling (Android Studio, Xcode, Fleet) and the incredibly supportive Kotlin community make the development experience productive and enjoyable.
This journey wasn’t without its challenges, but the rewards of seeing Arcana come to life, performing flawlessly on mobile devices, and proving the capabilities of Compose Multiplatform, have been immense.
Arcana is launching soon on Android and iOS. I invite you to download it and experience a truly native roguelike deckbuilder built with the power of Kotlin and Compose Multiplatform.
Download Arcana (Coming Soon): https://playarcana.app/
Press enter or click to view image in full size