For Up There They Love, my upcoming visual novel and character management sim, I am not just programming the entire game. I’m also creating my own engine. 🤷♂️
Any experienced game developer will tell you that it’s a fool’s errand to create your game engine. If you want to make a game, do it in an existing engine. Otherwise you will end up with a half-baked engine thing that will constantly be in your way when you’re trying to make the actual game.
Unfortunately, the best way to get experience is to make a lot of mistakes. Which is why every experienced game developer has a veritable graveyard of half-baked engine experiments somewhere on a forgotten hard drive.
To give you a bit of my background, I have worked in games industry professionally for over eight years now. In that time, I have shipped many titles, including Really Big Games that you’ve definitely heard of. And what I do for those games is pretty straightforward: I make the buttons clickable.
I’m a UI programmer. I love diving into engine code and figuring out some obscure rendering bug, but I also love talking to artists, designers and playtesters about how to make the game experience better.
When I got my start in AAA games, Flash wasn’t dead yet. Many titles used Scaleform for their UI, which allows you to render Flash movies on top of the game. This is actually less insane than it sounds! Scaleform is optimized for performance in game engines, while Flash allows the UI artists to be extremely flexible and creative.
That’s not to say that it’s a perfect workflow, though. Flash allows artists to do crazy things. I’ve definitely seen graphics programmers cry when they had to get the UI running smoothly on consoles…
In any case: Flash is dead, long live Flash. The new gold standard for game UI is HTML 5. And the best way to get HTML 5 in your game is with a package called Coherent UI. This framework allows you to render web pages on top of your game, similar to how Scaleform works with Flash.
At a previous job, I was able to evaluate Coherent for our game. At the time, we were struggling to get click & drag working for our menus. We ultimately spent about three weeks on that feature alone. With Coherent, I was able to import jQuery and jQuery UI and got click & drag working in under an hour.
I wanted to learn more about this magical new world of HTML 5. I needed a side project, something to hone my skills on…
Sexy games to the rescue
And that’s why I started experimenting with HTML 5 for my sexy character management sim. This allowed me to get started straight away, without getting bogged down in low-level details like text rendering and sprite animations. When I use HTML 5, those problems have either already been solved or I can plug in an off-the-shelf solution.
The big question that remained, though: can I do this on my own? Can my frontend be done in HTML 5, with the game logic done in C++?
Turns out that the answer is yes! It’s not entirely sane, but it can be done!
Here’s how it works: I have an executable that runs the game logic, written in C++ with the Qt framework. This is what I will refer to as the “backend” of my game.
This executable starts a local webhost on the port 1443. You can visit “localhost:1443” in your browser and the executable will give you back HTML, CSS, JS and image assets, just like any other webhost connected to the Internet would do.
I also have an executable with an integrated web browser, using the Chromium Embedded Framework. This browser loads everything from “localhost:1443” and displays it in its window. This is what I call the “client” of my game.
But here’s the twist: both the backend and the client are the same executable!
The backend will start a webserver that hosts the game files, which the client (itself) connects to in order to render the game.
As a player, you will not notice any of this. You will be able to run my game just like any other application.
Why do this?
Turns out, there is actually a valid technical reason for doing this. This separation ensures a very strict and narrow interface between backend and client, which makes it much harder to tangle up one with the other. Instead of the client retrieving information about the state of the game by poking services directly, there’s a much more formal communication protocol in place.
When the client needs data, it can retrieve it from the backend by calling an HTTP endpoint. This is basically a web address with parameters attached. For example, requesting “localhost:1443/ajax/set_character_location?location=gym&character=1” from the web server will set Chichi in the gym.
Whether she’s up for it is another matter entirely…
This is always an asynchronous call, but the client is not that concerned with the answer. When Chichi is assigned to the gym, the C++ backend will serialize the state of the game and package it as a JSON document. This document is then transferred to the HTML 5 client via a WebSocket. The WebSocket is a connection that stays open while the game is running.
When the client receives an update on the game state from the backend, it unpacks it and updates the rendering of the game if necessary. I will write more about how serialization and rendering works exactly in a later blog post. 🙂
I have found that I can be very productive in this setup. As long as I don’t need to update the game logic, I can keep the server running in the background. I can then tinker with the front-end in the browser and copy my changes over when I like the result.
With CSS, I started out by writing it by hand, but I’ve found that Sass is much easier to work with. Sass is a generator for CSS that allows you to write macros and functions, which reduces the amount of CSS you have to write.
Oh, and I use Grunt for packaging it all up, because it’s good enough for my needs and I don’t care about your holy wars. ✌
Although the architecture is intended for an offline experience, I could actually turn it into a web game. Because I already have a clean separation between backend and client, I could host instances of my backend somewhere and have players connect to them via a web client.
That’s a bit of a pipedream, however. For one thing, I would have to tighten up security a lot for it to be remotely feasible. At the moment, the backend doesn’t do any authentication and it doesn’t support the concept of different players connecting to the same instance.
So I’m going to keep my dreams a lot smaller: I want to ship a solid offline experience. And I also want to continue to be open about the process.
I hope you’ll continue to read my posts! If you want to poke me directly, you can always do that on Twitter: @mrhands31
Thanks for reading!