Project: Video game

Project: Video game

Motivations

In order to compete my exploration of Zig, I decided to write a "big" application. This project will allow us to see how Zig fits in a larger project since till here we have only written some applications.

The project I decided to go with will be a video game in the style of games like Travian. Which means it will be a multiplayer game where players can construct their villages, build armies, and attack other players (and much more but those are the basics).

The components I am going to need are the following:

  • A WEB server to handle the requests from the clients, this will contain the game logic.
  • A database to store the game state and player informations.
  • A frontend to display the game to the players.

Multiple solutions are possible for each of those components, I am going to discuss in the next chapters what I choose and why.

Architecture

The overall architecture of the game will be the following, here we have an example of a typical use case of a user wanting to build an archer for his army.

/HEIG_ZIG/images/architecture.svg

Since I will be using authentication and that some data might me sensible it is important to use HTTPS, since Zig does not support TLS I am going to use a reverse proxy like Nginx to handle the HTTPS. Since the NGINX and HTTP server are both going to be on the same machine, the security risks are minimal when both communicate in a non-encrypted manner.

Having that reverse proxy is mostly useful for security reasons and have no particular link with Zig so I will only do it if I have enough time.

/HEIG_ZIG/images/https.svg

Frontend

For the client application there is minimum one requirment being that the client has to be able to send and recevie HTTP requests. If I am using anything Zig related this should not be an issue since there is an HTTP client in the standard library. But a frontend in Zig is not a very common approach, but still I found some possibilities.

Note that my game will not need any 3D, it is a strategic, simulation, management game. So every actions can be done by just sending a simple order (POST request) and any information needed can be retrieved using a GET request.

CLI

The simplest solution would be to have a CLI frontend, this would be the easiest to implement and would be the most Zig-like solution. But I will not go with that for 2 main reasons:

  • It will not be pleasant to play a game where you build your village, your army etc with 0 image and graphical experience.
  • It is contraigning for the player to have to install the game on his computer and run it in the terminal.
Terminal User Interface

With a TUI like libvaxis I could have a better graphical interface than with a CLI, but still it will lack the graphical experience that I want to provide to the players.

Native GUI

Capy is a GUI library for Zig, it is still in development but it is the most promising solution for a Zig GUI. Even though it does not fit my needs, not being able to force a style to the GUI is a big issue for me. Also it seems very hard to make pleasant designs compared to using HTML+CSS.

WebAssembly

I thought about WebAssembly, but it will not be a possiblity since WebAssembly can not manipulate the webpage but can just communicate with the JavaScript. So I would have to write most of my frontend in JS aswell which loses the interest I had for Wasm. You can find more informations about this here.

ImGUI

ImGUI is a C++ GUI library that is very popular to make complex native UIs. There is a C wrapper for it, so I could use it in my project. And there is yet an other Zig wrapper around this C wrapper. The problem with this Zig solution is that it has been abandoned for 2 years nows and there is no other contributor than the author itself. Other than that the C wrapper and the library in general seems way more complex for my needs.

Templating engine

An popular solution for building web frontends is to use a templating engine, most of the Zig web frameworks I explored have one. But the problem with that solution is that I would have to change the architecture of my project, because of sending JSON responses I would send the whole HTML pages with the data in it. For me this is not a good solution as it put too much load on my server and will not allow me in the future to have a mobile application for example because my API will be returning full HTML pages instead of just the JSON data.

Solution: Classic web frontend

This is the most classic way of doing web applications, but even with this approach there are multiple solutions. I could use a frontend framework like React, Angular, Vue.js, Svelte, etc. Or simply use HTML+JS. Since I have almost no experience with any except a bit with Vue.js I will go with this solution. Note that here it really depends on the developer's preferences.

Backend

In my WEB documentation part I discussed about a lot of different solutions for the backend, but I will only explore to me relevant here, if you want to see the other alternatives for making HTTP servers feel free to reed it.

For this project as a first cireteria I want my server to be performant, meaning that it should be able to handle a lot of requests per second. Since I will be doing a massively multipler game I need to be able to handle all the requests from all the possible players.

The second criteria is that I want to have as less batteries included as possible, the reason for that is that I am mainly here to learn Zig and doing things like I had to handle cookies in httpz is what I like. This way I can truly understand in the process how a web server works and mainly how to make it work with Zig. This is important because I do not want to just learn a framework but rather learn the language. To sum up I prefer to write more application code rather than specific framework code that do not really translate into other projects

/HEIG_ZIG/images/batteries.png

The third criteria is that I need good support, I either need to have some kind of way of communication with the community or a good documentation. It is going to be very important since I am neither a WEB expert nor a Zig expert.

Other than that everything else are just bonuses, but note that having a templating engine is not a criteria at all since I will only be serving JSON data to a client that is then going to handle those data by himself.

Zap

Zap is a wrapper around the C library facil.io, it is the most popular choice to make WEB servers in Zig. The reason I am not going to go with it is that the community is not really helpful and this can be a major issue that could cause me being stuck on some isses for a long time. I also personnaly find that there is too much boilerplate even compared to other low level frameworks like HTTPZ but this is a personal opinion and it might depends of your use case.

Jetzig

Jetzig is a great 100% Zig web framework, since everything is in Zig and there are no weird C wrappers for which seeing the implementation is very complex, it is very easy to navigate the codebase. The discord server is also very helpful and the documentation is very good. The only two minor issues I have with this framework is that it might not be as performant as the other solutions, even though it should not truly be a problem since I probably won't have millions of players 🙃. The second issue is that it might be a bit too batteries included for me, I am not a big fan of needing a CLI to create new endpoints, middlewares and so on. I also find the way the project is structured in so many little files a bit confusing to me.

Solution: HTTPZ

HTTPZ the WEB server under Jetzig and Tokamak is the solution I am going to go with because it meets all my criterias. The performances are top notch, it is low level enough so that I can freely structure my project as needed and learn Zig along the way, the author of the framework himself answers my questions on Discord and the documentation is very complete.

Database

The database is needed in my project in order to persist the data and not have it live in the memory of the server. This is useful because as the project grows I might need to have multiple servers and sharing data across them might not be the easiest task, so having a centralized database is a good solution. Having a database is also useful to avoid losing all the data after a server restart.

I only have 2 simple criterias for the database. The first is that I need it to be as easy as possible to integrate in my project, and the second is that I would prefer a SQL database since I am already familiar with SQL queries.

Solution: SQLite

Since it is only a file and does net require tons of installation or running an other process on my machine I decided to go with SQLITE.

The SQLite database could also be run on the same machine as the server if we only have one server, allowing low latency between the database and the WEB server. Thus making requets 2 and 3 faster.

In Zig there are 2 main ways to integrate SQLITE in our project.

The first is to simply use the C SQLite library, as we have seen already it is very easy to use a C library within a Zig project making it a very decent option

However if I found a Zig wrapper around that same library that includes a few other features like checking the paramaters of the query at compile time. It also has the advantage of giving the feeling that I am using a Zig library, thus not having to wrap my head around the such concepts as C pointers or other C specific features.