A behind-the-scenes look at developing Decrypto, the game that changed me and my life.
Recently I was talking with my mom, and she told me about one of her favorite writers who writes books to encapsulate and solidify her experiences, ideas, and memories. For me, this blog kind of became that. A way to explore, solidify, and make sense of things. And this specific “page” of my book is about something really dear to me.
I believe that almost everything can be seen from different perspectives. The idea behind this blog post is to look at Decrypto through four lenses: as a human, as a creator, as a designer, and finally as a developer.
Part I: Human
I was always fascinated with the idea that you could create something, carry it in your pocket, and then share it with your friends with such ease. Just imagine that, in a black canvas filled with the void, you plant a seed of an idea that was forming in your mind, then over time you nurture it, help it grow, and eventually it grows and becomes real, ready to be shared with the rest of the world.
Because of this magical feeling, when I was in high school, I had a deep desire and drive to create my own mobile game, a game that would reflect my little world and allow me to share it with others.
Logical puzzle games captivated me from an early age, maybe because at the time most of them weren’t about squeezing money out of players, but instead were created by people driven by a passion to reflect and share the mysterious worlds they loved so much.
I was also interested in cryptic things. Maybe it was because of my more private personality, maybe because I liked the mystery, or maybe I just liked the idea of someone carefully crafting something deep and complex, yet seemingly simple to the plain eye.
As a result, the idea to create a game about ciphers was born. It wasn’t just any kind of game, but one for Android phones, which I didn’t own or have access to.
That meant I’d send builds via email to my friends and test them the next day at school. Surprisingly, this made waiting for the next day at school feel thrilling. Probably not the most common thing to hear from someone approaching their final exams. Nevertheless, every day felt exciting, even the ones when I saw the dreaded “Decrypto isn’t responding. Do you want to close it?” message.
Skipping all the technical hurdles and details, the first version of Decrypto was released on the Google Play Store in 2015. Then, after I got my first Mac, the game was rewritten and also published on the App Store.
For the most part, things remained calm and uneventful. I released more games. I fell in love with developing for Apple platforms. I left home to study abroad and shifted most of my focus to my studies. I started working as a barista. I was growing as a person, and I was living my normal life.
However, everything changed in 2018. For some reason, Decrypto started climbing the top charts in the puzzle category on the Google Play Store. It was totally unexpected since I hadn’t updated the game in years. Still, I cherished every moment of that. I constantly checked the reviews, the install count, and the rankings. It was obvious: I was high on my own game.

Not long after that, out of nowhere, I received an email from a European game publishing company that was interested in acquiring the game. I honestly thought it was just some scam. But being young, I didn’t care. Even if it was a Nigerian prince, I still would’ve talked.
After setting up a call over Skype, I realized it was real. I gave them access to my dashboards, provided all the info, and eventually received an offer for the game. Everything seemed great, but there was one catch: the offer required me to create an update.
It seems easy, right? Well, not if you haven’t touched the game in years and lost everything related to the setup. Especially not if it’s a Cocos2d-x project that requires installing Android SDKs, NDKs, fixing Proguard issues, migrating across multiple versions and recreating all the missing source files. Even more so if you’ve got just 24 hours to make it happen.
For me, this is one of the core memories of my life. I won’t forget that day because it felt like one of those days where you put all of yourself in without sparing anything. The ones where your survival instincts kick in and everything else ceases to exist for a moment.
It was a Wednesday, which meant I didn’t have any lectures. I had about three hours left before my work shift when I got a Skype message asking for my details so we could proceed. Two hours before my shift, we had the contract ready, but there was one issue. I still didn’t have a working game. In fact, at that point, I wasn’t even sure I could make one. And me being me, I knew for sure I wasn’t signing anything unless I had everything perfect.
So, being a child who is still developing his brain, instead of telling them I had an 8-hour barista shift and then I’d try to build the game overnight, I told them I had a flight and wouldn’t be available until Thursday night.
Now it sounds funny, but back then I was still mentally building my adult brain, and that excuse felt solid. The big, important me is taking a flight and won’t be reachable for 24 hours. Over the years, I’ve learned to be more direct and honest, but reading that conversation still brings a big smile to my face.
So, finishing my shift around 11 PM, I rushed home with only one important stop, the supermarket. I bought a few cans of energy drinks and headed straight home. At that time, I didn’t consume much caffeine, so that night felt like I was some hacker trying to break into a government system before sunrise. I still remember the awful sofa I spent the whole night on. Building, downloading, upgrading, fixing errors, setting up simulators. Ergonomically, it was the worst night of my life. Emotionally, it felt like the best. Around 5 AM, I finally had a working build in the simulator. It was a success.
I think I slept for a few hours before rushing to the university library to scan and sign the documents. At 10 AM, I was magically back from my “important flight” and sent everything. What followed was a complicated 5-step back-and-forth process where each party slowly handed over their part. It felt like a peace treaty negotiation, but with every step, I felt closer and closer to the finish line of the glorious sprint of my life.
After the deal was done, driven by curiosity, I kept following the game’s progress. And honestly, it was so devastating to watch that at some point I had to stop. The number of ads grew and the number of 1-star ratings exploded. Reading comments felt heartbreaking. Especially when you couldn’t do anything but just watch your carefully handcrafted ship slowly sink below the horizon. Eventually, the game was sold, resold, and then completely disappeared.
The iOS version still belonged to me, and I kept it safe and dear to my heart. Especially after seeing what happened to the Android version.
Nevertheless, even seeing how things ended up, if I had to rewind time, I would’ve done the exact same thing. The reason is simple. If it wasn’t for Decrypto, I don’t think I’d be where I am today.
Decrypto gave me financial freedom at the most important time of my life. I was in my third year at university, and my job as a barista was getting more and more stressful. But now, I could quit and focus fully on my studies and learning.
I firmly believe that’s why I wasn’t afraid to take a leap and pick one of the most challenging theses for my dissertation. It’s why, even after I graduated, I said yes to writing first academic paper. It’s why we won the best paper award. And it’s why every step after that has been backed by a quiet confidence and a deep gratitude.
It shaped me as a human. It guided my life. It will always have a place in my heart.
Part II: Creator
I’m a strong believer that creating is a core human need. I also believe that in the current state of the world, where we consume so much, this need often gets neglected. Just like a plant without enough water and sun, we as humans are getting weaker, less vibrant, and maybe even a little lost.
The beautiful thing about this core human need is that it can be fulfilled in many ways. It can be anything from writing a poem to growing your garden, from sketching in your notebook to designing a weird, experimental board game that only five people will ever play. It doesn’t have to be something complicated or very involved. Even the smallest moments add up and bring this untouchable flame to your heart.
It might sound like I’m trying to make it poetic or overly deep, but that’s honestly how I feel about it. If I imagine the core of my life, the place where I build all the other things, creating is part of that core. It’s one of the things that allows me to stand up when life hits me with challenges.
Before Decrypto, I had game servers, websites, and other similar projects. But Decrypto felt like the first project that was truly driven by my passion and vision. Every single pixel, every single interaction and message was handcrafted by me. In a way, it felt like a reflection of me and my core values. From the first moment I had a basic prototype that I was sharing with my friends, I knew that I would be chasing this feeling for the rest of my life.
Every time someone asks me how it’s not boring or repetitive to just write code, I wish they could feel the moment where something appears out of what feels like nothing. Sure, technically it’s not nothing, since you’re building on decades of technology, tools, and knowledge. But I see all of that as a canvas, a pencil, a set of brushes. And you’re the one creating something only you could. That first “hello world” program, that first black screen, or the moment a tiny script actually does what you wanted it to, makes you feel like you’re the next Da Vinci. And while that feeling has changed over time, and it takes more to reach that same thrill, it’s still there. That basic human need to create.
I started working on the 10-year anniversary Decrypto release around 10 months ago. To be more precise, two days after I finished watching all my WWDC videos. Coincidence? Definitely not. That’s the reason why I love WWDC. The inspiration I get when I watch new APIs and those cool presentations is just unmatched.
This time, though, my development started very differently compared to 10 years ago. This time I knew the release had sentimental value, and I wanted to be very intentional about it. I even told myself that I’d rather miss the 10-year anniversary than do something that doesn’t feel right.
This time, my life wasn’t centered around developing a game. I let life happen and flow, while filling it with the joy of creating something I was proud of.
Part III: Designer
I’ll be completely honest, looking at the old Decrypto version, I felt embarrassed. I almost wanted to remove it from the store until I could find time to revamp it. However, over the years, the game continued to receive the most wholesome reviews from people who genuinely enjoyed it.

In fact, user reviews were one of the strongest driving forces behind this complete rewrite. Another huge factor was that, over 10 years, I grew as a developer, designer, and most importantly, as a person. Now I’m a much more intentional and opinionated human being. In a sense, that’s a good thing, but it also has its downsides. That became especially clear on the developer side of me. But more on that in the Developer chapter.
Ten years ago, I didn’t question anything. I just followed the standard game template: menus, credits, standard navigation, leaderboards, achievements, and so on. This time, I decided to step back and rethink everything.
For example, why does a game have to open with a menu every time? Why should going from one scene to another feel like a jarring cut? Why would I sacrifice the game experience with ads?
With all those questions in mind, I spent a few days thinking about what feeling I wanted from this game. Yes, feeling. Just that. I didn’t care about anything else. I was laser-focused on the feeling and emotion someone should experience when they open the game.
The first thing I wanted to create was mystery. No onboarding, no tutorials, no menus. You enter the game, and you see symbols that instantly spark your curiosity.
I also wanted zero distractions. It’s just you, the code, and nothing else. Remember when you were a baby? No? Well, it doesn’t matter. Think for a second about a baby and what happens when you give them some toy that just clicks. For me, that toy was a long and colorful caterpillar made out of soft and soothing material. When my parents would give it to me, I would put my tiny fingers between its dozen legs and all of a sudden the surrounding world would just disappear.
To focus on this mystery feeling even further I decided the game would use only two colors: black and white. For some reason it just felt right. No distraction, no calling for attention, just a puzzle that you could wrangle your fingers around and forget your surroundings.
Another big change I wanted was phone orientation. The old version required landscape mode. Back then, it made sense because phones were smaller and I needed to show a lot of info on screen. But now, I wanted the game to feel like a kind of puzzle toy you could hold in one hand, twist around, and explore with fluid interaction.
At first, I felt a bit lost. I had pushed myself into a corner. Some of the encrypted puzzles took up a lot of space, some hints needed even more, and what about settings?
I let it boil in my head while I focused on other parts of life. Then one day, sitting on a humid sofa in Costa Rica, with crabs crawling around my room, watching a WWDC session about SwiftUI custom visual effects, it hit me. Why the hell had I been thinking in just two dimensions this whole time? What would happen if I brought a third dimension into the game? Suddenly, step by step, all the challenges started to slowly solve themselves.
The other big thing I wanted was input that made you feel connected to the game. In the previous version, typing a word into a text field worked fine, but this time I wanted the experience to feel more whimsical. Another issue with the old input was that, if a word was encrypted using a shift method, you’d have to do mental math.
I also wanted to make the game more approachable for people who don’t live in the cipher world. That meant the input method needed to constrain and guide users toward the goal, instead of leaving them stranded. And finally, the input needed to tie back into some kind of physical-world metaphor.
So what was the final result?
This is the input I landed on. It checked all the boxes: it felt like a real-world combination lock while keeping the aesthetics super minimal, it let you shift letters easily without doing math in your head. It constrained the input to help beginners, and each interaction had this whimsical yet platform-native vibe.
On top of that, for “power players” who didn’t want the handholding and just wanted to go fast, I added the ability to switch back to regular text input.
Another target for this version was to make it ergonomic in the player’s hand. Previously I didn’t think much about it. The buttons, menu items, and other interactive elements just followed the “regular” top-to-bottom flow. But personally, I hate that. Especially when you’re using a larger phone, you’re forced to stretch your fingers in uncomfortable ways or rely on accessibility gestures.
The idea for Decrypto was to create a game that feels more like a real toy, something you can mess around with using one hand without much effort.

Keeping that in mind, I decided to move interactive elements to the bottom of the screen wherever possible. That was a bit tricky when it came to the main input, since iOS has this reachability gesture that can be triggered easily when a scroll view is close to the bottom. The annoying part is that you can’t really disable it, which meant I had to sacrifice some aesthetics (like larger bottom paddings) for better ergonomics. Still, I was really happy with how it turned out.
One constraint from the original version that felt magical and really important was the fact that each answer acted as a hint for the next level. I don’t know why, but it felt like such a crucial detail. Maybe it’s my obsession with psychological thrillers, where every detail is passionately crafted and hidden in plain sight, only to reveal a huge twist at the end. I loved that feeling.
But over time, I also learned what that kind of constraint brings. If players discovered that level X was easier than level Y, I couldn’t just swap them. Worse, if I had a cool idea for a new level I wanted to insert midway through the game, I couldn’t just drop it in. The previous level’s answer had to act as a hint for the next one.
That’s actually one of the reasons I didn’t add new levels over time. Every part felt so delicately crafted that moving or inserting anything would require a full rework. Another big issue was that this setup forced the first hint of every level to be a single word. While that sounded great on paper, in reality it ended up being far too limiting. So in this rewrite, I decided to drop that constraint entirely.
Another major focus for this game rewrite was making it more engaging and dynamic. There’s something magical about touching something and having it respond and invite you deeper into the experience. That’s how the new interactive levels like Morse code, steganography images, and others came to life.
While I’m still far from the original vision I had 10 years ago, I believe this release is another step toward that dimension direction.
Part IV: Developer
I believe that over 10 years I changed a lot as a developer, in both good and bad ways. For example, paradoxically, I feel like with less experience I was able to ship things faster. How come, you ask? Well, opening 10-year-old C++ code, I can see that past me didn’t have any issues with a file having 1k lines of C++ code that mixes UI and business logic. Back then, my goal wasn’t to write the cleanest or the most beautiful code. I cared about shipping things more. That doesn’t mean I just wrote spaghetti code without thinking, I still cared about maintainability but shipping was above everything else.
However, over the years I caught this disease of focusing on the code more and more. Don’t get me wrong, maintainable code is very important, but I feel like over time I started prioritizing it at the expense of momentum. This is especially difficult since I actually enjoy it. I feel like all my life I’ve had this inner battle between the entrepreneurship part of me and the developer part of me. Entrepreneurship wants to ship cool and interesting things, whereas the developer part can spend weekends reading thousand-page book about a programming language that I find interesting. I’ve always lived on a swing where at one point one side dominates, then it swaps.
This rewrite was a moment where I really tried to work on that balance. Honestly, it was pretty hard, especially since I believe that when I was working on Invoicy, the developer part of me got so much stronger that it completely overpowered the side of me that just wants to ship and iterate.
In every project I work on, I usually allow myself to do some kind of very questionable overengineering to satisfy my developer side. In Invoicy, that was the InvoicyTemplateEvaluator
, which is a mechanism that basically renders the template, collects all the information, and compares it with user changes to prevent saving unnecessary values to the database. It might sound simple and very uninteresting, but I can tell you that to this day it’s probably the scariest thing lying around in the Invoicy codebase.
You might ask: “But why would you do such a thing?” The answer is simple: 5x less storage. Then you say: “Yeah, but those are invoice entries so you won’t feel anything unless you’re dealing with tens of thousands of them.” And to that, the developer part of me says: “500 invoices before: 13.1 MB. 500 invoices now: 2.5 MB.”
Now you may ask me: what was probably the most overengineered and most likely unnecessary part in Decrypto? Well, I kinda felt that it would only be fair if a game about ciphers and decryption had data that was itself encrypted.
But how do you encrypt data that constantly changes during development and would be a big pain in the ass to update manually?
After trying Swift Package plugins and other modern options, I went with a simple Swift Package solution. The project has a separate Swift Package with an executable target that uses a metadata file and converts it to Swift code. Basically a code generator of sorts, but instead of only generating code, it also generates and encrypts level explanations. The generated code looks something like this:
static let data: [Level: LevelData] = [
.AA_0A_6E_6F_69_78: .init(
decryption: "AA_04_6A_65_69_61",
encryption: .image(named: "AA_14_70_71_77_66_6D_64_60"),
key: .image(named: "AA_0D_69_68_6E_7F"),
hints: [
.text("AA_05_6D_6C_6B_71_76"),
.image(named: "AA_0F_69_68_61_7C_7A_7B"),
.image(named: "AA_0F_6B_6A_6C_7D_76_7F")
],
explanation: .init(
fileName: "AA_15_71_70_76_67_6C_65_61_7C",
password: "AA_05_6C_68_64_62_60"
)
),
.AA_06_6B_6F_74_74_69_74: .init(
// More generated code
),
]
I was thinking about going even further and encrypting the basic assets, but given how Xcode asset catalogs work, I decided to optimize for performance and size instead of pushing that idea too far.
Another interesting thing that changed over the past 10 years is how I chose technology. I feel like previously I didn’t care that much. Of course, I would still look around a lot and base my decision on many factors, but at the end of the day everything was fair game. Now I’m much more reluctant to do that. In a way I willingly closed myself into the Apple garden, because I grew up there and loved the smell of those flowers so much.
So it’s not going to be a big surprise that the game was written in SwiftUI. It was my second game in SwiftUI, since I’ve always seen it as an interesting way to push the technology and explore new ways to build stuff.
So you might ask me: how was the experience writing this game in SwiftUI? Well, first of all, let’s be clear, it’s not really a “standard” game with a standard game loop. Nevertheless, I think it’s an interesting experiment (well, at least for me).
To be completely honest with you, my experience using SwiftUI was very positive. It wouldn’t have been as positive if I had written the game a few years ago, as a few very important APIs weren’t available at the time, but now it was a really nice experience.
In fact, I thought it was too good to be true, until… I was finishing up and started testing on more devices. The first thing I noticed on my old iPad was that for some reason I couldn’t move the letters.
I immediately knew the culprit was probably the .scrollTargetLayout()
API, because during development I’d already run into a few issues with it that I managed to fix. My theory was that it was just the iPad and that API not playing nicely. That seemed to be the case until I tried it on a newer iPad where it worked magically. My immediate reaction was to open Settings and go to the About screen.
Of course. iOS 17.
So I decided to try Googling the issue, typing “iOS 17 .scrollTargetLayout()”, and to my surprise, I got at least a few results. Not only that, but they had a real workaround.
While the following didn’t work:
ScrollView(.vertical) {
VStack(spacing: spacing) {
ForEach(Self.letters, id: \.self) { letter in
makeLetterView(for: letter)
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
Wrapping the inner view in a ZStack
or another container view suddenly made it work on iOS 17:
ScrollView(.vertical) {
VStack(spacing: spacing) {
ForEach(Self.letters, id: \.self) { letter in
ZStack {
makeLetterView(for: letter)
}
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
There was another fix using a lazy container, such as LazyVStack
, but it had other issues. Anyway, I was very happy because it finally worked. Until… I tried running it on iOS 17.0. It didn’t work there. So I performed a binary search to find the version where it started working. I don’t remember the exact version I landed on, but after looking at adoption stats and other metrics, I decided to just use 17.2 and forget about the issue.
Then I discovered that on iOS 17, my custom transition using a shader with .layerEffect
caused the view to disappear after a certain condition was triggered. I tried debugging, changing things around, but in the end I said: “Wait, what am I doing? It’s time to take off the developer hat and put on the entrepreneur hat.” What was the solution?
// Using shaders on iOS 17 may cause the view to become invisible
if #available(iOS 18, *) {
LGTM ¯\_(ツ)_/¯
And honestly, that’s the main thing that scares me about SwiftUI. Things can drastically change with each OS release. Sure, UIKit had the same problem, but not to this extent. On the other hand, I can say with confidence that with every release, SwiftUI gets more mature, and I feel like I’m standing on a much stronger foundation.
When I shipped my first game with SwiftUI 2, I had total “this will definitely break at some point” vibes. Now, I actually have confidence that things will keep working for the most part.
Maybe iOS 19 is reading this blog post right now with all its AI features and laughing at how naive I was. But even then, I regret nothing. Having a game that takes 5MB of storage, has access to all the built-in iOS accessibility features, and uses APIs that get me excited at every WWDC is well worth it for me.