Flappy Bird in C for Android weighs only 92 KB APK

Greetings to all!
The impossible is possible, and today's article will be about that.

Story

It all started back in 2021.
Then I came across the repository rawdrawandroid. There was a motivation to make some game with the smallest possible APK weight, but at the same time, so that the game would be simple and understandable. At that moment, an idea appeared to make a clone of the long-forgotten game Flappy Bird. Which has already been ported to many programming languages.
Then, later in 2021, I found another interesting repository Raylib.
But, the first attempt to make this game was in C++, using ImGuibecause I was already familiar with him.
And so, all the difficulties were presented in Android Native Activity and building a clean APK from apktool.

The first attempt failed.
Firstly, the APK weight was about 1 Megabyte.
Secondly, the game could crash.
Thirdly, inside the APK there was only a library for armeabi-v7aand from 2022, Google's rules require the presence of arm64-v8a libraries.
Fourthly, the project structure and its organization were terrible, it created confusion in the eyes and made it difficult to navigate the project normally.
And fifth, it was nothing like Flappy Bird.
In general, I tried, it didn’t work, the idea was in my head throughout this whole time, but no more attempts were made.

Motivation

Around September 14th 2024, I saw a guy on Raylib's discord channel make Flappy Bird in C#.
Then I became very interested in trying a long-forgotten idea, to make this game in C, for Android, with an APK weight of less than 100 kilobytes.
Idea seemed crazy, and also unsuccessful.

Just imagine, today, when the weight of APK reaches 30-600 megabytes, you need to fit in just less than 100 kilobytes.
What are these frames for? It's a sporting interest, will it work? It did! But it wasn't easy at all.

The beginning of the journey

At first I made a small solution without Visual Studio using batnik which performed the following tasks:
1. Compiling Hello World in C.
2. Sending the finished library to the APK archive
3. APK packaging
4. APK Signature

Then I switched to Visual Studio and configured it there; I had to modify the batch file a little so that the finished APK would be sent to my phone for testing.

The less weight, the better

The task is to achieve the goal – the APK file of the game should not exceed 100 kilobytes.
It was necessary to understand how to implement all this so that everything works, and on two architectures: armeabi-v7a and arm64-v8a. Every byte counted!

The initial analysis, running through the resources, made it clear that the main weight is media files, pictures and sounds. I did not deal with them right away, but later.

Search for libraries. Basis for the game

Then the search for libraries began.
I had experience working with ImGui, Raylib, Rawdrawandroid, but they all do not fit my goal, because in the end they weigh a lot, except for the last one, there were chances, but there is extra code that I do not need, and cutting everything out would take a lot of time. Therefore, it was easier to implement everything from scratch.

I decided on the graphics, it's OpenGL ES 2.0. Then I had to solve three problems:
1. Shaders (never worked with them, learned thanks to this project)
2. Correct rendering (posX, posY, width, height for each required element)
3. Auto-scaling of elements (automatic scaling for any screens and it seems to work well)

Sound

I used to use BASSbut it doesn't fit because of the weight. I heard about dr_libsbut as it turned out, it didn't suit my task either, because it ended up weighing a lot, and besides, decoding the sound is not enough, you also need to play it. So I learned about OpenSLES, which solves two problems at once: decodes mp3 and plays it. Although it's not a simple solution, it can be done.

Everything related to sounds is stored in the project Here

In short: the sound is played, a player is created, after playing 5 such players, the previous ones are recreated and new sound is recorded into them.
There may be more players, my phone supports up to 30 players, but optimally I made the limit 5.
*players are sounds that can be played simultaneously.
We had to tinker a lot with the sounds, but the result is excellent.

PNG

In my memory there were only stb_image.h. But, although it is minimal, it also weighs a lot and is not suitable for me. Therefore, in my searches I came across such a UPNG repository. It supports very little decoding compared to stb_image, but it managed to implement everything (I really hoped so).

The resources for the game are taken partly from the original game, but mostly from the repository Flapper (pictures and sounds). However, PNG files did not want to be rendered right away, they were full of artifacts. Therefore, after re-tweaking Photoshop, I managed to find “working” export settings after which PNGs were rendered as expected.
ps I also tried to compress png in various ways, but I ended up with artifacts. I can't take another png decoder library because of its weight, so I had to stop at this and without compression.

Bugs

They exist. For example, you can notice the stretching of the green columns in height, how it shrinks or expands.
Also, the score/share buttons don't work, the functionality for them wasn't implemented, but they had to be left. it would be a shame to waste something good

Unboxing

On different devices, the weight of the installed application was different, what is the reason for this is unknown. On my Samsung it showed 150 KB, and on my friend 240 KB.

Useful links

My Flappy Bird Repository

Download and test the game you can here

Results

The goal has been achieved and everything works!

p.s. I didn't want to complicate the article by inserting code from the project, so there is no code in the article. In general, it described what and how was done to achieve the result and what I encountered.
pss about how to compile and build this is in the repository readme

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *