Table of contents
I’ve published a new version of Bim! and it’s without a doubt the best version published so far. Let’s see!
News
- New game assets by Aryeom: the player’s avatar, the bomb, the flames, the crates.
- More new game assets: sprites for the walls and the ground.
- Added the possibility for the players to pick the gameplay features for each game.
Let me tell you, the update is worth it just for the assets! On the gameplay side the player can enable blocks that will fall after two minutes to reduce the arena’s area. It causes an adrenaline boost and allows to conclude long games.
| In-game screenshot | Matchmaking |
|---|---|
![]() |
![]() |
Seriously, you should try it, either by installing the APK directly, or by sending an e-mail to bim-game@gmx.com. Give me your PlayStore e-mail address and I will add you in the tester list, then you will be able to install the app directly from the PlayStore (Pick this solution, I need testers in order to publish the app).
Let the installation going while we go into the development story of this version. As a reminder, Bim! is free and libre open-source software, code and assets. It’s a game in the last-man-standing arcade genre. It runs only on Android and the games are exclusively online. Consequently it’s better to synchronize with an acquaintance before launching a match, otherwise the game won’t find an opponent for you.
Dev stories
About the gameplay novelties
The activation of optional gameplay features are implemented with a logical AND: we need all players to have activated the feature for it to be applied in the game. This is a practical decision as it allows me to add features in the next versions and to simultaneously permit players with different versions of the game to play together.
On the other hand I wonder if a logical OR wouldn’t allow the players to discovers stuff they don’t have, which is stimulating. I’m still on the fence about it. I believe it could be very frustrating for the players who enable a feature to end up in games without said feature.
As I’m writing about it I’m thinking that I would need three states: if the player has deactivated the feature, the game does not use it, but if the player has not unlocked the feature yet, and that another player turns it on, then the game uses it.
A word about memory consumption
Soon after the previous release I received this intriguing message:
If we can’t play, it’s because there’s no one online?
Well, answering by the affirmative is tempting, but I wonder: what does this user mean by “we can’t play”? I launch the app, the button to start a game is disabled. Mmh, it does not smell good, I open a window. From there I attempt an SSH connection with the server. Crickets… Ok, nothing works, I reboot the host and keep an eye on the logs. It seems that the RAM has been exhausted. I switch into surveillance mode.
After a couple of games the obvious is here: the memory consumption is huge. Thankfully I’ve learned my lessons: Engineering time is expensive, memory is cheap. Consequently I buy a larger instance.
Just kidding, I still have some pride left. So let’s go for an analysis. The possibility of a memory leak is quickly rejected because other tools would have reported the issue sooner. I put my bet on an ever growing resource instead. In order to confirm this hypothesis I start Heaptrack and I script a series of matchmaking requests followed by a match.

Heaptrack is an awesome tool. There’s a view of the memory usage over time where I can see two things. First of all it increases constantly before quickly falling down, which is expected. Indeed, since the client-server channel uses UDP, the server does not know when a client has left. It compensates with a clean-up pass from time to time in order to remove clients who have not given news in a while. I observe that each peak is a bit higher than the last.
Secondly I can see many allocations related the the server’s scheduler in this view. Far more than expected. After a quick analysis it can be easily explained: I had implemented the removal of a dead client by scheduling a clean-up 30 seconds after a message from it. In other words, on each client message I scheduled a callback; and thus the callback queue kept growing rapidly, stacking calls that would be eventually ignored. Not smart!
I have rewritten all of this in a cheaper way. Now I keep for each client a timestamp after which it can be removed. When a client sends a message, I update the timestamp. Aside from this, I schedule a removal of disconnected clients on a fixed interval. This way it does not accumulate.
And since I was in the memory consumption topic I jumped on the
opportunity to have a look at temporary allocations. There were so
many! A lot of them were tied to the scheduler and were more or less
tamed in the previous paragraph. Then came the messages sent between
the client and the server. This one was simple to reduce: I just have
to recycle the messages. And finally there was the obvious: the many
operations on
std::string. Classical. Thankfully
this was happening only in the context of logs displayed in the
terminal, which are deactivated in production, thus it was not an
actual problem. Yet I’ve still rewritten some parts to have fewer of
them.
Power-up placement
There’s a feedback I have since the first playable version, which is that the power-ups are always located at the top of the map. First of all, it’s very wrong, as we can clearly see that there are power-ups in the bottom part too; but also come on, I know I have implemented a random placement. So in order to prove to those losers that everything works as expected I have generated 1000 levels to build a heatmap showing the power-up distribution. The brighter it is, the more frequently there is a power-up in the cell:

Oh sugar…
Well ok, let’s see the code of the level generation. Ouch! a random followed by a modulo… and a swap that will cause excluded cells to come back into the pool! Well well well, how sloppy.
Now I remember that when I had implemented this I took the shortest path while thinking that I should, at some point, replace it with you-know-this-algorithm (Fisher-Yates). Clearly, it went off my mind. So be it. After fixing the implementation we get better results:

Meh, there’s still a problem with the cells at the top. Once again this is the result of taking shortcuts in the initial implementation. I use xoshiro256plusplus as the game’s random number generator, whose state is made of four values. I initialize the first one with the game seed and I leave the three other to zero. How a bad idea! xoshiro256plusplus does not play well with zeros. After having correctly initialized the generator I get this:

Far better!
A short digression. A few weeks ago I watched a great talk by Mike Acton. He can be quite radical and at some point he said something that picked my interest. It was about prioritizing during implementation, in essence that one should avoid future-proofing and that whatever is coded today in anticipation of a future need, a problem that does not exist today, is certainly going to be a bad solution when the problem actually presents itself, if ever. Indeed, by the time the actual problem happens we will have improved as programmers and we would code the solution differently if we were to start from a blank page. Until then, all the code about it is a handicap. I’m quite in tune with that. Then he adds something along the lines of: start with the most direct implementation, as if you have to deliver tomorrow, and only then, if you have the time, you can tweak your code.
I struggle to decide how to use this advice. It looks like a good idea to me, but on the other hand if the constraint is to deliver tomorrow I expect to see stuff like global variables, high coupling, dynamic allocations everywhere, and other bad things. It does not fit with the rest of his discourse. In my opinion a good share of the difficulty in programming is to find a good compromise within the available resources, without doing too much but also without botching the work.
Because of this talk I wonder if it was a good or a bad idea to implement the level generation the way I did. On the one hand it allowed me to move faster on other aspects of the game, on the other hand it clearly was an unsatisfying implementation.
End of the digression, let’s come back to our levels. Now that the power-up distribution is correct I inform the other members of the family and we start a game. First bomb power-up: in the upper part. Second bomb power-up: also in the upper part. Third power-up, same… Then the flame power-ups: all in the bottom part. Argh! The structure of the code is popping in my mind, there’s no doubt about the cause of the issue. I do pick the cells randomly, but the selection is sorted when I assign the power-ups!
| Bomb power-ups | Flame power-ups |
|---|---|
![]() |
![]() |
I implement a shuffle of the cells before assigning the power-ups, and finally:
| Bomb power-ups | Flame power-ups |
|---|---|
![]() |
![]() |
Graphic design process for the new walls
Hey, while we’re here… Since I had to do a bit of graphic design for this release, I’m going to talk about the process. As I’m neither a graphic designer nor an illustrator I always struggle with my drawings.
The idea is to create some wall assets to replace the grey boxes from the previous releases. I want a feeling like the RPGs from the 90s, with a view halfway from above, thus I begin with an image search to soak up the style, then I do some rough drawings.

After that, I do a bit of research to get some texture ideas, and I draw the sprites.

Well, it works, but… I dunno, I don’t like it. Too realist, too dark, too detailed. This is not what I want. So I get back to some research, I look at how it’s done in other projects, then I come back to the sketchbook for a small study. When is it too detailed? When is it too empty? How to express the intent with few lines?

In this panel I’m trying to find key elements. A single block in depth, two in height, it’s enough. I like the height offset between the upper blocks too. This time I use brighter colors and more contrasted tints.

A-ha, this is far better!
About delivering for the app stores
On F-Droid’s side all I need is time and motivation. I finally managed to create an account on GitLab but I don’t like it. I had to use an old e-mail address that I don’t use anymore, and that I intented to abandon, only because they require an “enterprise” address. This is stupid, just allow me to connect as an individual, then I will be able to push to use GitLab at work! I will have acquired experience with the tool on my free time and that will weight in the balance in an eventual migration. Forcing the user to jump through hoops to register is useless. I’m registered now, and I’m still not an enterprise… Moreover F-Droid is a store for everyone, it makes no sense to prevent individual contributions to it.
On the PlayStore’s side, the deployment is in progress. I spent two hours filling their forms, it was painful. I also had to produce a privacy policy and illustrations late in the evening in order to complete their thing (I could have postponed to the day after but as I was in I figured I would finish). I also had many warnings when uploading the bundle. First of all I had no bundle but an APK instead, thus I had to find how to produce a bundle. Then I had issues with the emission of debug symbols because the Gradle build did not find the expected NDK version.
Once uploaded the store told me to fill additional forms to justify the READ_PHONE_STATE permission. Mmh, I don’t need the phone state in my app, where does it come from? I discovered that the Android build produced a file with the reasons behind each implicit permission, very useful. It happened that some dependencies did not declare the minTargetSdk field, or declared it incorrectly, which had the side effect to fall back to an older SDK for which this permission was automatic. Once fixed, the upload passed.
The final step before being able to publish the application on the PlayStore is to run a closed test with at least 12 testers during at least 14 days. I need more testers! If you agree to help all I need is your PlayStore e-mail. I will add it in the tester list and you will be able to install the app with this link. I won’t do anything else with this address, obviously, but you have to trust me on this. As for Google, I’m pretty sure that they already know this address :) Send your info to bim-game@gmx.com to join. Thanks!





