Table of contents
In the previous post I wrote about setting up the development environment for Bim!, a PvP mobile game I develop to play with my friends and also to experiment with the Entity Component System design.
The project has progressed quite well since and I want to write a small report that is coming up below.
What’s new in Bim!
At the end of the last post we had a fully-functional terminal-based network game, as well as a basic Android application. It wasn’t much but it allowed to validate the tools, the dev cycle, and the implementation outlines. Since this post I have added many new things.
On the game-play side
I began by implementing the removal of the players when they are colliding with a flame. Then I made the game to stop when there is only one player left. Yes, very obvious, but if there is no code it does not happen…
Then I added a software joystick to control the player. I don’t like the feeling of those fake devices but I have nothing better yet. By the way, you’ll know that calibrating this is far from obvious, and I went through a lot of trial and error, switching between a d-pad and an analog stick. Handling diagonal move requests on a grid-based game, dealing with automatic avoidance of walls… This was not easy.
When the prototype game was running in a terminal I had implemented the player movement from one cell to the other, with no intermediate position. With the graphical application this does not work anymore. I have thus implemented fractional moves for it.
By the way, since we are talking about the terminal application, I had to drop this program. Since the player cannot be displayed between cells the two versions became somewhat incompatible. Either the player in the graphical application would see the opponent’s avatar jumping from one cell to the next, or the player from the terminal would experience a huge latency. I could have split the matchmaking according to the end device but I want to avoid handling too many use cases so I preferred dropping the terminal.
I have then added the code to drop bombs. Yes, I have implemented the flames before the bombs that create them…
Finally, I have added the power-ups for the bomb and flames, each one adding one unit of each for the player grabbing the power-up.
And with all this we have enough to play some games :)
Network
On the network side I had some surprises. First of all, some messages were incomplete when the system was under stress. Thus I had to add guards to ignore them.
I have also implemented an automatic connection to the game server when the app starts. Without that, no network game. Then, this being set, I have added the ability to send a game request when the player clicks on the “Play” button. Then I have added the game creation on the server side, and the game proposal from the server to the players. They have to confirm it, and when all players have accepted the game the server sends a signal to launch the fight. All of this was quite easy since the protocol was already available in the terminal client.
Regarding the matchmaking, I initially thought about grouping the players in a room identified with a name provided by the user. It was actually quite complex, and since it would need some UI to get the room’s name, I eventually put that aside in favor of a grouping in the order the players come. Put simply, if you launch a game you will play with the player looking for a game at the same time, with up to four players in a game.
Tooling for the development
I have added localization with Gettext. It was not as simple as it could have been because I wanted the .pot file and the associated .po files to be updated during the build. There are some CMake commands related to Gettext but nothing like what I needed. I thus had to hack masterfully implement, using CMakeScript, a collection of the sources from the targets declared in the CMakeLists.txt, then to create a new target generating the .pot from these sources. Once this was done, going from .pot file to the compiled translation files is quite easy.
As usual it could not be this simple. Unfortunately I also have some strings to translate in the resource files. For this to play well with xgettext
I have added a Python tool to extract those strings and to put them in a C file to be processed by xgettext
, all of this with correct dependency relations. It looks like this:
resources
|
v
Python source code
| |
v |
xgettext <---------+
|
v
.pot .po
| |
v |
msgmerge <--------+
|
v
msgfmt
|
v
.mo
I’ll skip on the part where I had to tweak the build to avoid a systematic rebuild of all localization files when generating of the .pot file, because this .pot file embeds the current date. Thus even if the content has not changed, the date has changed…
A small surprise emerged from the ThreadSanitizer tests failing randomly at launch. It happens that this tool, as well as AddressSanitizer, does not like ASLR much. If you ever encounter a crash at launch time of a program compiled with these tools you’ll know that it can be solved with sysctl vm.mmap_rnd_bits=28
(cf. bug #1716 of these tools).
Last but not least, I have added a Docker container and the scripts to deploy the server.
Aside from this, I have added some small things like compiling with -Werror
and writing .gdb
files in the release builds.
Note that I did not have to touch anything from the build environment in the CI, which is quite cool.
Coming next
I still have some gaps to fill before releasing a public build. First of all, there is no way to play twice in a row. Once the game is over the user has to quit and launch the app again to play a second match. Then there are some game-play tweaks to implement: the bombs explode too soon, the feeling when playing with the stick is not great, the player should be blocked by the bombs, and a couple of other things.
Ideally I should add a small latency on the inputs to avoid seeing the other player jumping from one position to the next. This is not essential to play but it would be more pleasant.
In the comments of the last post a very smart person said:
there would probably be a lot of research to tell what is a good automatic test for a game.
Well, I can say that the few tests I had implemented did help me quite well in the development by validating the functional parts before switching to the graphic rendering. They are very simple tests like “flame + player => elimination of the player”, or “flame + bomb => the bomb explodes”. I also have some tests launching a server and some game requests, to validate the protocol. Moreover, ECS is really good at this: No need to create the whole world to test one thing, I just have to create the entities with the expected components and I can run the systems independently.
In the last weeks I skipped the tests on the new features and I must say that I missed them quite quickly. I know that as soon as I’ll have to touch these features again, for example the power-ups, I will be afraid to break something. Tests are good.
Finally one thing that misses a lot in the game are good graphics. On this part I would like to let someone who actually knows how to draw taking care of it!
Guaranteed drawn with the touch pad.
Where can I get it
There is no public build right now but if you really want it you can clone the repository and type ./setup.sh --help
. You should then find your way to build the Linux app or the Android one. The game will automatically connect to the deployed server.