Game Engines (and why should you care?) - Intro

Yuriy Georgiev, 13.Aug.2022

This article is primarily for people who are new to the term “Game Engine” and don’t know what exactly it involves.
Before starting talking on the topic, let me clarify several things right from the beginning.

First and foremost, when I say “game engine”, it’s exactly what I mean — an engine that powers a byproduct (the game created with it), not simply a game. The Game Engine is a software infrastructure developed to build games. It includes not just the code that will power the game but also tools that help design the gameplay and the levels.

Second, what I mean by the title is not that you should start programming game engines or specialize in that area. Not at all. What I mean is that the game engine development community has pioneered many creative solutions over the years, and we really should care about that. The whole industry may benefit from the wisdom generated over the years.

And third, whenever I mention “game engine”, and do not clarify something else, I will mean a 3D first-person game engine coded from scratch.
“Coded from scratch” is an essential detail here because it suggests encountering and solving problems on your own, without the help of a 3rd party library or framework.
I’m talking about 3D first-person engines because this is the area I have the most experience in.

Okay, after getting those small details out of the way, I can start supporting my statement about why we should all care about game engines.

Game Engines are one of the most sophisticated pieces of software I’ve ever encountered over the years of my career as a software engineer. John Carmack himself stated that game engines are more sophisticated even than building a rocket. And I tend to believe that. After all, he is a household name in the gaming industry on his own and a rocket engineer who created the startup Armadillo Aerospace — focused on building a crewed suborbital spacecraft capable of space tourism. They managed to contract and work on projects for NASA at their prime. I believe he knows what he is talking about.

A Game Engine is not simply a piece of software made to run a game. It’s way more than that.
A Game Engine must pack a relatively high amount of functionality to achieve even the most minor features expected to be supported by a game, compared to any other kind of software. And those expectations only rise over the years.

A Game Engine usually packs several smaller engines (also called subsystems), such as a Physics engine, A.I. engine, Rendering engine, Sound subsystem, just to name a few. Meanwhile, it has to orchestrate all game objects, handle events, manage a pseudo-database that keeps track of the state of a given game, etc.
All of that has to work in conjunction and perfect sync. And on top of that, the whole thing has to keep running at the maximum performance possible, no matter what.
And this is where a Game Engine differentiates itself from most of the software out there. Everything must happen in real-time. No matter what.
While you can wait a few more hundreds of milliseconds for your image to get resized or rotated in Photoshop or your Browser to interpret the javascript snippet, this could be a deal breaker in a fast-paced 3D first-person shooter game.
The minimal amount of frames per second that a player is relatively okay to accept is 30. That’s a frame every 33.3 milliseconds. And this is the bare minimum. Nowadays, everything below 60 FPS is considered a low frame rate. 60 FPS means a frame every 16.6 milliseconds.

[*Why 60 FPS:
Nowadays, the minimum non-gaming monitor refresh rate is 60Hz. That means it refreshes all its pixels 60 times a second. Therefore 60 FPS are required to feed the monitor without making it starve.]

So all those subsystems have to be orchestrated in a way such that they can compute their final results the fastest way possible in order to meet this deadline of generating a picture in 33.3ms minimum. In other words, the Physics engine, the sound subsystem, the A.I., and all the rest, have to do their job for less than the total amount of time required to generate the final image. Of course, nowadays, we have multi-threading and faster GPUs dedicated to splitting the job and working simultaneously on different parts of the computations, but with new solutions come new issues. Cache synchronization, for instance.

As you probably start to understand, things are a bit more complicated than they seem on the surface.

The one universal issue the developers struggled back in the days of Wolfenstein 3D and later on DOOM, Duke Nukem 3D, etc., is the same today — performance. It’s just that the hardware of today provides solutions to some of those issues but opens new, different challenges.

In fact, unlike what common sense dictates to us, performance optimization is even more critical today.
Let me explain.

If you had Wolfenstein 3D targeted for an Intel 286 (running at up to 25Mhz) back then, that means non-optimized code would make a hot-loop miss N percent of performance that optimized code could otherwise achieve. Where N% is, let’s say, 1000 CPU cycles. When you run the very same code on a faster processor, this hot-loop will execute many more times for the same amount of time, causing it to miss even more cycles. Missed performance accumulates with the increase of the hardware horsepower. You push the CPU to execute poorly optimized code many more times in a second.

Now apply that issue to a device powered by a battery. Your phone, tablet, or laptop would lose more power to compute something that could be less power-hungry if optimized, saving battery life and achieving the same result.

The same is valid for all these services running on huge server farms. Big companies use server farms to perform a lot of computations. And energy efficiency is a critical factor there. Two of my patents in VMware are related to this kind of issue — energy conservation by optimizing efficiency.
Big companies have regulations on what’s called Carbon Emission Credits.

[*Carbon Credits:
A carbon credit is a kind of permit that represents 1 ton of carbon dioxide removed from the atmosphere. Credits can be purchased by an individual or, more commonly, a company to make up for carbon dioxide emissions that come from industrial production, delivery vehicles, or travel. Companies can also trade their carbon credits with each other.]

What could the software industry learn from the Game Engine Dev community?
The answer is simple — the importance and benefits of performance optimizations. And more specifically, the creativity involved in all those tricks that game engine developers pioneered over the years.

Let me give you an example of creative optimization, pioneered by non-other but John Carmack himself.
Back in the days of the first IBM PCs, the holy grail in sidescroller games was the smooth scrolling. But that was only possible on the Super Nintendo Entertainment System (SNES) at the time due to its powerful custom processor that supported fast graphics rendering.
At the time, the screen buffer for a frame in a game was a rectangle with the size of the screen. So, you must switch to the next “picture” when you reach the edge of the screen in order to go further on the level. That involves rendering the following frame and transferring it to the frame buffer. On those slow machines, that took time. So, you end up freezing the screen for a while until the next frame is generated and displayed. Those who have played Dangerous Dave by John Romero on MS DOS know what I mean.
What Carmack did was a straightforward and simple solution.
He used only the frame that is currently displayed on the screen, however, when a boundary of the screen is reached, he replaces only the objects that differ from the previous frame.
At the time, the scenes were simple, with solid colored background and just a few tiles and sprites.
So, replacing them was just a matter of replacing old objects with pixels with the background color (in order to clear them from the screen) and drawing the new ones, essentially ending up replacing a few rects of pixel data in the frame buffer—all this information about what to replace where is held in the data structure of the level.
Nowadays this technique is known as adaptive tile refresh.

That’s a creative, conceptual form of optimization. As you can see, optimizations can happen on different levels — it’s not only a matter of code optimization but also a matter of the approach you will take to attack the given problem. One problem mostly always has different ways to be solved.

But what is the way to optimize via creative coding? There is no one specific definition of “creative coding” as far as I’m concerned, but there is a very clear, well-known way to do it.
Creative coding may require a lot of patience and self-discipline.
A lot of the times, it’s simply not enough to start improving your current algorithm until it gets transformed into a new, more optimized version of itself that has less to do with the original one.
It requires starting from the very beginning and attacking the problem from a completely different angle. And that could be a very mentally exhausting process.
As far as I know, the Quake rendering engine has been completely rewritten several times, especially its data structures. That caused massive frustration throughout the level design team since each time, all levels became incompatible with the new data structure.

Game Engines pushed the boundaries to their total limits in terms of optimization via creative coding over the years.
However, creative coding is not limited by the same constrain as the low-level optimization is, as it’s language agnostic.
You simply cannot do proper low-level optimizations while working with Javascript or some Intermediate-Language (IL) that uses a common runtime library (CRL) or Just-In-Time compilation. You don’t have the required amount of control over the final code produced and executed by the hardware. That’s not always a bad thing, though. JIT compilers and translators are getting smarter every day. Most of the times they are smarter than us.
However, it will never be the same as working with a lower-level language where you directly deal with the hardware or the instruction set for that matter, where you can experiment and measure performance so you can compare different approaches. This is pretty much a scientific method of learning and working.
Higher-level languages are great nowadays, but they also tend to rob you out from valuable knowledge. It’s way faster and easier to do something in a higher-level language, and most of the times it’s the preferred way to do so. But not if you are looking for optimal results. Working and depending on several layers of abstraction between you and the computer is not the way to become familiar with the hardware and learn how to write efficient code for it.

Game Engines are not simply tools to make games with. Sure, the final byproduct is a game. But if you think about it, you will see that it involves a serious amount of simulations. They are a bit more arcady so people can have fun. But they also can easily be tuned up to perform scientific simulations, architectural and industrial design, and, generally speaking — work that is beneficial to other industries with the required amount of precision.
You just stop calling them Game Engines at that point.

The subsystems involved in the game engines are really mindblowing sometimes and require an enormous amount of learning in areas different than programming.

For instance, while building my engine, Blast, I had to learn a ton of stuff related to physics, A.I. and math.
For instance, to simulate dynamic lighting, I had to learn how light works and interacts with the human eye. What is the complete life-cycle of the photon, from the point of emission till it reaches the human eye, and how does it transfers the colors it collects while bouncing off different surfaces based on their material.
While coding my physics subsystem, I had to deal with different issues, from the most straightforward problem of detecting and resolving collisions between objects to simulating Newtonian Physics, causing objects to bounce off each other in a physically correct manner when colliding. That required reading about physics and coding simulation tests until I got it right. Gravity was another feature I needed to implement.
Simulating all those stuff in a physically correct manner is both challenging and fun. It’s a highly educational process.
Once you get it right, you tune it up a bit to make it more fun. Since you are targeting a game as a byproduct of the engine, you constantly have to pay attention to the fun factor of each new feature you implement. With time you develop a sense of what is the right balance between physically accurate simulation and fun gameplay.

An enormous amount of work and constant learning are involved.
I highly encourage everyone to experiment with game development in their spare time. It’s a very educational process, and it’s a whole lot of fun.

Hopefully, I managed to wrap up the primary reasons why you should care about game engines and how they are developed. How they pushed people to invent new, more creative ways to deal with specific problems and that performance is more important than we tend to assume.
And most importantly, game engines are a serious piece of software, probably more complicated than any other software focused on single-domain problem-solving.
And that’s why they are an exciting topic to the hardcore software engineers.
As John Carmack stated in one of his interviews, “Quake is an operating system on its own”.