45.0 What this chapter gives you#
- You will be able to say exactly what makes a game different from every
other program on your machine, in one sentence, and defend it.
- You will be able to write a correct game loop with a fixed physics step,
an accumulator and interpolation, and explain every line of it.
- You will be able to do frame budget arithmetic in your head, and explain
why “average frames per second” hides the thing that actually annoys you.
- You will be able to describe how a real game project is staffed and
funded, from a one-person hobby project to a three-hundred-person AAA
title, with real money figures.
- You will be able to compare Unity, Unreal Engine and Godot honestly on
cost, language and licence, including the 2023 Unity fee episode.
- You will be able to explain what an asset pipeline does, why a build takes
hours, and what “cooking” content means.
- You will be able to work through a collision resolution by hand and check
that momentum is conserved.
- You will be able to run the A-star pathfinding algorithm on a grid by
hand, and explain why game AI is designed to be beaten.
- You will be able to explain client-side prediction, server reconciliation,
entity interpolation and lag compensation, and say precisely why you get
shot after you reached cover.
- You will be able to trace what happens between the double-click and the
first frame of gameplay, in twenty-five steps with real timings.
45.1 What a game actually is as a program#
PLAIN45.1.1 in simple words#
- Most programs are lazy. They sit still and wait for you to do something.
- A text editor draws your document once, then does nothing until you press
a key. If you walk away for an hour, it does nothing for an hour.
- A game is the opposite. A game never sits still.
- A game runs the same short list of jobs over and over, very fast, forever,
whether or not you touched anything.
- That list is: read the controls, work out what the world looks like now,
draw it, show it. Then do it again.
- One trip round that list is called a frame.
- At 60 frames a second, the game does this 60 times every second. That is
once every 16.67 thousandths of a second.
- It keeps doing it even when you stand perfectly still in an empty room.
- Why? Because the world keeps moving. Water flows, clouds drift, an enemy
walks somewhere far away, a timer counts down.
- The game cannot know in advance whether anything changed. Working that out
would cost more than just redoing the work.
- So it redoes all of it, every single time, on a strict clock.
- That one decision, “redo everything on a clock”, explains almost every
other odd thing about how games are built.
PLAIN45.1.2 a picture in your head#
- Think of two people who work in the same building.
- The first is a receptionist. She sits at a desk and does nothing until
someone walks in. Then she deals with them and goes back to waiting.
- Her day is quiet. Her energy use is low. Nothing happens between visitors.
- The second is a film projectionist in an old cinema.
- He cannot wait for anything. Twenty-four times a second a new picture must
be in front of the lamp, whether the film is exciting or boring.
- If he is late by even a fraction of a second, the audience sees a flicker
and the illusion of motion breaks.
- The receptionist is an ordinary application. The projectionist is a game.
- Now notice what this does to the projectionist’s job. He cannot go and make
tea. He cannot take a long phone call. He has a deadline every 41
thousandths of a second, all day.
- Everything about how he arranges his booth is decided by that deadline.
Where this comparison breaks: the projectionist is only showing pictures that
already exist on the film. A game invents each picture from scratch, having
first worked out what the world looks like at that instant. It is closer to a
projectionist who must also draw each frame in the time between showing them.
Also, real film runs at a fixed 24 frames per second and cannot be late. A
game can be late, and when it is, you see it as a stutter rather than a
flicker.
PLAIN45.1.3 a worked example#
- Take one hour of a person using a word processor, and one hour of the same
person playing a game.
- In the word processor, the screen is redrawn when something changes: a
letter typed, a scroll, a menu opened.
- A fast typist hits about 400 keys a minute, so about 24,000 keys an hour.
- Even if each key caused one redraw, that is 24,000 redraws in an hour.
- In the game at 60 frames a second: 60 x 60 x 60 = 216,000 frames an hour.
- That is nine times more drawing, and the drawing itself is far heavier:
millions of triangles instead of a page of text.
- Now watch what the machine does.
| Program state |
Word processor |
Game at 60 fps |
| Screen updates per hour |
~24,000 |
216,000 |
| CPU while idle |
near 0 percent |
one core busy |
| GPU while idle |
near 0 watts |
150 to 450 watts |
| Deadline per update |
none |
16.67 ms |
- The word processor has no deadline at all. If a redraw takes 200
milliseconds, nobody dies.
- The game has a hard deadline, 60 times a second, and missing it is visible.
- This is why your laptop fans spin up for a game and stay silent for a
document, even though both are “just a program”.
PLAIN45.1.4 what is really happening inside#
- Both kinds of program start the same way. The operating system loads them
and calls a starting function.
- The lazy program then enters a message loop. It asks the operating
system: “is there anything for me?” and, if not, it goes to sleep.
- Going to sleep is the key. The program is removed from the list of things
that need the processor. It uses no time at all.
- The operating system wakes it only when a real event arrives: a key, a
mouse click, a window resize, a timer.
- When it wakes, it handles the one event, redraws only the part of the
window that changed, and goes back to sleep.
- A game also has a message loop, because the operating system still sends it
events. But it never sleeps in it.
- Instead it asks “is there anything for me?”, takes whatever is there
without waiting, and immediately moves on to its own work.
- Its own work is: read the current state of every input device, advance the
simulated world by a small slice of time, and build a new picture.
- Then it asks the graphics system to show that picture, and starts again.
- The only place it ever waits is at the very end, when it hands the finished
picture to the display and waits for the screen’s next refresh.
- That single wait is what keeps a game at exactly 60 or 120 frames a second
instead of running as fast as the hardware allows.
TECHNICAL45.1.5 the engineer’s version#
- An event-driven application on Windows blocks in
GetMessage, which does
not return until a message is in the thread’s queue. The thread is in a
wait state and consumes no scheduler quantum.
- It redraws in response to
WM_PAINT, and the system tracks an update
region so only invalidated rectangles are repainted. On macOS the
equivalent is setNeedsDisplay and drawRect; on X11 it is Expose.
- A real-time application instead uses
PeekMessage with PM_REMOVE, which
returns immediately whether or not a message is waiting, then falls through
to its own frame code. This is the standard game shape and has been since
the Win32 era.
- The frame ends with a present:
IDXGISwapChain::Present in Direct3D,
vkQueuePresentKHR in Vulkan, [CAMetalDrawable present] in Metal,
SDL_GL_SwapWindow or eglSwapBuffers in the portable stacks.
- The swap chain holds two or three back buffers. With a sync interval of 1,
Present blocks until the display’s vertical blanking interval, which is what
pins the frame rate to the refresh rate.
- With variable refresh rate displays (VESA Adaptive-Sync, marketed as AMD
FreeSync from 2015 and NVIDIA G-Sync from 2013) the panel waits for the
game rather than the other way round, within a supported range, typically
48 to 144 Hz or wider.
- The consequences of the loop shape are measurable. A game pins at least one
CPU core near 100 percent and keeps the GPU in its highest power state.
A discrete GPU that idles at 10 to 25 W will draw 150 to 450 W under load.
- The other big consequence is memory behaviour. An event-driven application
can allocate freely, because a 5 ms garbage collection pause is invisible.
A game cannot: a 5 ms pause inside a 16.67 ms budget is 30 percent of the
frame, and a 30 ms pause is a visible hitch.
- This is why game code pre-allocates pools, avoids per-frame heap
allocation, and why C# game code is written to keep the generation 0 heap
quiet rather than in idiomatic allocating style.
| Property |
Event-driven app |
Real-time game |
| Blocking call |
GetMessage |
none, PeekMessage |
| Redraw trigger |
invalidated region |
every frame |
| Frame deadline |
none |
16.67 ms at 60 Hz |
| Allocation policy |
free |
pooled, per-frame zero |
- Tools that show the difference: Windows Task Manager and
powermetrics on
macOS for power draw, perf top on Linux for the busy loop, PresentMon on
Windows for per-frame present timings, and RenderDoc for a captured frame.
WORDS45.1.6 remember these#
- Frame — one complete picture — one iteration of the game loop producing one
presented back buffer.
- Game loop — the list of jobs done over and over — the input, update, render,
present cycle running at the target frame rate.
- Event-driven — waits until poked — blocks on a message queue and repaints
only invalidated regions.
- Present — showing the finished picture — handing a back buffer to the
display engine, optionally synchronized to vertical blank.
- Swap chain — the queue of pictures waiting to be shown — a set of back
buffers rotated between the renderer and the display controller.
- Vertical blank — the pause between screen refreshes — the interval in which
a buffer swap can occur without tearing.
45.2 A history of video games as technology#
PLAIN45.2.1 in simple words#
- Video games did not start as a business. They started as people playing
with expensive laboratory equipment.
- In 1958 a physicist wired an analogue computer to a small round screen so
that visitors to his laboratory’s open day would have something to do.
- In 1962 students at a university did something similar on a room-sized
computer, and the program spread to every machine of that type.
- The first machines you could buy for a home, in 1972, had no computer
inside at all. They were built from simple switching parts wired together.
- Then chips got cheap. Arcade cabinets became small computers with one game
burned into them.
- Then home consoles became small computers with a slot for a cartridge.
- Then home computers became fast enough to draw a three-dimensional world,
and then extra chips were added just for drawing.
- Then the internet arrived, and games stopped being finished things and
started being services that keep changing.
- Then phones arrived, and more people played games than ever before, mostly
for free, paying in small amounts inside the game.
- Every one of those steps was a technical step first, and a business step
second.
PLAIN45.2.2 a picture in your head#
- Think about how photography grew up.
- First there were one-off chemical experiments by scientists, making a
single image with enormous effort.
- Then there were heavy plate cameras owned by professionals with studios.
- Then a company put film in a small box and said “you press the button, we
do the rest”, and ordinary people took pictures.
- Then colour arrived, then instant prints, then video, then digital, then a
camera in every pocket connected to the whole world.
- Games followed the same shape, about eighty years later and much faster.
- The laboratory oscilloscope is the chemical experiment. The arcade cabinet
is the professional studio. The home console is the box with film in it.
The phone is the camera in every pocket.
Where this comparison breaks: photography captures something that already
exists. A game must create everything, so each step forward needed not just
better hardware but also new mathematics and new ways of organizing a team.
And unlike photography, games have kept the old forms alive: people still make
and play games that would run on 1985 hardware.
PLAIN45.2.3 a worked example#
- Compare one specific thing across the decades: how many moving pictures per
second the machine had to produce, and what it had to remember.
| Machine and year |
Working memory |
Screen |
| Odyssey, 1972 |
none |
3 white dots |
| Atari 2600, 1977 |
128 bytes |
160x192, 4 colours |
| NES, 1983 |
2 KB |
256x240, 25 colours |
| PlayStation, 1994 |
2 MB + 1 MB video |
320x240 to 640x480 |
| PlayStation 5, 2020 |
16 GB shared |
3840x2160 |
- Read the memory column again. 128 bytes on the Atari 2600 is not a typing
error. That is 128 individual bytes for all game state.
- The whole screen would not fit in that memory, so the machine did not have
a screen buffer at all.
- Instead the processor had to change the graphics chip’s registers while the
television’s electron beam was sweeping across the screen, line by line.
- Programmers called this racing the beam. You had about 76 processor
cycles per scan line to set up the next line.
- From 128 bytes to 16 gigabytes is a factor of 134 million in about
43 years.
PLAIN45.2.4 what is really happening inside#
- Each era solved one specific bottleneck, and the games of that era look the
way they do because of that one bottleneck.
- The 1972 machines had no processor, so the game was fixed in wiring. You
could not have a game with rules that changed.
- The 1977 to 1983 machines had a processor but almost no memory, so the
world had to be tiny and mostly regenerated each frame.
- The 1983 to 1990 machines added dedicated graphics hardware that could move
small pictures around cheaply, so games became about sprites and scrolling.
- The early 1990s machines were fast enough to compute perspective in
software, so first-person games appeared, with clever mathematics used to
avoid work rather than to do it.
- From 1996 a separate chip did the triangle filling, so the limit moved from
“how many pixels can we fill” to “how many triangles can we send”.
- From about 2001 those chips became programmable, so the limit moved again
to “what can we compute per pixel”.
- From about 2013 the limit for many games became not the hardware but the
cost of making enough content to fill it.
- That last shift is the reason a modern game costs two hundred million
dollars and a 1985 game cost a few hundred thousand.
TECHNICAL45.2.5 the engineer’s version#
| Year |
Milestone |
Technical advance |
| 1958 |
Tennis for Two |
Real-time analogue graphics |
| 1962 |
Spacewar, PDP-1 |
Stored-program interactive |
| 1971 |
Computer Space |
First coin-operated cabinet |
| 1972 |
Magnavox Odyssey |
Home console, discrete logic |
| 1972 |
Pong arcade |
TTL logic, no CPU, no code |
| 1977 |
Atari VCS / 2600 |
Cartridge ROM, 6507 CPU |
| 1978 |
Space Invaders |
Microprocessor arcade game |
| 1983 |
Market crash |
Quality control matters |
| 1983 |
Famicom in Japan |
Sprite and scroll hardware |
| 1985 |
NES in North America |
Lockout chip, licensing model |
| 1988 |
Mega Drive |
16-bit 68000, bigger sprites |
| 1990 |
Super Famicom |
Mode 7 affine transforms |
| 1992 |
Wolfenstein 3D |
Ray-cast pseudo-3D at speed |
| 1993 |
Doom |
BSP trees, modding, LAN play |
| 1994 |
PlayStation |
Hardware triangle rasterizer |
| 1996 |
3dfx Voodoo Graphics |
Consumer 3D acceleration |
| 1999 |
Dreamcast online |
Built-in modem, online play |
| 2002 |
Xbox Live |
Unified console online service |
| 2003 |
Steam |
Digital distribution, patching |
| 2008 |
Apple App Store |
Mobile mass market |
| 2017 |
Fortnite Battle Royale |
Live service at scale |
| 2020 |
PS5 and Xbox Series X |
NVMe streaming, RT hardware |
| 2024 |
PS5 Pro |
Machine-learning upscaling |
| 2025 |
Nintendo Switch 2 |
DLSS on a handheld |
- Tennis for Two was shown on 18 October 1958 at Brookhaven National
Laboratory in Upton, New York, built by William Higinbotham with technician
Robert V. Dvorak. It ran on a Donner Model 30 analogue computer with a
five-inch oscilloscope as the display. Each player had an aluminium box with
a knob to set the angle and a button to hit the ball.
- Spacewar was written in 1962 by Steve Russell and others at MIT on a DEC
PDP-1 with 9 kilowords of core memory and a Type 30 point-plotting display.
It was copied to essentially every PDP-1 installation, which makes it the
first game with a distribution story.
- The Magnavox Odyssey, designed by Ralph Baer at Sanders Associates from the
1967 “Brown Box” prototype, shipped in September 1972. It had no processor,
no memory and no software: transistor and diode logic produced three white
spots, and coloured plastic overlays taped to the television supplied the
backgrounds.
- Pong, designed by Allan Alcorn at Atari and installed in November 1972, was
also built from discrete transistor-transistor logic. There is no program to
disassemble because there is no program.
- The Atari Video Computer System, later the 2600, launched 11 September 1977
with a MOS 6507 at about 1.19 MHz, 128 bytes of RAM, and the Television
Interface Adaptor. It had no frame buffer, so the CPU had to modify the TIA
registers within each of the 262 scan lines of an NTSC field.
- The 1983 crash is well documented in numbers: United States home video game
revenue fell from roughly 3.2 billion dollars in 1983 to roughly 100
million dollars in 1985, a drop of about 97 percent. Contributing factors
were oversupply, poor quality third-party titles, and cheap home computers.
Atari buried roughly 728,000 cartridges in a New Mexico landfill in
September 1983, confirmed by an excavation in 2014.
- Nintendo’s answer was a hardware lock. The Famicom launched 15 July 1983 in
Japan; the redesigned Nintendo Entertainment System launched in New York on
18 October 1985. Its 10NES system used a Checking Integrated Circuit in the
console and an identical one in the cartridge, sharing a 4 MHz clock. The
console’s chip sends a challenge and the cartridge’s chip must return a
matching pseudo-random stream. On mismatch the console pulls the CPU and
picture processing unit reset lines low with a 1 Hz square wave, producing
the flashing screen. Different part numbers enforced regions: 3193 and 6113
for NTSC, 3197 for PAL-A, 3195 for PAL-B, 3196 for Asia.
- The honest version: the lockout chip was not security in the modern sense.
It was a business control. It let Nintendo decide who published on its
platform, cap the number of titles per publisher, and manufacture all
cartridges itself. Every console since has had some version of that control,
and it is the reason the certification process in section 45.14 exists.
- Doom shipped on 10 December 1993. Its renderer precomputed a binary space
partitioning tree at level build time so that walls could be drawn in
correct depth order without a depth buffer. Walls were drawn as vertical
texture columns; floors and ceilings as horizontal spans called visplanes,
with a hard limit of 128 of them. All arithmetic was 16.16 fixed point. It
could not do rooms above rooms, sloped floors, or a proper look up and down.
It also shipped as shareware, kept its data in an editable WAD file, and
supported four-player networked deathmatch over IPX, which created the
modding and competitive scenes at the same time.
- 3dfx Voodoo Graphics arrived in late 1996 as an add-in card that did only
3D and passed 2D through from the existing card. GLQuake in January 1997
was the demonstration that made the category mainstream.
- The PlayStation launched 3 December 1994 in Japan and 9 September 1995 in
North America. Its geometry engine had no floating-point unit and its
rasterizer had no depth buffer, so it used fixed-point maths and sorted
polygons into ordering tables, which is why its textures wobble and
polygons sometimes pop through each other.
- Console online gaming became normal in stages: the Dreamcast shipped with a
56k modem in 1998 in Japan and 1999 elsewhere, and Xbox Live launched on
15 November 2002 with a broadband-only, subscription, unified-identity
model that everyone else eventually copied.
- As of August 2026 the current landscape is: PlayStation 5 and PlayStation 5
Pro, Xbox Series X and Series S, Nintendo Switch 2 released 5 June 2025,
a PC market dominated by Steam, a handheld PC category led by the Steam
Deck, and a mobile market larger by player count than all of them together.
WORDS45.2.6 remember these#
- Racing the beam — changing the picture while the screen draws it — writing
video registers in sync with horizontal scan timing on a frame-buffer-less
system.
- Sprite — a small movable picture — a hardware-composited image layer with
its own position registers, independent of the background.
- Lockout chip — the part that says which cartridges are allowed — a
challenge-response microcontroller pair gating the console reset line.
- BSP tree — a way of pre-sorting a level — a binary space partitioning
structure allowing back-to-front or front-to-back traversal from any point.
- Shareware — try the first part free — a distribution model splitting a game
into a freely copyable episode and paid episodes.
- Fixed point — fractions stored as whole numbers — a numeric format such as
16.16 with an implicit binary scaling factor, used where no FPU exists.
45.3 The game loop in detail#
PLAIN45.3.1 in simple words#
- The loop has four jobs, always in this order.
- Input: find out what the player is doing right now. Which keys are
down, where the mouse moved, how far the trigger is pulled.
- Update: move the world forward by a small slice of time. Apply gravity,
move characters, run the enemy brains, check what hit what.
- Render: build the picture that shows the world in its new state.
- Present: hand that picture to the screen.
- Then start again from input.
- There is one hard question in the middle of this: how big is that “small
slice of time”?
- The obvious answer is “however long the last frame took”. That is called a
variable timestep, and it is wrong for physics.
- The reason is that physics maths gives different answers for different
slice sizes. Big slices lose detail and small slices keep it.
- So if your machine is fast and mine is slow, a jump that clears a gap on
your machine can fail on mine. That is not acceptable.
- The fix is to always advance physics by exactly the same slice, for
example one sixtieth of a second, no matter how long the frame took.
- If the frame took longer, you run the physics slice more than once. If it
took less, sometimes you do not run it at all.
- That is called a fixed timestep, and it is what almost every serious
game does.
PLAIN45.3.2 a picture in your head#
- Imagine filling a bucket from a tap, and every time the bucket is full you
must pour it into a barrel.
- The tap is real time flowing past. The bucket is a store of time you have
not simulated yet. The bucket’s size is your fixed step, say 16.67
thousandths of a second.
- Each time round the loop, you measure how much water came out of the tap
since last time and add it to the bucket.
- Then, while the bucket has at least one bucketful in it, you empty one
bucketful into the barrel. That emptying is one physics step.
- Sometimes you empty it twice, because the frame was slow and two bucketfuls
collected. Sometimes you empty it zero times, because the frame was fast.
- The leftover water in the bucket is real time that has passed but has not
been simulated. It is always less than one full bucket.
- That leftover is not wasted. You use it to decide how far between the last
two physics positions to draw the picture. Half a bucket left means draw
halfway between.
- That last trick is called interpolation, and it is why a game with a
60-step physics simulation can look perfectly smooth at 144 frames per
second.
Where this comparison breaks: water is continuous and time in a computer is
not. Real clocks are read as whole counts of a hardware timer. Also, a real
bucket cannot overflow into an infinite queue; a game must put a limit on how
much time it will try to catch up, or a slow frame causes a longer frame,
which causes a longer one, and the game locks up. That failure is called the
spiral of death and the fix is to clamp the measured frame time.
PLAIN45.3.3 a worked example#
- Fixed step is 16.67 ms, which is 1/60 of a second. The screen refreshes at
144 Hz, so a frame arrives every 6.94 ms.
- Start with the bucket empty. Follow ten frames.
| Frame |
Real time added |
Bucket after |
Steps run |
| 1 |
6.94 ms |
6.94 ms |
0 |
| 2 |
6.94 ms |
13.88 ms |
0 |
| 3 |
6.94 ms |
4.15 ms |
1 |
| 4 |
6.94 ms |
11.09 ms |
0 |
| 5 |
6.94 ms |
1.36 ms |
1 |
| 6 |
6.94 ms |
8.30 ms |
0 |
| 7 |
6.94 ms |
15.24 ms |
0 |
| 8 |
6.94 ms |
5.51 ms |
1 |
- Over eight frames, three physics steps ran. That is 3 x 16.67 = 50 ms of
simulated time for 8 x 6.94 = 55.5 ms of real time, with 5.5 ms still in
the bucket. The books balance.
- Notice that the picture changed on all eight frames, even the five where no
physics ran. Those five frames were drawn by interpolating.
- On frame 4 the bucket held 11.09 ms out of a 16.67 ms step, so the
interpolation factor was 11.09 / 16.67 = 0.665. Draw the world 66.5 percent
of the way from the previous physics position to the current one.
- Now the frame budget arithmetic, which you should know by heart.
| Target rate |
Budget per frame |
Ticks per second |
| 30 fps |
33.33 ms |
30 |
| 60 fps |
16.67 ms |
60 |
| 90 fps |
11.11 ms |
90 |
| 120 fps |
8.33 ms |
120 |
| 144 fps |
6.94 ms |
144 |
| 240 fps |
4.17 ms |
240 |
- The budget is 1000 divided by the target rate. That budget covers
everything: input, physics, AI, animation, audio submission, all the render
commands, and the driver’s own work.
- At 144 fps you have 6.94 ms total. If your shadow pass alone takes 3 ms you
have already spent 43 percent of the frame on shadows.
PLAIN45.3.4 what is really happening inside#
- Here is the real loop, with the fixed step, the accumulator and the
interpolation. Every line is explained underneath.
const double dt = 1.0 / 60.0; /* fixed step: 16.667 ms */
double accumulator = 0.0; /* unsimulated time store */
double t = 0.0; /* total simulated time */
double currentTime = now(); /* clock at loop start */
while (running) {
double newTime = now();
double frameTime = newTime - currentTime;
if (frameTime > 0.25) frameTime = 0.25; /* clamp */
currentTime = newTime;
accumulator += frameTime;
poll_input();
while (accumulator >= dt) {
previous_state = current_state;
simulate(¤t_state, t, dt);
t += dt;
accumulator -= dt;
}
double alpha = accumulator / dt;
State view = lerp(previous_state, current_state, alpha);
render(view);
present();
}
dt is the fixed simulation step. It never changes at run time. Every
physics calculation in the game is written knowing this exact number.
accumulator holds real time that has passed but has not yet been fed to
the simulation. It is always between 0 and dt at the bottom of the loop.
t is total simulated time. Effects, animations and networked timestamps
are keyed off this, not off the wall clock.
currentTime remembers when the previous loop iteration started, so we can
subtract and get the elapsed time.
now() must be a monotonic high-resolution clock. On Windows that is
QueryPerformanceCounter; on Linux clock_gettime(CLOCK_MONOTONIC); on
macOS mach_absolute_time. Never use wall-clock time, because it can jump
backwards when the machine syncs with a time server.
frameTime is how long the previous whole frame took, in seconds.
- The clamp to 0.25 seconds is the spiral-of-death guard. If the process was
suspended, or a big file loaded, or you dragged the window,
frameTime
might be 8 seconds. Without the clamp the loop would try to run 480 physics
steps in one frame, take even longer, and never recover. With the clamp the
game simply loses that time. Slow motion is better than a freeze.
poll_input reads the devices once per frame, before any simulation, so
that every physics step inside this frame sees the same input.
- The inner
while is the fixed-step loop. It runs zero, one or more times,
consuming one dt of accumulator each time.
previous_state = current_state saves the state before stepping, so we
have two snapshots to interpolate between.
simulate advances the world by exactly dt. It never sees the real frame
time and never needs to.
alpha is the leftover fraction, between 0 and 1. It says how far past the
last physics step the display moment is.
lerp is linear interpolation: a + (b - a) * alpha. Applied to
positions it is straightforward; applied to rotations you use spherical
interpolation of quaternions instead.
render draws the interpolated view, not the simulation state. This is the
line most beginners get wrong, and getting it wrong causes visible judder
when the frame rate is not an exact multiple of the tick rate.
present hands the buffer to the display and, with vertical sync on,
blocks until the next refresh.
TECHNICAL45.3.5 the engineer’s version#
- The accumulator pattern above is the one popularized by Glenn Fiedler’s
article “Fix Your Timestep”, first published in 2004 and widely revised
since. It is a convention, not a standard, but it is close to universal.
- Fixed step is required whenever the integration scheme is not
step-size-invariant, which is every scheme used in games. Semi-implicit
Euler with a 33 ms step and with a 4 ms step give different trajectories,
and constraint solvers converge differently at different step sizes.
- Typical simulation rates: 60 Hz is the default for most engines; 30 Hz for
large-world console titles that trade physics fidelity for CPU; 120 Hz or
240 Hz for racing, fighting and VR titles; 128 Hz for competitive shooters
on the server.
- Substepping is separate: a solver may internally split one 16.67 ms step
into 4 substeps of 4.17 ms to improve stability for fast objects, while the
game still ticks at 60 Hz.
- Frame time is the wall-clock duration of one frame in milliseconds.
Frames per second is 1000 divided by the mean frame time. Frame time is
the primary measurement; frames per second is a derived, compressed and
lossy summary of it.
- Why the average lies. Take 100 frames: 99 of them at 8.00 ms and one at
100 ms. Total elapsed is 99 x 8 + 100 = 892 ms. Mean frame time is 8.92 ms,
so the reported average is 112.1 fps. But the player saw one frame held on
screen for a tenth of a second, which reads as a clear hitch.
- This is why reviewers and profilers report percentiles. The 1 percent
low is, by the most common convention, the average frame rate of the
slowest 1 percent of frames; some tools instead report the frame time at
the 99th percentile. The two definitions give different numbers and the
industry has not settled on one. When comparing figures, check which was
used.
- In the example above, the 1 percent low is 10 fps by either definition,
against a 112 fps average. That gap is exactly the complaint people
describe as “the frame rate is fine but it feels bad”.
- Frame pacing is a separate problem from frame rate. A sequence of frame
times of 8, 8, 8, 8 ms feels smoother than 4, 12, 4, 12 ms even though both
average 8 ms, because the second sequence presents images at uneven
intervals against an even display refresh.
- The full click-to-photon latency chain, with realistic numbers for a PC at
60 Hz with vertical sync and a 2-frame render queue:
| Stage |
Typical latency |
| Mouse sample and USB |
1 to 8 ms |
| Input poll to sim |
0 to 16.7 ms |
| Simulate and render |
16.7 ms |
| Render queue depth |
16.7 to 33.4 ms |
| Display scanout and panel |
5 to 20 ms |
- That totals roughly 40 to 95 ms, which is why competitive players disable
vertical sync, cap frames just below the refresh rate, use variable
refresh, and enable low-latency modes such as NVIDIA Reflex (2020) or AMD
Anti-Lag, all of which mainly work by shortening the render queue.
- Measuring tools: PresentMon and its front ends on Windows give per-frame
present timings and a latency estimate;
stat unit and Unreal Insights in
Unreal Engine; the Unity Profiler; RenderDoc and PIX for GPU timings;
perf and Tracy for CPU timeline capture.
- The distinction between CPU frame time and GPU frame time matters. If the
GPU is the bottleneck the CPU finishes early and waits; if the CPU is the
bottleneck the GPU starves. Profilers report both, and the larger one is
your frame time.
frame N frame N+1 frame N+2
CPU [sim|render cmds] [sim|render cmds] [sim|...
GPU [ draw N ] [ draw N+1 ] [ ...
DISP [show N ] [show N+1]
CPU builds frame N while GPU draws N-1: this is pipelining.
It raises throughput and adds one frame of latency.
WORDS45.3.6 remember these#
- Timestep — the slice of time simulated at once — the
dt passed to the
integrator each simulation tick.
- Fixed timestep — always the same slice — a constant
dt decoupled from
frame duration, required for reproducible integration.
- Accumulator — the store of unsimulated time — a scalar holding elapsed real
time not yet consumed by fixed steps.
- Interpolation — drawing between two known positions — blending previous and
current simulation states by the leftover accumulator fraction.
- Spiral of death — the game falls further and further behind — unbounded
catch-up stepping where step cost exceeds real time elapsed.
- Frame time — how long one frame took — wall-clock duration in milliseconds,
the primary performance measurement.
- 1 percent low — how bad the worst frames are — the mean frame rate of the
slowest one percent of frames, or the 99th-percentile frame time.
- Frame pacing — whether frames arrive evenly — the variance of frame
intervals relative to the display refresh period.
45.4 How a game is built, as a project#
PLAIN45.4.1 in simple words#
- A game is not written. It is built, the way a film is shot or a building
is put up, by people with very different skills.
- The designer decides what the player does and why it is fun. Levels,
rules, numbers, pacing.
- The programmer makes the machine do it. Gameplay code, engine code,
graphics code, tools for everyone else, network code.
- The artist makes what you see. Concept art first, then the actual
models, textures, environments and characters.
- The animator makes things move: walking, reloading, dying, a door
opening, a face speaking.
- The audio people make what you hear: footsteps, gunfire, wind, music,
voices.
- Quality assurance, usually called QA, plays the game deliberately and
methodically to find what is broken, and writes it down precisely.
- The producer keeps the whole thing on a schedule and decides what gets
cut when there is not enough time. There is never enough time.
- On a big game there are more roles: technical artist, user interface
designer, writer, localization, build engineer, live operations, community.
- The single most important fact about this list is that programmers are a
minority. On a large modern game, roughly one person in five writes code.
PLAIN45.4.2 a picture in your head#
- Think of a restaurant opening.
- Somebody decides what kind of restaurant it is and writes the menu. That is
the designer.
- Somebody builds the kitchen and makes the equipment work. That is the
programmer.
- Chefs cook. Decorators decorate. Someone chooses the music. Those are the
artists, animators and audio people.
- Before opening, friends come in and eat for free and say what was wrong.
That is QA and playtesting.
- Someone watches the money and the calendar and says “the dessert menu is
cut, we open in three weeks”. That is the producer.
- And a restaurant is never finished on opening night. The first month is
fixing what real customers break. That is the launch patch and live
operations.
Where this comparison breaks: a restaurant can open with a small menu and add
dishes. A game usually has to ship one enormous simultaneous thing, and a
missing piece in the middle stops everything. Also, a bad dish affects one
diner; a bad save-file bug affects everyone at once, everywhere, at 3 a.m.
PLAIN45.4.3 a worked example#
- The phases, in order, with what each one actually means.
- Concept: a few people, a few weeks to a few months. A document, some
sketches, maybe a rough playable thing. Most concepts die here, and that is
the cheapest place to die.
- Pre-production: build the risky bits. Answer “can we even do this”.
Small team, six months to two years on a big project.
- Vertical slice: one small part of the game at full final quality. Ten
minutes that look and feel exactly like the finished game. It exists to
prove the vision and to unlock funding.
- Production: the big, expensive middle. Make all the content. The team
is at its largest here.
- Alpha: feature complete. Every system exists, even if content is
missing and it is full of bugs.
- Beta: content complete. Everything is in. From here you only fix.
- Certification: for consoles, the platform holder tests the build
against a long checklist. See section 45.14.
- Gold and launch: the build is locked and manufactured or uploaded.
- Live operations: patches, seasons, events, balance changes, and
sometimes years of new content.
| Scale |
Team size |
Time |
Budget range |
| Solo hobby |
1 |
6 to 24 months |
0 to 20k |
| Small indie |
2 to 8 |
1 to 3 years |
50k to 1M |
| Mid-size (AA) |
30 to 80 |
2 to 3 years |
5M to 30M |
| AAA |
200 to 600 |
4 to 6 years |
80M to 300M |
- Those budget figures are in United States dollars and exclude marketing,
which on a AAA title is often as much again as development.
PLAIN45.4.4 what is really happening inside#
- The reason production is expensive is content, not code.
- A gun in a modern shooter is not one job. It is a concept sketch, a
high-detail model, a low-detail game model, several texture maps, a rig,
reload and inspect and fire animations, muzzle flash effects, four or five
layered sounds, a tuning pass on damage and recoil, a first-person and a
third-person version, and an entry in the user interface.
- That is roughly two to six person-weeks for one weapon, and a game may have
forty.
- Multiply that pattern across characters, environments, vehicles and
cutscenes and you get the two hundred million dollars.
- Code is a smaller share, but it gates everything: nobody can build a level
until the level tools work.
- This is why the tools programmers are quietly the most valuable people on a
big team. A one-second improvement in the editor’s save time, times 200
people, times 50 saves a day, is 2.8 hours of team time per day.
- And this is why the schedule always slips at the end. Content work is
parallel and estimable. Integration, bug fixing and certification are
serial and are not.
TECHNICAL45.4.5 the engineer’s version#
- Real documented budgets, from court filings and leaks rather than press
releases, which is why they are trustworthy.
| Game |
Reported cost |
Source and year |
| The Last of Us Part II |
~220M, ~200 devs |
Court exhibit, 2023 |
| Horizon Forbidden West |
~212M, ~300 devs |
Court exhibit, 2023 |
| Grand Theft Auto V |
~265M with marketing |
Reported, 2013 |
| Cyberpunk 2077 |
~316M with marketing |
CD Projekt, 2021 |
| Stardew Valley |
one person, 4.5 years |
Developer, 2016 |
- The Sony figures became public in June 2023 through poorly redacted
documents filed in the United States Federal Trade Commission case about
the Microsoft acquisition of Activision Blizzard. The Cyberpunk 2077
number is roughly 1.2 billion Polish zloty of combined development and
marketing spend, converted at the rates of the time, and should be treated
as approximate.
- Team composition on a typical 250-person AAA project is roughly: 45 to 60
artists, 30 to 45 engineers, 20 to 30 designers, 20 to 30 animators, 10 to
15 audio, 30 to 60 QA, plus production, writing, user interface and
localization. External outsourcing studios may add another 200 people who
never appear on the internal headcount.
- Costs per head, fully loaded with salary, benefits, hardware, software and
office, run roughly 120,000 to 250,000 US dollars per person-year in North
America and Western Europe, less elsewhere. A 250-person team for four
years at 160,000 is 160 million dollars, which is where these budgets come
from.
- Now the honest part, because the reader asked for honesty.
- Crunch means long mandatory overtime near milestones. Sixty to eighty
hour weeks for months are documented at many studios. It is often unpaid
for salaried staff. It correlates with burnout, health damage and people
leaving the industry in their thirties.
- The industry has argued about it publicly since the 2004 “EA Spouse” open
letter, which led to overtime lawsuits and settlements at Electronic Arts.
It recurred publicly around Rockstar Games in 2018 and CD Projekt Red
in 2020.
- The structural cause is not villainy. It is that games are fixed-date,
fixed-scope products with an unpredictable final integration phase, sold in
a market with a hit-driven revenue distribution. Cutting scope is the only
real fix and it is the hardest decision to make.
- Layoffs became the defining industry story of the 2020s. Trackers
recorded roughly 10,500 games industry job losses in 2023 and roughly
14,600 in 2024, with further large numbers through 2025 and 2026. Studios
have been closed within months of shipping well-reviewed games.
- Unionization started to take hold in the same period, with organized
bargaining units at several large studios from 2023 onward. Whether this
changes crunch materially is still open.
- Where experts disagree: some argue budgets are unsustainable and the AAA
model must shrink; others argue the top few titles will keep growing and
the middle will disappear. The evidence in 2026 supports both, because the
middle has in fact been shrinking while the top has grown.
WORDS45.4.6 remember these#
- Vertical slice — a small piece at final quality — a fully polished
representative segment used to validate the design and secure funding.
- Alpha — every feature exists — feature complete, content incomplete.
- Beta — everything is in — content complete, bug fixing only.
- Gold master — the locked build — the final candidate submitted for
manufacture or platform release.
- Crunch — mandatory long hours — sustained overtime at milestone boundaries,
often uncompensated for salaried staff.
- Live operations — running the game after launch — the ongoing content,
balance, event and monetization pipeline for a service game.
45.5 Game engines#
PLAIN45.5.1 in simple words#
- An engine is the pile of reusable machinery that every game needs and
that is not about your particular game.
- It draws things. It plays sounds. It reads controllers. It works out what
hit what. It loads files. It runs on Windows and consoles and phones.
- It also gives you an editor: a program where you place objects, light a
scene and press play, without writing code for any of it.
- What it does not give you is a game. It gives you the ability to make one.
- Studios use one instead of writing their own for a plain reason: writing
your own costs several engineer-years before you can show anything.
- Worse, you must then keep it working on five platforms as those platforms
change, forever, with a team of maybe three people.
- Big studios that do write their own do it because they need something the
commercial engines do not do well: enormous open worlds, very specific
physics, or an existing pile of tools twenty years deep.
PLAIN45.5.2 a picture in your head#
- Think about building a house.
- You could make your own bricks, mill your own timber and wind your own
wire. People did, once.
- Today you buy standard bricks, standard wire in standard colours, standard
window units and standard plumbing fittings.
- The standard parts are not what makes your house yours. The plan is.
- But the standard parts decide a lot: what shapes are cheap, what is
awkward, and what will simply not fit.
- An engine is the standard parts. It makes some games cheap to build and
others painful, and you feel that pressure the whole way through.
Where this comparison breaks: bricks do not change their price after you have
built half the house. Engine licences can, and in 2023 one of them tried to.
Section 45.5.5 tells that story exactly.
PLAIN45.5.3 a worked example#
- What is actually inside an engine, listed as the parts you would otherwise
have to write.
| Part |
What it does |
| Renderer |
Turns a scene into pixels |
| Physics |
Moves bodies, finds collisions |
| Audio |
Mixes and positions sound |
| Input |
Reads keyboard, mouse, pads |
| Scene system |
Holds and finds objects |
| Asset pipeline |
Imports and converts content |
| Scripting |
Runs gameplay code safely |
| Editor |
Lets non-programmers build |
| Build system |
Packages for each platform |
| Networking |
Replicates state to clients |
- A bare version of the first four is roughly 50,000 to 150,000 lines of
code and two to four engineer-years for a competent small team.
- A version with an editor, a working asset pipeline and console support is a
decade of work by a real team. That is the honest scale.
- Which is why a two-person studio using Godot ships in eighteen months, and
a two-person studio writing an engine ships never.
PLAIN45.5.4 what is really happening inside#
- Two ways of organizing the objects in a game world dominate, and the
difference is about how the computer’s memory works.
- A scene graph is a tree. A car is a node; its wheels are children of
the car; a mirror is a child of a door which is a child of the car.
- Moving the car moves everything under it automatically, because each child
position is stored relative to its parent.
- This is natural for humans and it matches how artists think. It is what
Unity’s GameObject hierarchy and Godot’s node tree give you.
- Its weakness is speed. Each object is a separate lump of memory with
pointers to its children, scattered across the heap.
- When the game walks 10,000 objects to move them, it jumps all over memory,
and the processor spends most of its time waiting for memory rather than
computing.
- An entity-component-system, always abbreviated ECS, is the answer.
- An entity is just a number, an identity with no data of its own.
- A component is a small plain lump of data, such as a position or a
health value, stored in one big array with all the other positions.
- A system is a function that runs over every entity that has a
particular set of components, walking those arrays straight through.
- Because all the positions sit next to each other in memory, the processor
can fetch them in order and predict what comes next. That is the whole
trick, and it can be several times faster.
TECHNICAL45.5.5 the engineer’s version#
- The cache arithmetic that makes ECS worth the awkwardness. A cache line on
every current x86-64 and ARM64 processor is 64 bytes.
- Suppose 10,000 objects, each a 256-byte object, and you want to add
velocity to position: 12 bytes read, 12 bytes written per object.
- In the object-oriented layout, each object touches at least one 64-byte
line, usually two because the fields straddle. Memory traffic is at least
10,000 x 64 = 640 KB, in an access pattern the hardware prefetcher cannot
predict.
- In the component layout, positions are one contiguous 120 KB array and
velocities another. Total traffic is 240 KB, perfectly sequential, fully
prefetched. That is under half the traffic and far better latency hiding.
- Blizzard’s Overwatch is the best-documented shipped example. In Timothy
Ford’s GDC 2017 talk “Overwatch Gameplay Architecture and Netcode” the
client is described as having about 46 systems and about 103 component
types, with only three systems involved in gameplay networking.
- Now the engines themselves, as of August 2026.
| Engine |
Language |
Cost model |
| Unity 6 |
C# |
Free under 200k revenue |
| Unreal Engine 5 |
C++ and Blueprints |
Free under 1M lifetime |
| Godot 4 |
GDScript, C#, C++ |
MIT licence, free |
| In-house |
usually C++ |
Salaries and years |
- Unity was announced at Apple’s Worldwide Developers Conference in June
2005 as a Mac-only engine. It now targets more than nineteen platforms. It
scripts in C#; the old UnityScript was deprecated in August 2017. Unity
Personal is free below 200,000 US dollars of annual revenue and funding.
Unity Pro is required above that; its list price was 2,200 dollars per seat
per year from 1 January 2025 and 2,310 dollars per seat per year from
12 January 2026. Unity Enterprise is required above 25 million dollars.
- The 2023 episode, stated precisely. On 12 September 2023 Unity announced a
Runtime Fee: a per-install charge on games above revenue and install
thresholds, to begin 1 January 2024. The reaction was severe, because the
fee applied retroactively to already-shipped games built under different
terms, was based on installs rather than sales, and had no clear way to
count them.
- Unity revised the terms on 22 September 2023. Chief executive John
Riccitiello retired on 9 October 2023. Matthew Bromberg became chief
executive in May 2024. On 12 September 2024, exactly one year after the
announcement, Unity cancelled the Runtime Fee outright and returned to
seat-based subscriptions, doubling the Personal threshold from 100,000 to
200,000 dollars and raising Pro by 8 percent and Enterprise by 25 percent
instead.
- The lesson is not “Unity is bad”. It is that a licence is part of your
technology stack, it is a contract with a company that has shareholders,
and it can change under a project that is already three years in. Read the
terms, keep an exit plan, and prefer terms fixed at the version you ship.
- Unreal Engine licensing has moved the other way over time. In March
2014 Unreal Engine 4 was 19 dollars per month plus a 5 percent royalty. In
March 2015 it became free with a 5 percent royalty above 3,000 dollars per
calendar quarter. In May 2020, retroactive to 1 January 2020, the
exemption became 1,000,000 dollars of lifetime gross revenue per title.
Revenue from the Epic Games Store is royalty-free. Since 2024 there is
also a seat licence, 1,850 dollars per seat per year, for companies over
1 million dollars doing non-game work such as film and architecture.
Unreal Engine 5.7 shipped in November 2025.
- Godot is MIT licensed and has been open source since February 2014.
There is no fee, no royalty and no threshold, and the licence cannot be
revoked for a version you already have. The latest stable release at the
time of writing is 4.7.1 from 13 July 2026. It is developed by the Godot
Foundation on donations, which is its own risk: a much smaller budget than
either commercial competitor.
- In-house engines still dominate the top end: RE Engine at Capcom,
Decima at Guerrilla, Frostbite at Electronic Arts, Anvil at Ubisoft,
id Tech at id Software, Creation at Bethesda, Source 2 at Valve, and
Rockstar’s RAGE. The reason is usually a genre the commercial engines
handle badly, plus twenty years of tooling that a team already knows.
- Where experts disagree: some argue in-house engines are a strategic asset;
others argue they are a tax that diverts engineers from the game. Several
large publishers have moved to Unreal Engine 5 since 2022, which is
evidence for the second view but not proof.
WORDS45.5.6 remember these#
- Engine — the reusable machinery — the platform layer, renderer, physics,
audio, tools and pipeline shared across titles.
- Scene graph — a tree of objects — a hierarchy of transforms where child
transforms are expressed relative to their parent.
- ECS — data in flat arrays with functions over them — entity-component-system
architecture separating identity, plain data and behaviour for cache
locality.
- Cache line — the smallest chunk memory moves in — 64 bytes on current x86-64
and ARM64 processors.
- Royalty — a share of revenue paid to the engine maker — a percentage of
gross above a stated threshold, as in Unreal’s 5 percent above 1 million.
- Runtime fee — a charge per install — the per-installation model Unity
announced in September 2023 and cancelled in September 2024.
45.6 Assets and the content pipeline#
PLAIN45.6.1 in simple words#
- Everything in a game that is not code is an asset: models, pictures,
sounds, animations, fonts, levels, text.
- Assets are made in other programs. A model is made in a modelling tool, a
texture in a painting tool, a sound in an audio tool.
- Those programs save in formats designed for editing, not for playing.
They are big, flexible and slow to read.
- So there is a step in the middle that converts everything into the exact
form the target machine wants. That step is the asset pipeline.
- It compresses textures into a format the graphics chip can read directly.
It simplifies models into several versions for different distances. It
packs thousands of small files into a few big ones.
- It also computes things in advance that would be too slow to compute while
playing: how light falls on a static wall, where characters can walk, how
sound travels in a room.
- Doing all that for an entire game is why a full build takes hours.
- In Unreal Engine this conversion step is called cooking, and the phrase
“cook the content for PlayStation” means “convert every asset into the
exact form that machine wants”.
PLAIN45.6.2 a picture in your head#
- Think of a professional kitchen before service.
- The raw ingredients arrive as whole vegetables, whole fish, sacks of flour.
Flexible, but useless during a busy service.
- So in the morning the kitchen does prep: chopping, portioning, making
stocks, part-cooking things that take an hour.
- During service nothing takes an hour, because the hour already happened.
- Prep is the asset pipeline. Raw ingredients are the source files. The
prepped trays are the cooked assets.
- And if the chef changes the menu at 5 p.m., all the prep for that dish is
wasted and must be redone. That is why artists hate late changes.
Where this comparison breaks: a kitchen preps for one evening. A game preps
for every machine it will ever run on, and each target wants different prep,
so the same source is prepped four or five times in parallel.
PLAIN45.6.3 a worked example#
- Follow one texture from painting to screen.
- An artist paints a 4096 by 4096 colour map in a painting program and saves
a 32-bit-per-pixel file.
- Raw size: 4096 x 4096 x 4 bytes = 67,108,864 bytes, which is 64 mebibytes
for one texture.
- The pipeline generates mipmaps, smaller copies at half size, quarter
size and so on down to one pixel. That adds about 33 percent, so about 85
mebibytes.
- Then it compresses to a format the graphics chip can sample directly. On PC
and console that is usually BC7, which is one byte per pixel.
- BC7 size: 4096 x 4096 x 1 = 16 mebibytes, plus mipmaps, about 21.3
mebibytes. That is a quarter of the raw size and it stays compressed in
video memory, which is the point.
- On a phone the same texture is compressed to ASTC instead, because mobile
graphics chips do not read BC7.
| Format |
Target |
Bits per pixel |
| RGBA8 uncompressed |
none |
32 |
| BC1 (DXT1) |
PC, console |
4 |
| BC7 |
PC, console |
8 |
| ETC2 RGBA |
Android, GLES 3 |
8 |
| ASTC 4x4 |
mobile, Apple |
8 |
| ASTC 6x6 |
mobile, Apple |
3.56 |
- Now do that for 4,000 textures. At 64 mebibytes raw each, the source is
256 gibibytes; cooked to BC7 with mipmaps it is about 85 gibibytes; after
packaging and further lossless compression, perhaps 45 gibibytes on disk.
- And the compression itself is not free. High-quality BC7 encoding is
roughly 0.5 to 5 seconds per 4K texture on one core. Four thousand of them
is 30 minutes to 5 hours of single-core work, which is why studios run
distributed build farms and shared caches.
PLAIN45.6.4 what is really happening inside#
- The full pipeline, in order, for a 3D character.
- Model: the artist builds a mesh, a set of points joined into triangles.
A hero character might be 60,000 to 150,000 triangles.
- UV unwrap: the artist flattens the surface onto a square so a
two-dimensional picture can be painted onto it.
- Texture: several pictures are painted, not one. Base colour, roughness,
metalness, a normal map that fakes small bumps, sometimes ambient occlusion
and emissive.
- Rig: a skeleton of bones is built inside the mesh, and each vertex is
assigned weights saying which bones move it and how much.
- Animate: the animator poses the skeleton over time, or motion capture
data is cleaned up and retargeted onto it. Each clip is a list of bone
rotations at keyframes.
- Export: everything is written to an interchange format, usually FBX, or
increasingly glTF 2.0 or USD.
- Import: the engine reads that file and converts it. Triangles are
reordered for the graphics chip’s vertex cache. Normals and tangents are
computed. Animation curves are compressed, often to about a tenth of their
size, by dropping keys within an error tolerance.
- Level of detail: simplified copies are generated. A common ladder is
100 percent, 50 percent, 25 percent and 12 percent of the triangles,
swapped by screen size.
- Bake: things that never change are computed once. Light maps for static
geometry, a navigation mesh for where characters can walk, occlusion data
for what can see what.
- Package: everything is written into a few large archive files, sorted
so that things loaded together sit next to each other on disk, and
compressed with a fast codec.
- Ship: the archive plus the executable is what the player downloads.
TECHNICAL45.6.5 the engineer’s version#
- Tools in common use: Blender (free, GPL) and Autodesk Maya for modelling
and animation; ZBrush for sculpting; Adobe Substance 3D Painter and
Designer for textures; Houdini for procedural content and effects;
Photoshop or Krita for two-dimensional art; Reaper, Pro Tools and iZotope
RX for audio.
- Interchange formats: FBX (Autodesk, proprietary but ubiquitous), glTF 2.0
(Khronos, 2017, open and runtime-friendly), USD (Pixar, open-sourced 2016,
now standard for large scene assembly), Alembic for baked geometry caches,
OBJ for simple static meshes.
- Cooking, precisely, means: convert every source asset into a
platform-specific, engine-specific binary that can be memory-mapped or
streamed with minimal parsing, and drop all editor-only data.
- Why full builds take hours, itemized for a large project:
| Stage |
Typical duration |
| Code compile and link |
20 to 90 minutes |
| Shader compilation |
1 to 6 hours |
| Texture compression |
30 to 180 minutes |
| Lightmap baking |
1 to 12 hours |
| Packaging and compress |
20 to 90 minutes |
- Shader compilation is usually the worst offender because of
permutations. One material shader with 12 independent boolean features
is 2 to the power 12, which is 4,096 variants, and a real project has
hundreds of such shaders. Large titles ship tens of thousands to hundreds
of thousands of compiled pipeline states.
- The countermeasures are a derived data cache (a shared server storing
the result of every conversion keyed by a hash of the input plus the
settings, so nobody converts the same asset twice), distributed compilation
systems such as Incredibuild or FASTBuild, and incremental cooking that
touches only changed assets. With a warm cache, an incremental cook is
minutes rather than hours.
- Runtime compression codecs matter as much as the format. Oodle Kraken,
Zstandard and LZ4 are the common choices; consoles decompress in hardware,
with the PlayStation 5 Kraken decompressor rated at roughly 5.5 gigabytes
per second of compressed input and the Xbox Series X BCPack path similar in
spirit.
- Virtualized geometry changes the level-of-detail story. Unreal Engine 5’s
Nanite, introduced in 2021, stores meshes as a hierarchy of triangle
clusters and selects detail per cluster per pixel at run time, removing
hand-authored LODs for static opaque geometry. It does not remove the need
for LODs on skinned characters, foliage or translucent materials, which is
a caveat often skipped in marketing material.
- Virtual texturing solves the matching problem for textures: only the pages
of a texture actually visible at the current screen resolution are resident
in video memory, so a scene can reference far more texture data than fits.
- Observation tools: Unreal’s
-run=DerivedDataCache and cook logs, Unity’s
Build Report and Addressables analysis, ls -la on the packaged archives,
RenderDoc to see which textures a frame actually sampled, and the
platform’s own memory profiler to see what is resident.
WORDS45.6.6 remember these#
- Asset — anything that is not code — content data authored in an external
tool and consumed by the engine.
- Cooking — converting content for one machine — transforming source assets
into a platform-specific runtime binary form.
- Mipmap — smaller copies of a texture — a precomputed pyramid of
half-resolution levels used to avoid aliasing at distance.
- Level of detail — simpler versions for far away — a set of decimated meshes
selected by projected screen size.
- Baking — computing it in advance — precomputing lighting, navigation or
occlusion data at build time rather than at run time.
- Derived data cache — a shared store of conversion results — a server keyed
by input hash so that each conversion is performed once for the whole team.
- Shader permutation — one variant of a shader — a compiled pipeline state
for one specific combination of features and platform.
45.7 Physics and collision#
PLAIN45.7.1 in simple words#
- A physics system answers two questions, sixty times a second: where is
everything now, and did anything touch anything.
- Each movable object is a rigid body: a shape that does not bend, with a
mass, a position, a speed and a spin.
- Forces such as gravity change its speed. Its speed changes its position.
Doing that arithmetic step by step is called integration.
- Finding touches is done in two passes, because checking every pair is far
too slow.
- The first pass, the broad phase, cheaply throws away pairs that are
obviously nowhere near each other, using a grid or a tree of boxes.
- The second pass, the narrow phase, does the real shape test on the few
pairs that survived.
- When two things do touch, the system pushes them apart and changes their
speeds. How bouncy that is depends on a number between 0 and 1 called
restitution.
- Ropes, hinges, doors and ragdolls are the same machinery plus rules that
say “these two bodies must stay joined here”. Those rules are constraints.
PLAIN45.7.2 a picture in your head#
- Imagine a large hall with 1,000 people walking around, and you must report
every collision.
- Checking every pair means 1,000 x 999 / 2 = 499,500 checks. At sixty times
a second that is 30 million checks a second, for nothing.
- So you chalk the floor into a grid of squares. Each person reports which
square they are in.
- Now you only compare people in the same square or in touching squares.
Almost every pair is eliminated without looking at them.
- That is the broad phase. The remaining few hundred pairs get the careful
look, which is the narrow phase.
Where this comparison breaks: people are all about the same size, so one grid
square size works. Game objects range from a bullet to a cathedral, and one
grid size cannot serve both. Real engines therefore use trees of boxes that
adapt, not a flat grid.
PLAIN45.7.3 a worked example#
- Two balls hit head-on. Ball A weighs 2 kg and moves at +5 metres per second
along x. Ball B weighs 1 kg and is still. Restitution is 0.5.
- The collision normal
n points from A to B, so it is (1, 0, 0).
- Relative velocity along the normal:
v_rel = (v_B - v_A) . n = 0 - 5 = -5.
Negative means they are approaching, so we must respond.
- Impulse magnitude uses this formula:
-(1 + e) * v_rel
j = --------------------
1/m_A + 1/m_B
- Put the numbers in:
j = -(1 + 0.5)(-5) / (1/2 + 1/1) = 7.5 / 1.5 = 5.
The unit is kilogram metres per second.
- Apply it:
v_A' = 5 - j/m_A = 5 - 5/2 = 2.5 m/s, and
v_B' = 0 + j/m_B = 0 + 5/1 = 5.0 m/s.
- Check momentum. Before: 2 x 5 + 1 x 0 = 10. After: 2 x 2.5 + 1 x 5 = 10.
Conserved, as it must be.
- Check restitution. Separation speed after is 5 - 2.5 = 2.5, and the
approach speed was 5. The ratio is 0.5, which is exactly
e.
- Check energy. Before: 0.5 x 2 x 25 = 25 joules. After: 0.5 x 2 x 6.25 plus
0.5 x 1 x 25 = 6.25 + 12.5 = 18.75 joules. 6.25 joules were lost as heat
and sound, which is what a restitution below 1 means.
PLAIN45.7.4 what is really happening inside#
- The integration step. The naive version, called explicit Euler, is
x = x + v*dt then v = v + a*dt. It quietly adds energy on every step and
a spring simulated this way will slowly explode.
- Games use semi-implicit Euler instead: update velocity first, then use
the new velocity to update position. One line swapped, and the system is
stable enough for gameplay.
- Verlet integration stores the previous position instead of velocity:
x_new = 2*x - x_prev + a*dt*dt. It handles distance constraints very well,
which makes it the standard choice for cloth, rope and hair.
- The broad phase in a real engine is usually a bounding volume hierarchy: a
tree where each node is a box containing its children’s boxes. Testing a
ray or a box against it costs about log of the object count.
- The narrow phase uses exact tests for simple pairs, such as sphere against
sphere, and a general algorithm for convex shapes.
- Contacts are not resolved one at a time in isolation, because a box resting
on the floor has four contacts that must agree. The solver runs over all
contacts several times per step, nudging each towards consistency.
- That is why a tall stack of boxes in a game jitters. The solver has a fixed
number of iterations and simply runs out of time before the stack agrees.
TECHNICAL45.7.5 the engineer’s version#
- Broad-phase structures in use: uniform grids and spatial hashes for
same-size objects; sweep and prune, which keeps objects sorted along an
axis and exploits frame-to-frame coherence; quadtrees and octrees; and
dynamic AABB trees, which is what Box2D, Bullet, PhysX and Jolt all use.
- Narrow phase: analytic tests for sphere, capsule and axis-aligned box
pairs; the separating axis theorem for oriented boxes and convex polygons;
and GJK, published by Gilbert, Johnson and Keerthi in 1988, plus the
expanding polytope algorithm to recover penetration depth, for general
convex shapes. Concave meshes are decomposed into convex pieces or treated
as static triangle soups.
- Constraint solving is almost always sequential impulses, also called
projected Gauss-Seidel, popularized by Erin Catto in Box2D and his GDC
presentations from 2005 onward. Typical settings are 4 to 10 velocity
iterations and 1 to 4 position iterations per step. Baumgarte stabilization
or a split-impulse pass removes penetration without injecting energy.
- Joint types: hinge (revolute), ball and socket (spherical), slider
(prismatic), fixed, distance, and six-degree-of-freedom with per-axis
limits and motors. A ragdoll is a set of rigid bodies matched to the
skeleton’s bones with joints whose limits mimic human range of motion, plus
a blend that hands control from animation to physics on death or impact.
- Continuous collision detection exists because a bullet moving 600 metres
per second travels 10 metres in a 16.67 ms step and will tunnel straight
through a wall. Solutions are conservative advancement, swept shape tests,
or simply raycasting bullets instead of simulating them, which is what
most shooters do.
- Common engines and their defaults:
| Engine |
Physics |
Default rate |
| Unity 6 |
PhysX 4 or Unity Physics |
50 Hz |
| Unreal Engine 5 |
Chaos |
30 or 60 Hz |
| Godot 4 |
Godot Physics or Jolt |
60 Hz |
| Custom |
Bullet, Jolt, Box2D |
60 Hz |
- Determinism, stated precisely. IEEE 754-2019 fully specifies addition,
subtraction, multiplication, division and square root: given the same
inputs, rounding mode and precision, every conforming machine returns the
same bits.
- It does not specify
sin, cos, exp, log or pow, so two maths
libraries can legally differ in the last bit. That is the first source of
divergence.
- The others are: compilers reordering floating-point expressions or
contracting
a*b+c into a fused multiply-add with different rounding;
fast-math flags; historic x87 80-bit intermediates versus SSE 64-bit;
different SIMD widths taking different code paths; and multi-threaded
solvers where the order contacts are summed changes between runs.
- The consequence for multiplayer: you cannot assume two machines simulating
the same inputs reach the same state. A one-bit difference in one frame
becomes a visibly different world within seconds, because contact
resolution amplifies small differences.
- If you need determinism, you must either use fixed-point arithmetic, or
lock down compiler flags, library versions, thread counts and instruction
sets across every platform you ship on. This is why deterministic lockstep
networking, described in section 45.11, is hard.
WORDS45.7.6 remember these#
- Rigid body — a solid that does not bend — a body with mass, inertia tensor,
linear and angular velocity, and no internal deformation.
- Integration — stepping the maths forward — advancing state by
dt using a
scheme such as semi-implicit Euler or Verlet.
- Broad phase — the cheap first filter — spatial culling that produces a
candidate pair list, typically via a dynamic AABB tree.
- Narrow phase — the careful shape test — exact intersection tests producing
contact points, normals and penetration depths.
- Restitution — how bouncy it is — the coefficient
e relating separation
speed to approach speed along the contact normal.
- Impulse — an instant change of momentum — the quantity
j applied along the
contact normal to resolve a collision.
- Tunnelling — moving straight through a wall — a fast body crossing thin
geometry within one timestep, fixed by continuous collision detection.
45.8 Game AI#
PLAIN45.8.1 in simple words#
- Game AI is the code that decides what a character that is not you does
next.
- It has two halves: decide what to do, and work out how to get there.
- The simplest way to decide is a state machine. The guard is in one state
at a time: idle, patrol, investigate, chase, attack, flee. Events move it
between states.
- When there are twenty states, the arrows between them become unmanageable,
so bigger games use a behaviour tree: a tree of small tasks read from
the top, left to right, until one succeeds.
- Another way is a utility system: score every possible action with a
number and do the highest-scoring one.
- The most elaborate is a planner: describe the goal, describe what each
action requires and produces, and let the machine search for a sequence.
- The second half, getting there, is pathfinding, and the standard
algorithm has been the same since 1968.
PLAIN45.8.2 a picture in your head#
- Think about how you decide what to do at work.
- Some of it is a state machine: you are in a meeting, or at your desk, or at
lunch, and only certain moves make sense from each.
- Some of it is a checklist read top down: is anything on fire, no; is anyone
waiting for me, no; then do the next task on the list. That is a behaviour
tree, and the order encodes priority.
- Some of it is scoring: three things could be done, and you weigh urgency
against effort and pick one. That is a utility system.
- And occasionally you plan: to get the report signed you need the data,
which needs the export, which needs access. Working backwards from the goal
is what a planner does.
- All four are used in games, often in the same game, for different
characters.
Where this comparison breaks: you have a goal of your own. A game character
does not. Its goal is that you enjoy fighting it, which is not the same thing
as winning, and that changes every design decision underneath.
PLAIN45.8.3 a worked example#
- A-star pathfinding, by hand, on a five by five grid.
S is the start, G
is the goal, # is a wall. Moves are up, down, left and right, each
costing 1.
y=4 . . . . .
y=3 . . # . .
y=2 S . # . G
y=1 . . # . .
y=0 . . . . .
x0 x1 x2 x3 x4
- A-star keeps a score for each square:
f = g + h.
g is the real cost from the start to that square, counted so far.
h is a guess of the cost from that square to the goal. Here it is the
Manhattan distance, |4 - x| + |2 - y|, which never overestimates because
you cannot reach the goal in fewer steps than that.
- Always expand the open square with the lowest
f.
- Start: S at (0,2) has
g=0, h=4, f=4.
- Expand S. Neighbours (0,1) and (0,3) get
g=1, h=5, f=6. Neighbour (1,2)
gets g=1, h=3, f=4.
- Lowest
f is (1,2) at 4, so expand it. (2,2) is a wall. (1,1) and (1,3)
get g=2, h=4, f=6.
- Now four squares are tied at
f=6. Ties are broken towards higher g,
which pushes the search forwards rather than sideways.
- Expanding those gives (1,0) and (1,4) at
f=8, and later (0,0) and (0,4)
at f=8.
- From (1,4) the search runs along the top: (2,4)
g=4 h=4 f=8, (3,4)
g=5 h=3 f=8, (3,3) g=6 h=2 f=8, (3,2) g=7 h=1 f=8, and finally the
goal at g=8, h=0, f=8.
- The answer is an eight-step path around the top of the wall. Note the
heuristic said 4 at the start and the truth was 8. That is allowed, and
that gap is exactly why the search had to look around.
| Algorithm |
Squares expanded |
Path length |
| Breadth-first / Dijkstra |
~22 of 22 |
8 |
| A-star, Manhattan h |
~13 of 22 |
8 |
| Greedy best-first |
~9 of 22 |
may exceed 8 |
- A-star found the same shortest path as Dijkstra while looking at about
forty percent fewer squares. Greedy search looks at fewer still but can
return a worse path, because it ignores the cost already paid.
PLAIN45.8.4 what is really happening inside#
- A-star holds two collections: an open set of squares discovered but not
yet expanded, and a closed set of squares already expanded.
- The open set is a priority queue ordered by
f, so taking the best square
is fast.
- Each square records which square it came from. When the goal is reached,
you follow those links backwards to build the path.
- Grids are convenient for teaching and terrible for large 3D worlds, because
the number of squares grows with area and the paths look like staircases.
- Real 3D games use a navigation mesh: the walkable floor is covered with
a few thousand convex polygons instead of a million squares.
- A-star then runs over polygons, and a second step called the funnel
algorithm pulls the resulting corridor tight into a straight-line path.
- Finally, steering turns that path into motion: the character seeks the
next corner, slows as it arrives, avoids other characters, and blends with
its animation so the feet do not slide.
TECHNICAL45.8.5 the engineer’s version#
- A-star was published in 1968 by Peter Hart, Nils Nilsson and Bertram
Raphael as “A Formal Basis for the Heuristic Determination of Minimum Cost
Paths” in IEEE Transactions on Systems Science and Cybernetics. It is
optimal if the heuristic is admissible, meaning it never overestimates,
and needs no node reopening if the heuristic is also consistent.
- Heuristics by grid type: Manhattan for four-way movement; octile,
dx + dy + (sqrt(2) - 2) * min(dx, dy), for eight-way; Euclidean for
navigation meshes. Using Euclidean on a four-way grid is admissible but
weaker, so the search expands more nodes.
- Variants shipped in real games: hierarchical A-star over a coarse graph
then a fine one; jump point search for uniform grids; theta-star for
any-angle paths; D-star Lite for replanning in changing worlds; and flow
fields, where one Dijkstra pass from the goal produces a direction for
every cell, which is how real-time strategy games move 500 units at once
without 500 searches.
- The standard open-source navigation toolkit is Recast and Detour by Mikko
Mononen: Recast voxelizes the level and extracts walkable convex polygons;
Detour does the queries, path corridors and local avoidance. Unity and
Unreal both ship navigation mesh baking built on the same ideas.
- Decision architectures with their shipped examples: hierarchical finite
state machines everywhere; behaviour trees popularized by Damian Isla’s GDC
2005 talk on the Halo 2 AI; utility scoring used in The Sims from 2000;
and goal-oriented action planning described in Jeff Orkin’s GDC 2006 paper
“Three States and a Plan: The A.I. of F.E.A.R.”, where the state machine
has only three states and a planner sequences them at run time.
- Steering behaviours come from Craig Reynolds. His 1987 SIGGRAPH paper
“Flocks, Herds, and Schools: A Distributed Behavioral Model” introduced
boids with three rules: separation, alignment and cohesion. His 1999 GDC
paper added seek, flee, arrive, pursue, evade, wander, obstacle avoidance
and path following. Flocking that looks alive is those three rules and
nothing else.
- Now the honest part. Game AI is not optimizing for winning. It is
optimizing for the player’s experience, and the two are usually opposed. A
perfect aimbot enemy is trivial to write and miserable to play against.
- Deliberate handicaps that ship in real games: enemies miss the first one or
two shots on purpose; only one or two enemies attack at a time while the
rest circle, a pattern used widely in third-person action games; attacks
have long telegraph animations so you can react; enemies announce their
intentions out loud, which is a user interface disguised as dialogue;
vision cones and hearing radii are far worse than a human’s; racing games
rubber-band opponents to keep the pack close.
- The Pac-Man ghosts from 1980 remain the best teaching example. Four ghosts
with four short, deterministic targeting rules read as four personalities,
and none of them contains anything a modern programmer would call
intelligence.
- Separating fact from marketing: established fact is that shipped game AI
is overwhelmingly hand-authored logic. Active research is reinforcement
learning agents such as OpenAI Five for Dota 2 in 2018 and DeepMind’s
AlphaStar for StarCraft II in 2019, which beat strong humans but are
expensive to train, hard to tune and generally not fun opponents.
Marketing claim is “AI-powered characters” in trailers, which in 2026
almost always means a language model generating dialogue lines, not the
combat behaviour.
WORDS45.8.6 remember these#
- Finite state machine — one mode at a time — a set of states with guarded
transitions, the simplest decision architecture.
- Behaviour tree — a prioritized checklist as a tree — composites, decorators
and leaf tasks ticked from the root each evaluation.
- Utility AI — score everything and pick the best — action selection by
evaluating scoring curves over world variables.
- GOAP — describe the goal, let it plan — goal-oriented action planning,
an A-star search over world states using action preconditions and effects.
- Heuristic — an educated guess of remaining cost — the
h term in A-star,
admissible if it never overestimates.
- Navigation mesh — the walkable floor as polygons — a convex polygon
decomposition of traversable surfaces used as the pathfinding graph.
- Steering — turning a path into movement — force-based local motion such as
seek, arrive, separation and obstacle avoidance.
45.9 Rendering a game frame, specifically#
PLAIN45.9.1 in simple words#
- In one line, the drawing pipeline is: points in space, moved into camera
view, turned into triangles, filled in as pixels, shaded, depth-tested and
written to a picture.
- A game adds a lot of decisions around that, because it must do all of it in
under 16.67 milliseconds.
- First it works out what it does not need to draw at all. That is
culling. Anything behind you or outside the camera’s cone is thrown
away immediately, and anything fully hidden behind a wall as well.
- Second it groups what is left so the processor talks to the graphics chip
as few times as possible. Each of those conversations is a draw call
and they are expensive on the processor side.
- Third it sorts. Solid things are drawn nearest first, so far-away pixels
are rejected cheaply. See-through things must be drawn furthest first, so
the blending is right.
- Then it draws shadows, then the world, then the see-through things, then a
stack of full-screen effects, and finally the user interface on top.
PLAIN45.9.2 a picture in your head#
- Think of a stage crew setting up a theatre scene in one minute.
- First they check the script: what is actually visible from where the
audience sits. Everything else stays in the wings. That is culling.
- Then they carry things on in loads rather than one item at a time, because
every trip costs time regardless of what is on it. That is batching.
- They set the lights before the actors walk on, because moving lights during
the scene is expensive. That is the shadow pass.
- Glass and gauze go on last and in the right order, because you can see
through them and the order changes what you see.
- And the surtitles are projected on top of everything at the end, in their
own crisp resolution. That is the user interface.
Where this comparison breaks: the stage crew works once and the scene runs.
The renderer redoes the entire setup from nothing, sixty times a second, with
the camera in a new place each time.
PLAIN45.9.3 a worked example#
- A real frame breakdown, taken from a profiler on a mid-range PC at 2560 by
1440 with a 60 frames per second target. The numbers are typical rather
than from one specific game.
| Stage |
Time (ms) |
Share |
| Shadow map passes |
2.4 |
14 percent |
| Depth prepass and G-buffer |
3.1 |
19 percent |
| Lighting and reflections |
3.8 |
23 percent |
| Transparency and effects |
1.6 |
10 percent |
| Post-processing stack |
2.7 |
16 percent |
| Upscale and interface |
1.1 |
7 percent |
| Present and slack |
1.9 |
11 percent |
- Total is 16.6 ms, just inside the 16.67 ms budget.
- Read the first row again. Shadows cost 2.4 ms, which is more than the
entire user interface and post-processing of many older games, and they are
just one lighting feature.
- This is why the graphics settings menu exists. Dropping shadow resolution
from 2048 to 1024 per cascade typically saves 30 to 50 percent of that row.
PLAIN45.9.4 what is really happening inside#
- Frustum culling tests each object’s bounding sphere or box against the
six planes of the camera’s viewing pyramid. A sphere fully outside any one
plane is rejected. This is a handful of arithmetic operations per object.
- Occlusion culling removes what is hidden behind other things. It is
harder, because you must know what is in front before you know what is
hidden. Common approaches are precomputed visibility per region, a
low-resolution software depth buffer rendered on the processor, and
graphics-chip queries whose answers arrive a frame or two late.
- Batching merges objects that share a material into one draw call.
Instancing goes further: send one mesh and a list of 5,000 positions,
and the chip draws all 5,000 in one call.
- Sorting solid objects front to back lets the depth test discard hidden
pixels before shading them. On modern hardware a depth prepass, which draws
depth only and then shades with the depth test set to equal, guarantees
every pixel is shaded exactly once.
- Forward rendering shades each object against every light that touches
it. Cost grows as objects times lights. It handles transparency and
hardware anti-aliasing naturally.
- Deferred rendering first writes surface properties into several
full-screen buffers, together called the G-buffer, then computes
lighting once per screen pixel. Cost is decoupled from scene complexity,
which is why it won for scenes with many lights.
- Deferred rendering’s costs are memory bandwidth and transparency.
See-through surfaces cannot be written into a single G-buffer pixel, so
they are drawn afterwards in a separate forward pass.
TECHNICAL45.9.5 the engineer’s version#
- G-buffer bandwidth arithmetic. At 1920 by 1080 with four 32-bit render
targets plus a 32-bit depth buffer, that is 5 x 4 bytes x 2,073,600 pixels,
about 41.5 megabytes written per frame, or 2.5 gigabytes per second at 60
frames per second, before the lighting pass reads it all back.
- At 3840 by 2160 the same layout is about 166 megabytes per frame and about
10 gigabytes per second of writes. This is why 4K deferred rendering is a
bandwidth problem before it is a compute problem.
- Modern engines mostly use clustered or tiled deferred and forward variants,
which bin lights into screen tiles or view-space clusters so each pixel
only evaluates the lights that reach it. Unreal Engine 5 and Unity’s
High Definition Render Pipeline both do this.
- Draw call budgets. Under Direct3D 11 the per-call driver cost made 1,000 to
3,000 calls per frame a common ceiling. Direct3D 12, Vulkan and Metal cut
that cost sharply, and with instancing, bindless resources and
GPU-driven indirect draws, 10,000 to 30,000 batched calls per frame is
normal in 2026.
- Transparency ordering has no cheap correct answer. Per-object sorting fails
for intersecting or concave transparent geometry. The options are alpha
testing, which is opaque and sortable; per-triangle sorting, which is
expensive; depth peeling, which costs one pass per layer; or weighted
blended order-independent transparency, published by McGuire and Bavoil in
2013, which is approximate but cheap and widely shipped.
- Shadows in practice are cascaded shadow maps for the sun: the view frustum
is split into 3 or 4 depth ranges, each rendered from the light into a
1024 to 2048 square depth texture. Each cascade is another full scene
traversal of shadow casters. Point lights need six faces. Filtering ranges
from simple percentage-closer filtering to variance and moment methods.
- A typical post-processing stack, in execution order: depth of field, motion
blur, bloom, auto-exposure, tone mapping (commonly an ACES curve), colour
grading through a 3D lookup texture, temporal anti-aliasing, upscaling,
sharpening, then film grain and vignette.
- Upscalers such as DLSS, FSR and XeSS are inserted after the main scene and
before the user interface, so the interface renders at native output
resolution and stays sharp. Getting that order wrong makes text blurry, and
it is a common bug in early builds.
- The interface is drawn last, usually as batched textured quads from a
texture atlas with a signed distance field font, in a separate orthographic
pass, sometimes at a different resolution from the scene.
- Capture and profiling tools: RenderDoc for a full frame capture on almost
any API; PIX on Windows for Direct3D 12 timing; NVIDIA Nsight Graphics and
Radeon GPU Profiler for hardware counters; Xcode’s Metal debugger on Apple
platforms; Unity’s Frame Debugger; Unreal’s
stat gpu, stat unit and
ProfileGPU console commands.
WORDS45.9.6 remember these#
- Frustum culling — skip what is off-screen — rejecting bounding volumes
against the six camera planes.
- Occlusion culling — skip what is hidden — rejecting objects proven to be
behind other opaque geometry.
- Draw call — one instruction to draw something — a submitted command with a
bound pipeline state, costing processor time regardless of triangle count.
- Instancing — one command, many copies — drawing N copies of a mesh from one
call with per-instance data.
- G-buffer — the sheet of surface facts — the set of render targets holding
albedo, normal, roughness, metalness and depth in deferred rendering.
- Deferred rendering — light once per pixel, not per object — decoupling
shading from geometry by writing surface data first.
- Post-processing — the full-screen effects at the end — the ordered chain
from depth of field through tone mapping to anti-aliasing and upscaling.
45.10 Audio in games#
PLAIN45.10.1 in simple words#
- Sound is a pressure wave in air, and a computer stores it as a long list of
numbers, typically 48,000 numbers per second per channel.
- A game does not play files. It plays events: “footstep on gravel”,
“pistol fire”, “door creak”. One event may pick one of eight recordings at
random and change its pitch slightly so it does not sound repetitive.
- Those recordings are packed into sound banks, loaded and unloaded in
groups, usually one bank per level or per character.
- A sound in the world has a position. The mixer works out how loud it should
be from the distance, and how much goes to each speaker from the angle.
- If a wall is in the way, the game fires a ray from the source to your ears,
and if it is blocked, it turns the volume down and removes the high
frequencies, because that is what walls do to sound.
- All the sounds are grouped into buses: music, effects, dialogue,
interface. Each bus has its own volume, and rules such as “duck the music
by 6 decibels while anyone is speaking”.
- Music in a modern game is not one track. It is layers that fade in as
danger rises, and blocks that swap at musical boundaries.
PLAIN45.10.2 a picture in your head#
- Imagine a live sound engineer at a theatre with a mixing desk.
- Every microphone and every playback source is a channel on the desk.
Channels are grouped into buses: cast, orchestra, effects.
- She rides the faders as the scene changes, pulls the music down when
somebody speaks, and adds reverb when the scene moves to a cathedral.
- She also has a limit: the desk has 64 channels. If a 65th sound is needed,
something quiet must be dropped.
- A game audio engine is that desk, run by rules instead of a person, updated
sixty times a second.
Where this comparison breaks: the theatre engineer knows the script. The game
engine does not know what will happen next, so every rule must be written to
handle any order of events, including 200 sounds at once.
PLAIN45.10.3 a worked example#
- Audio memory arithmetic, which is what decides whether a sound is kept
decompressed in memory or streamed from disk.
- Uncompressed 48 kHz, 16-bit stereo is 48,000 x 2 x 2 = 192,000 bytes per
second. One minute is 11.5 megabytes. One hour is 691 megabytes.
- The same audio in Vorbis at 128 kilobits per second is 16,000 bytes per
second: 0.96 megabytes per minute, 57.6 megabytes per hour, a saving of
about 12 to 1.
- So the rule of thumb is: short and frequent sounds are decompressed into
memory once and played from there; long music and dialogue are streamed
from storage and decoded on the fly.
| Content |
Typical handling |
Cost |
| Footsteps, gunfire |
Decompressed in RAM |
~50 KB each |
| Ambience loops |
Compressed in RAM |
~1 MB each |
| Music tracks |
Streamed from disk |
2 buffers |
| Voice lines |
Streamed, bank per scene |
2 buffers |
- A console game commonly budgets 100 to 500 megabytes of memory for audio,
which is a real constraint against a script with 40,000 recorded lines.
PLAIN45.10.4 what is really happening inside#
- The audio system does not run on the frame clock. It runs on its own
high-priority thread with its own deadline.
- That deadline is the buffer size. A 512-sample buffer at 48 kHz must be
filled every 512 / 48,000 seconds, which is 10.67 milliseconds. A
256-sample buffer is 5.33 milliseconds.
- If the audio thread misses that deadline, the hardware plays whatever was
in the buffer, and you hear a click or a stutter. There is no equivalent of
a dropped frame that merely looks bad.
- This is why audio must never wait for the game. The game posts events into
a queue, and the audio thread reads them when it wakes.
- Each buffer fill is: gather the active voices, decode any compressed ones,
apply per-voice volume, pitch and filters, sum them into buses, apply bus
effects such as reverb and compression, and write the result out.
- Voice limits exist because that work is per voice. A budget of 32 to 128
simultaneous voices is normal, and beyond it the quietest and most distant
sounds are stolen.
TECHNICAL45.10.5 the engineer’s version#
- Distance attenuation. The physical law is inverse square, which is minus 6
decibels per doubling of distance. Games rarely use it directly; they use
authored curves with a minimum distance, inside which volume is constant,
and a maximum distance, beyond which the sound is culled entirely.
- Occlusion versus obstruction: occlusion is a full barrier between
source and listener and attenuates both the direct and reverberant paths;
obstruction blocks the direct path only while sound still arrives via
reflections. Both are usually implemented as raycasts driving a low-pass
filter cutoff and a gain.
- Spatialization ranges from cheap stereo panning, through vector-based
amplitude panning for surround layouts, to head-related transfer function
convolution for binaural headphone output. Shipping implementations include
Sony’s Tempest 3D AudioTech on PlayStation 5, Dolby Atmos, Windows Sonic
and Valve’s Steam Audio.
- Adaptive music has two standard techniques. Vertical layering plays
several stems at once and cross-fades them with game intensity.
Horizontal re-sequencing switches between composed blocks at musical
boundaries, using short transition segments so the change lands on a beat.
- Middleware exists because building all of this well takes years. The two
dominant products are FMOD Studio from Firelight Technologies and Wwise
from Audiokinetic, which Sony acquired in 2019. Both give composers and
sound designers an editor that produces data the game loads, so audio
changes do not require a programmer or a rebuild.
- Wwise pricing per title, from the published rate card, as an example of how
middleware is sold:
| Tier |
Budget cap |
First platform |
| Indie |
250k USD |
Free |
| Pro |
2M USD |
7,000 USD |
| Premium |
none |
22,000 USD |
| Platinum |
none |
40,000 USD |
- Additional platforms cost extra on the paid tiers, which is why a small
team shipping on five platforms must budget for audio middleware as a real
line item rather than an afterthought.
- Streaming considerations: each streamed voice needs at least two buffers so
one can be filled while the other plays, plus a seek-and-decode budget. On
consoles with a hardware decompressor, audio streaming competes with
texture streaming for the same input-output bandwidth, and audio must win,
because a late texture is a blurry wall and a late sound is a click.
- Diagnostic tools: the FMOD Studio and Wwise live profilers connect to a
running game and show every active voice, bus level and memory pool;
Unreal’s
stat audio and au.Debug commands; Unity’s Audio Profiler
module; and pw-top or pactl on Linux for the system side.
WORDS45.10.6 remember these#
- Sound bank — a group of sounds loaded together — a packaged set of audio
assets and event metadata with a shared lifetime.
- Voice — one sound currently playing — an active mixer channel consuming
decode and processing budget.
- Attenuation — getting quieter with distance — a gain curve over distance,
physically minus 6 dB per doubling.
- Occlusion — a wall in the way — attenuation and low-pass filtering applied
when the direct path to the listener is blocked.
- Bus — a group fader — a mix group through which many voices are summed
before further processing.
- Middleware — audio tools bought in — FMOD or Wwise, giving designers an
authoring environment decoupled from engine code.
45.11 Multiplayer and netcode#
PLAIN45.11.1 in simple words#
- Here is the problem, and it cannot be solved, only hidden.
- Information takes time to travel. Light in a glass fibre goes about 200,000
kilometres a second, which is fast but not instant.
- Mumbai to Singapore and back is roughly 60 milliseconds of round trip in
practice. Mumbai to Frankfurt is roughly 120. Mumbai to the United States
east coast is roughly 240.
- So when you press fire, the server learns about it at best 30 milliseconds
later, and you learn its answer 30 milliseconds after that.
- Meanwhile your screen must keep drawing at 60 frames a second. It cannot
wait for the answer.
- So the game lies to you, carefully. It shows you what it believes will
happen, and corrects itself later when the truth arrives.
- Everything in netcode is a variation on that one trick, plus the question
of who is allowed to decide the truth.
- The answer to that question is: a server that nobody plays on, owned by the
game company. That is an authoritative server, and it won because any
other arrangement lets a player’s own machine cheat.
PLAIN45.11.2 a picture in your head#
- Imagine two people playing chess by post, with letters taking three days.
- If each waits for the other’s letter before thinking, a game takes a year.
- So each of them keeps a board at home and moves their own piece
immediately, guessing what the opponent will do.
- When the letter arrives, they compare. If the guess was right, nothing
changes. If it was wrong, they must undo their guessed moves and redo them
from the true position.
- That undo-and-redo is exactly what your game does, sixty times a second,
with the postal delay measured in milliseconds instead of days.
- And there is a referee whose board is the only one that counts. If your
board disagrees with the referee’s, yours is wrong by definition.
Where this comparison breaks: chess players can wait, and a game cannot. Also,
in chess both boards are complete. In a game the referee deliberately does not
tell you about pieces you cannot see, because if it did, you could cheat.
PLAIN45.11.3 a worked example#
- The full sequence for one shot, with real numbers. Round trip time is 80
milliseconds, so one-way delay is 40 milliseconds. The server runs at 64
ticks per second, so a tick is 15.6 milliseconds. Your interpolation delay
is 100 milliseconds.
t=0 you press fire; client predicts the shot at once
t=0 input #4471 stamped and sent over UDP
t=40 server receives input #4471
t=40 server rewinds all hitboxes by 40 + 100 = 140 ms
t=40 server tests the ray against the rewound world
t=47 next server tick packages the result
t=87 you receive "hit confirmed, input #4471 processed"
t=87 client reconciles: state matches, nothing visible
- Now the same event from the victim’s point of view. On their screen they
ran behind a wall at their local time t=-20 milliseconds, that is, 20
milliseconds before you pressed fire.
- The server still counted the hit, because it rewound the world to where you
saw them, and there they were in the open.
- How far can that be? At a running speed of 6 metres per second, 140
milliseconds is 0.84 metres. That is most of a body width, which is exactly
why it feels like being shot through a wall.
- The 140 milliseconds is not padding. It is 40 milliseconds of network delay
plus the 100 milliseconds of deliberate interpolation delay your client
uses to smooth other players’ movement.
PLAIN45.11.4 what is really happening inside#
- Client-side prediction. Your client never sends “I am at position X”.
It sends “I held forward and pressed fire, and this is input number 4471”.
Then it immediately applies that input locally so the screen responds now.
- It keeps every unacknowledged input in a list.
- Server reconciliation. The server replies with “here is your true state
after I processed input 4471”. Your client snaps to that state and then
replays inputs 4472 onwards on top of it.
- If the prediction was correct, the replay lands exactly where you already
were and you see nothing. If it was wrong, you see a small correction.
- Entity interpolation. Other players are not predicted. Instead your
client deliberately renders them slightly in the past, between the last two
snapshots it received, so their movement is smooth even though the
snapshots arrive unevenly.
- Lag compensation. The server records where every hitbox was for the
last half second or so. When your shot arrives, it rewinds to what you were
actually looking at, tests the hit there, then restores the present.
- That is the entire architecture. Prediction hides your own latency.
Interpolation hides everyone else’s jitter. Lag compensation makes aiming
fair. The cost is paid by the person being shot.
TECHNICAL45.11.5 the engineer’s version#
- The techniques above were set out publicly in Yahn Bernier’s 2001 paper for
Valve, “Latency Compensating Methods in Client/Server In-game Protocol
Design and Optimization”, building on the prediction work in QuakeWorld
from 1996. Almost every shooter since uses this model.
- Blizzard’s Overwatch, described in Timothy Ford’s GDC 2017 talk, runs 16
millisecond command frames, about 62.5 per second, tightened to about 7
milliseconds in tournament configuration. The client clock runs ahead of
the server by roughly half the round trip plus one buffered command frame,
so at 160 milliseconds of latency it predicts about 96 milliseconds ahead.
Above about 220 milliseconds round trip it stops predicting hits.
- Tick rate is how often the server simulates. 64 ticks is one every
15.625 milliseconds; 128 ticks is one every 7.8125 milliseconds. Halving
the tick interval halves the average quantization error on event timing,
from about 7.8 to about 3.9 milliseconds, and doubles both server processor
cost and downstream bandwidth. That is a money decision, not a technical
one, which is why third-party services ran 128-tick Counter-Strike servers
while official matchmaking ran 64.
- Counter-Strike 2, released in September 2023, introduced sub-tick
input: the client timestamps each input with its exact moment inside the
tick, and the server uses that timestamp rather than snapping to the tick
boundary. Valorant instead runs 128-tick servers. Whether sub-tick fully
matches a true 128-tick server is genuinely disputed by players and
analysts, and there is no neutral published measurement that settles it.
- Deterministic lockstep is the other architecture. Only player commands
are transmitted; every machine runs an identical simulation. Bandwidth is
independent of the number of units, which is why real-time strategy games
use it. The canonical write-up is Mark Terrano and Paul Bettner’s GDC 2001
paper “1500 Archers on a 28.8”, about Age of Empires.
- Lockstep requires bit-identical simulation across every machine, for the
reasons given in section 45.7: unspecified transcendental functions,
compiler reordering, fused multiply-add, and non-deterministic thread
ordering will all desynchronize it. It also needs a command delay of two to
five turns, typically 100 to 250 milliseconds, so that all commands arrive
before the turn executes. That delay is why strategy games feel slightly
sluggish by design.
- Rollback netcode for fighting games, popularized by Tony Cannon’s GGPO from
2006, is lockstep plus speculation: assume the opponent pressed nothing,
and when the real input arrives, restore the saved state and re-simulate
the intervening frames. It needs a fast full state save and restore every
frame, which constrains how the game is written.
- Bandwidth. A worked example: 64 players, 20 snapshots per second, 200
bytes per snapshot after delta compression and relevancy culling, gives
64 x 20 x 200 = 256,000 bytes per second, about 2.05 megabits per second
outbound per server, before packet headers.
| Genre |
Snapshot rate |
Down per client |
| Competitive shooter |
60 to 128 Hz |
200 to 800 kbps |
| Battle royale, 100 players |
20 to 30 Hz |
150 to 500 kbps |
| MMO |
5 to 20 Hz |
30 to 150 kbps |
| Strategy, lockstep |
5 to 10 Hz |
5 to 30 kbps |
- Delta compression sends only what changed since the last snapshot the
client acknowledged, a model established by Quake 3 in 1999. Combined with
quantization it is dramatic: a position stored as three 32-bit floats is 12
bytes; quantized to 16-bit fixed point over a bounded world it is 6 bytes;
as a delta from the previous value with variable-length bit packing it is
often 1 to 3 bytes.
- Relevancy culling, sending a client only what it could plausibly
perceive, saves bandwidth and is also the single most effective anti-cheat
measure that exists, because a wallhack cannot draw data it never
received. Riot’s Fog of War in Valorant, shipped in 2020, is the
best-known example.
- Why UDP. TCP, standardized in RFC 793 in 1981 and now RFC 9293 from
2022, guarantees an ordered reliable byte stream. If packet 5 is lost,
packets 6, 7 and 8 sit in the kernel buffer until 5 is retransmitted. That
is head-of-line blocking, and it costs at least one round trip. For
position updates it is exactly wrong: by the time packet 5 arrives it is
stale and you already hold newer truth.
- UDP, RFC 768 from 1980, has no ordering, no retransmission and no
congestion control. Games build their own reliability layer and choose per
message: unreliable for positions, since the next update supersedes this
one; reliable and ordered for chat and inventory; reliable but unordered
for one-off events. QUIC, RFC 9000 from 2021, offers independent streams
over UDP and is used for some game backend traffic, but action games
generally still roll their own.
- Practical UDP detail: since there is no connection, NAT devices time out
idle mappings, commonly after 30 to 120 seconds, so games send small
keep-alive packets.
- Matchmaking is a multi-objective search over skill, latency, party
size, role and queue time, widening its tolerances as the wait grows.
Skill systems descend from Arpad Elo’s chess rating from the 1960s,
through Glicko, to Microsoft’s TrueSkill from 2007, which models skill as
a distribution with an uncertainty that shrinks as it observes you.
- NAT traversal matters because most home connections, and every
carrier-grade NAT connection, have no reachable public address. STUN,
currently RFC 8489 from February 2020, which obsoletes RFC 5389 of 2008
and RFC 3489 of 2003, lets a host discover the public address and port its
NAT assigned. TURN, currently RFC 8656 from February 2020, relays traffic
when a direct path cannot be established. ICE, RFC 8445 from 2018,
gathers all candidate addresses and systematically tests pairs.
- Hole punching works when both sides send outbound packets simultaneously
so each NAT creates a mapping the other can use. It fails when both ends
use symmetric NAT, which allocates a different external port per
destination. A relay is then the only option, and a single-digit to
low-double-digit percentage of connection attempts need one in practice.
- Relays such as Steam Datagram Relay carry game traffic over a
provider’s private backbone. The benefits are that the server’s real
address is never exposed, which prevents denial-of-service attacks on
individual players; routing is often better than the public internet; and
NAT problems disappear.
- The unfixable part: a player far from any datacentre cannot be given a
competitive experience. No amount of netcode removes 240 milliseconds.
This is a real and often-ignored fairness issue for players in regions
without local server presence.
WORDS45.11.6 remember these#
- Authoritative server — the referee whose word counts — a server that
simulates canonically and treats client messages as inputs, never as state.
- Client-side prediction — acting before permission — applying local input
immediately and retaining it for later replay.
- Reconciliation — correcting the guess — snapping to the server state and
replaying unacknowledged inputs on top of it.
- Entity interpolation — drawing others slightly in the past — rendering
remote entities between two received snapshots with a fixed delay buffer.
- Lag compensation — rewinding to what the shooter saw — server-side
historical hitbox rewind by the shooter’s latency plus interpolation delay.
- Tick rate — how often the server thinks — simulation steps per second, 64
ticks being 15.625 ms and 128 ticks 7.8125 ms.
- Delta compression — send only what changed — encoding a snapshot as a
difference from the last one the client acknowledged.
- Deterministic lockstep — send commands, not state — identical simulation on
every machine, requiring bit-exact reproducibility.
45.12 Cheating and anti-cheat#
PLAIN45.12.1 in simple words#
- Cheating in an online game means making your copy of the program do
something the designers did not intend, to gain an advantage.
- An aimbot reads the game’s memory to find where other players are, then
points your weapon at them for you.
- A wallhack draws other players through walls. It works only because
your machine was told where they are.
- A speed hack changes the clock the game reads, so your character moves
faster than everyone else’s.
- Packet manipulation means interfering with the messages themselves: a
lag switch drops your outgoing packets so others cannot hit you.
- Some cheating is not technical at all: paying someone to play your account,
deliberately losing to face weaker opponents, or trading wins.
- The one rule that explains all defences is this: your machine belongs to
the attacker. Anything the game checks on your machine, the attacker can
remove.
- So the only real defence is to check on the server, and to never send your
machine information it is not entitled to.
PLAIN45.12.2 a picture in your head#
- Think of an examination hall.
- Asking candidates to mark their own papers is the client trusting itself.
Some will cheat, and you will never know.
- Collecting the papers and marking them centrally is server-side validation.
Now the cheating must happen in the room, not in the marking.
- Not printing the answers on the back of the paper is relevancy culling.
You cannot copy what you were never given.
- Invigilators watching for suspicious behaviour are statistical detection.
- And searching candidates at the door, going through their pockets, is
kernel-level anti-cheat. It works, and people reasonably object to it.
Where this comparison breaks: an exam lasts three hours. Anti-cheat software
that runs at boot is searching your pockets every day whether or not there is
an exam, which is precisely the objection people raise.
PLAIN45.12.3 a worked example#
- How server-side validation actually looks, for movement.
- The client sends: “input 4471, held forward, delta time 15.6 milliseconds”.
- The server does not read a position. It runs the same movement code the
client ran, from the state it already holds.
- Maximum run speed is 5.2 metres per second. In 15.6 milliseconds the
maximum possible movement is 5.2 x 0.0156 = 0.081 metres.
- If the client claims a delta time of 100 milliseconds while only 15.6 have
passed on the server’s clock, that is a speed hack, and it is rejected by
comparing the client’s claimed time budget against elapsed server time.
- The same pattern applies everywhere: fire rate against the weapon’s
cooldown, damage against the weapon’s table, line of sight against the
server’s own geometry, and inventory against the server’s own database.
| Cheat |
Defence that works |
| Aimbot |
Statistical aim analysis |
| Wallhack |
Do not send hidden positions |
| Speed hack |
Server-side time budget |
| Damage edit |
Server owns the damage table |
| Item duplication |
Atomic server transactions |
PLAIN45.12.4 what is really happening inside#
- Statistical detection looks at how you aim rather than at your files.
- Human aim has tremor, overshoot, correction and a reaction time that never
drops below about 150 milliseconds for a genuinely unexpected event.
- A machine has none of those. Its angular snap to a target is too fast, too
precise, and too consistent across distances.
- Detectors measure the distribution of flick times, the time between a
target becoming visible and the first shot, the hit rate as a function of
range, and the smoothness of the mouse path.
- The output is a probability, not a verdict, which is why bans are issued in
waves rather than instantly: batching hides which specific detection fired,
so cheat authors cannot binary-search their way around it.
- False positives are the hard part. At a 0.1 percent false positive rate
across 10 million players, 10,000 innocent people are banned. This is why
detections are usually required to be independently corroborated.
TECHNICAL45.12.5 the engineer’s version#
- Categories in more detail: memory-reading external cheats; injected
internal cheats hooking the rendering or input path; triggerbots; radar
overlays; automated recoil control macros in hardware mice; lag switches
and packet delay; and account services such as boosting and win trading.
- Two categories defeat all software-only defences. DMA cheats use a
second computer with a PCIe direct memory access card reading the gaming
machine’s memory over the bus, so nothing runs on the machine being
watched. Screen-reading cheats capture the video output with a capture
card, run object detection on a second machine, and drive a hardware device
that emulates a mouse. Both are a live problem in 2026 and neither is
detectable by inspecting the game machine’s software.
- Kernel-level anti-cheat runs a driver at ring 0 so it can see and block
things user-mode code cannot: other drivers loading, handles opened to the
game process, hooked system calls, and tampered kernel structures. Shipped
examples include Riot Vanguard, introduced with Valorant in 2020 and
extended to League of Legends in 2024; Easy Anti-Cheat, now owned by Epic
Games; BattlEye; and Activision’s Ricochet, introduced in 2021.
- The honest debate, both sides in full. For: cheats themselves run in the
kernel, and a user-mode watcher simply cannot see a kernel-mode cheat, so
without a kernel presence the defender has already lost the privilege race.
Games with kernel anti-cheat measurably have fewer visible cheaters.
- Against: it is a signed driver with total access to your machine, shipped
by a game company, usually loading at boot whether or not you play. A bug
in it is a system-wide vulnerability. This is not hypothetical: the
mhyprot2.sys driver shipped with Genshin Impact was abused by ransomware
operators to disable antivirus software, and the July 2024 CrowdStrike
incident showed what a single faulty kernel-mode update does at scale.
- It also excludes people. Kernel anti-cheat generally does not work under
Proton on Linux or the Steam Deck unless the developer explicitly enables
the vendor’s Linux support, which many competitive titles decline to do.
- The platform direction is changing. Microsoft announced the Windows
Resiliency Initiative in November 2024 and from 2025 began moving endpoint
security products out of kernel mode into a supported user-mode platform,
with security vendors involved in the design. As of August 2026 this is a
live transition rather than a completed one, and how anti-cheat fits into
it is not yet settled.
- Hardware-backed identity raises the cost of ban evasion. Valorant requires
TPM 2.0 and Secure Boot on Windows 11, which lets bans attach to something
harder to change than an account or a network address.
- Machine learning detection is real and shipped: Valve described VACnet, a
classifier trained on human-reviewed cases, at GDC in 2018, and comparable
systems exist at other publishers. It is a filter that raises human review
efficiency, not an oracle.
- The arms race is structural and permanent. Cheat development is a paid
industry with subscription pricing, private builds to avoid signature
detection, and customer support. Anti-cheat cannot win; it can only make
cheating expensive, unreliable and short-lived enough that most people do
not bother.
WORDS45.12.6 remember these#
- Aimbot — the machine aims for you — automated target acquisition driven by
memory-read entity positions or screen-space detection.
- Wallhack — seeing through walls — rendering entity positions the client
received but should not have been told about.
- Server-side validation — the server checks everything — simulating client
inputs authoritatively and rejecting physically impossible claims.
- Relevancy culling — do not send what cannot be seen — filtering network
state by visibility, which prevents wallhacks at the source.
- Kernel-level anti-cheat — a watcher with full system access — a ring 0
driver monitoring for tampering, with the privilege and stability trade-off
that implies.
- Ban wave — punishing in batches — delayed enforcement that obscures which
detection triggered, slowing the cheat authors’ feedback loop.
45.13 What actually happens when you double-click a game#
PLAIN45.13.1 in simple words#
- The short version of the ordinary part: the operating system reads the
file’s header, works out how much memory the program needs, copies the code
and data into that memory, fills in the addresses of the system libraries
the program uses, and jumps to its first instruction.
- That is true for every program. A game then does a great deal more before
you see anything.
- It usually starts a launcher first, which checks for updates, verifies
that your files have not been altered, and logs you in.
- It starts the anti-cheat service, if there is one.
- Then it starts the real game program, which must find a graphics card, ask
the driver for a device, and set up the chain of pictures it will draw into.
- Then it must turn its shader source into machine code for your specific
graphics chip. On the first run this can take minutes, and if it is done
lazily while you play, you get the famous first-run stutter.
- Then it loads a small amount of content for the menu, and only then does
the loop from section 45.3 start running.
- Choosing a level starts a second, much bigger load, and finally you play.
PLAIN45.13.2 a picture in your head#
- Think of an aircraft before a flight.
- Opening the door is the double-click. Nothing is running yet.
- Ground power, then auxiliary power, then engines: that is the loader, the
launcher and the engine start.
- The pre-flight checklist is the device and swap chain creation. Every item
must be confirmed before the next.
- Loading passengers and fuel is asset loading. It is the slowest part and it
scales with how far you are going.
- Taxiing is the main menu: you are moving, everything is running, but the
real work has not started.
- Take-off is entering the level.
Where this comparison breaks: an aircraft does the same checklist every time.
A game’s first run is dramatically different from its second, because the
shader cache, the file system cache and the driver cache are all empty the
first time.
PLAIN45.13.3 a worked example#
- The twenty-five step trace, with realistic timings for a Windows PC with an
NVMe solid-state drive, a mid-range graphics card and a broadband
connection. Cold means first ever run; warm means a later run.
| Step |
What happens |
Warm time |
| 1 |
Shell creates the process |
20 ms |
| 2 |
Loader maps the launcher |
30 ms |
| 3 |
Launcher checks for updates |
200 to 2000 ms |
| 4 |
File integrity spot check |
500 ms to 30 s |
| 5 |
Anti-cheat service starts |
50 to 500 ms |
| 6 |
Launcher spawns the game |
50 ms |
| 7 |
Loader maps the game image |
100 to 400 ms |
| 8 |
Runtime and static init |
20 to 100 ms |
| 9 |
Read config and command line |
5 to 20 ms |
| 10 |
Memory pools reserved |
10 to 50 ms |
| 11 |
Job system threads start |
5 to 20 ms |
| 12 |
Archives mounted, index read |
50 to 300 ms |
| 13 |
Enumerate adapters, device |
100 to 500 ms |
| 14 |
Create swap chain buffers |
50 to 200 ms |
| 15 |
Allocate render targets |
50 to 200 ms |
| 16 |
Load or compile shader states |
2 s warm, minutes cold |
| 17 |
Audio device and mixer graph |
50 to 200 ms |
| 18 |
Enumerate input devices |
10 to 100 ms |
| 19 |
Sockets, DNS, account login |
200 to 1500 ms |
| 20 |
Load front-end bundle |
500 to 3000 ms |
| 21 |
Main menu, loop now running |
first frame |
| 22 |
You pick a level, load list |
10 ms |
| 23 |
Stream, decompress, upload |
3 to 30 s |
| 24 |
Warm-up frames force work |
1 to 5 s |
| 25 |
Gameplay loop settles |
steady state |
- Warm total to the main menu is roughly 4 to 8 seconds. Cold total can be
several minutes, almost all of it in step 16.
- Step 16 is the one worth understanding. Shader source is compiled at build
time into an intermediate form, but the final translation into your exact
graphics chip’s instructions can only happen on your machine, because the
developer does not know which chip you have.
- A game may have 20,000 to 200,000 pipeline states. If each takes 20
milliseconds to build, 50,000 of them is about 17 minutes of one core, or
roughly one minute spread across sixteen cores.
- If the game builds them lazily instead, the first time a new effect appears
the frame stops for 20 to 200 milliseconds. That is the stutter. Consoles
never have it, because the chip is known and the compilation happened at
build time.
PLAIN45.13.4 what is really happening inside#
- A save file is a written-down copy of the parts of the world the
designer decided matter.
- It is never the whole world. Nobody stores every leaf position. It stores
your position, your inventory, quest flags, which doors are open, which
enemies are dead, and a version number.
- Turning live objects into a flat sequence of bytes is called
serialization, and reading it back is deserialization.
- The formats used, in rough order of how common they are:
| Format |
Example use |
Trade-off |
| Chunked binary |
Most console games |
Fast, opaque |
| Tagged binary |
Minecraft NBT |
Flexible, compact |
| JSON, often gzipped |
Many indie games |
Readable, large |
| SQLite database |
Mobile, big worlds |
Robust, heavier |
| Engine key-value |
Unity PlayerPrefs |
Settings only |
- Minecraft’s NBT, standing for Named Binary Tag, is a tagged tree of
typed values, gzip-compressed, with world data grouped into region files
that each hold a 32 by 32 block of chunk columns.
- The correct way to write a save is: write to a temporary file, flush it to
the storage device, then rename it over the old one. Rename is atomic on
every mainstream file system, so a power cut leaves either the old save or
the new one, never half of each. Games that write in place corrupt saves.
- Saves must carry a version number, because patch 1.20 must still load a
save written by 1.00, which means keeping an upgrade path for every old
version. This is why some games break saves at a major update and why
players are right to be annoyed about it.
- Online games sign or checksum saves and usually store them server-side, so
that editing them is pointless. Single-player games often do not, which is
why save editors exist and are harmless.
TECHNICAL45.13.5 the engineer’s version#
- On Windows the image is a PE file: the loader maps sections according to
the section table, applies base relocations if the preferred base is taken,
resolves the import address table, runs TLS callbacks, then calls the entry
point. On Linux it is an ELF file handled by
ld.so. Section 45.13 does
not repeat that machinery; it only notes where it sits in the sequence.
- Graphics initialization in Direct3D 12 is: create a DXGI factory, enumerate
adapters,
D3D12CreateDevice, create command queues, then
CreateSwapChainForHwnd with 2 or 3 buffers and a chosen swap effect,
usually flip-model. In Vulkan it is vkCreateInstance,
physical device selection, vkCreateDevice, then a surface and a
VkSwapchainKHR.
- Pipeline state objects bundle shaders, blend, depth, rasterizer and vertex
layout into one immutable object, which is why they are compiled up front
rather than assembled per draw. Both APIs support a pipeline cache blob
that can be saved to disk and reloaded, which is what makes the warm run
fast. Steam additionally distributes precompiled Vulkan pipeline caches for
Proton titles so a Steam Deck rarely compiles at play time.
- Asset streaming on modern consoles uses hardware decompression and a
direct storage path: the PlayStation 5 Kraken decompressor is rated at
about 5.5 gigabytes per second of compressed input, and Microsoft’s
DirectStorage on Windows, with GPU decompression from version 1.1 in 2022,
brings a similar path to PC.
- Useful observation commands: Process Monitor to watch every file the game
opens in order;
strace -f or ltrace on Linux; Windows Performance
Recorder or xperf for a boot-to-first-frame trace; nvidia-smi or
GPU-Z to watch video memory fill during load; and the engine’s own load-time
trace, such as Unreal Insights with the LoadTime channel.
WORDS45.13.6 remember these#
- Launcher — the small program that runs first — an updater, integrity
checker and authentication front end that spawns the real executable.
- Swap chain — the queue of pictures — the set of back buffers created at
startup and rotated between renderer and display.
- Pipeline state object — a frozen graphics configuration — an immutable
bundle of shaders and fixed-function state compiled ahead of a draw.
- Shader cache — the compiled results kept for next time — an on-disk store of
driver-compiled pipeline blobs keyed by hardware and driver version.
- Serialization — turning live objects into bytes — writing state in a
versioned, replayable form, and reading it back.
- Atomic rename — the safe way to save — writing to a temporary file and
renaming over the target so no partial file is ever visible.
45.14 Consoles versus PC#
PLAIN45.14.1 in simple words#
- A PC is a different machine for every person. A console is the same machine
for everybody.
- That single difference is worth more than it sounds.
- On a console the developer knows exactly how fast the processor is, exactly
how much memory there is, exactly how fast the storage is, and exactly
which graphics chip will run the shaders.
- So the developer can tune to that machine, compile shaders in advance, use
the memory to the last megabyte, and rely on a fixed loading speed.
- On a PC the same code must work on thousands of combinations, through a
driver that has to guess, with unknown amounts of memory, and with shaders
compiled on your machine while you wait.
- In exchange for that constraint, the console maker takes control: your game
must pass their tests before it can be sold.
- That is why a console game with weaker numbers on paper can look better
than a PC game on stronger hardware.
PLAIN45.14.2 a picture in your head#
- Think of a tailor.
- A bespoke suit is measured for one body. It fits perfectly and it fits
nobody else. That is a console game.
- Off-the-peg suits come in twelve sizes and must fit everybody roughly. They
need more fabric in places, and they hang a little loose. That is a PC
game.
- The bespoke suit is not made of better cloth. It just wastes none.
Where this comparison breaks: a PC owner can buy far better cloth. A 1,500
dollar PC in 2026 genuinely outperforms any console, and gets modding,
backwards compatibility and higher frame rates too. The console advantage is
efficiency per unit of hardware, not raw capability.
PLAIN45.14.3 a worked example#
- The 2026 landscape, with United States prices as of August 2026. Note that
prices in this generation went up rather than down, which is historically
unusual.
| Machine |
Graphics |
Price |
| PlayStation 5 (2020) |
36 CU, 10.3 TFLOPS |
649.99 |
| PlayStation 5 Pro (2024) |
60 CU, 16.7 TFLOPS |
899.99 |
| Xbox Series X (2020) |
52 CU, 12.1 TFLOPS |
649.99 |
| Xbox Series S (2020) |
20 CU, 4 TFLOPS |
399.99 |
| Nintendo Switch 2 (2025) |
1,536 Ampere cores |
449.99 |
- PlayStation raised prices in August 2025 and again on 2 April 2026. Xbox
raised prices in October 2025. The Nintendo Switch 2 launched at 449.99 on
5 June 2025 and has held that price.
- Memory tells the same story as compute. The PlayStation 5 has 16 gigabytes
of GDDR6 at 448 gigabytes per second, shared between processor and graphics
chip. The Pro keeps 16 gigabytes but raises bandwidth to 576 gigabytes per
second and adds 2 gigabytes of DDR5 for the system. The Switch 2 has 12
gigabytes of LPDDR5X at about 102 gigabytes per second docked.
- Unified memory is the quiet advantage. On a PC, data must be copied across
the PCI Express bus from system memory to video memory. On a console there
is one pool and no copy.
PLAIN45.14.4 what is really happening inside#
- Certification is a checklist, not a review of whether the game is good.
- Sony calls its list the Technical Requirements Checklist. Microsoft calls
its list the Xbox Requirements. Nintendo’s process is called Lotcheck.
- The checks are behavioural. What happens if the controller battery dies
mid-save. What happens if the network drops during a purchase. What happens
if the user signs out. Does the game suspend and resume within the required
time. Does it use the platform’s exact button names. Does it declare its
save data size correctly. Does it survive an eight-hour soak test.
- A submission takes on the order of one to three weeks per platform per
build, and a failure means fixing and resubmitting. Studios therefore lock
content weeks before launch to leave room for one or two failures.
- Those durations are studio experience rather than published figures, and
they vary by platform, by title and by relationship.
- Age ratings are a separate process again: ESRB in North America, PEGI in
Europe, CERO in Japan, USK in Germany, and the IARC questionnaire for
digital storefronts.
TECHNICAL45.14.5 the engineer’s version#
- The concrete reasons a fixed target wins, in order of importance:
precompiled shaders, so no run-time compilation and no first-run stutter;
unified memory, so no bus copies; low-overhead graphics APIs closer to the
hardware than the PC equivalents; a known memory budget minus a known
system reservation; guaranteed storage bandwidth with hardware
decompression; and a single optimization target, so every hour of tuning
benefits every player.
- The APIs differ: PlayStation uses its own GNM and GNMX; Xbox uses Direct3D
12 with console-specific extensions and a fixed driver; Nintendo Switch and
Switch 2 use NVN. All three expose more control and less driver
interpretation than desktop Direct3D 12 or Vulkan.
- System reservations are real and published in developer documentation
rather than in marketing: the Xbox Series X reserves about 2.5 gigabytes of
its 16, and the Switch 2 reserves about 3 gigabytes of its 12 by reported
figures, leaving the rest to the game.
- Handhelds are the growth area. The Steam Deck, released 25 February 2022
with an OLED model in November 2023, uses an AMD APU with a 4-core Zen 2
processor and 8 RDNA 2 compute units, about 1.6 teraflops, 16 gigabytes of
LPDDR5, and a 1280 by 800 display, in a 4 to 15 watt power envelope.
- SteamOS is Arch-based Linux, and Windows games do not run on Linux
natively. Proton makes them run. It is not emulation: the processor
instructions are native x86-64 and execute at full speed. Only the calls
into Windows are translated.
- Proton is Wine, the open reimplementation of the Windows API begun in 1993,
plus DXVK which translates Direct3D 9, 10 and 11 into Vulkan, plus
VKD3D-Proton which translates Direct3D 12 into Vulkan, plus FAudio for
XAudio2, plus Steam-specific shims. Shader bytecode is translated too, from
DXBC and DXIL into SPIR-V.
- Typical overhead is 0 to 15 percent, and a minority of titles run faster
than on Windows because of driver differences. The thing Proton cannot fix
is kernel anti-cheat, which must be explicitly enabled for Linux by the
game’s developer.
- Valve announced a Steam Machine in November 2025 for release in 2026: a
small SteamOS box with a semi-custom 6-core AMD Zen 4 processor up to
4.8 GHz, an RDNA 3 graphics part, 16 gigabytes of system memory plus 8
gigabytes of dedicated graphics memory, running the same Proton stack. At
the time of writing in August 2026 the price had not been announced.
- The honest summary: consoles buy predictability and efficiency; PCs buy
ceiling and freedom. Which is better depends entirely on whether you value
a guaranteed experience or a configurable one, and reasonable people split
on it.
WORDS45.14.6 remember these#
- Fixed platform — one machine for everyone — a single known hardware
configuration allowing exact tuning and ahead-of-time compilation.
- Certification — the platform holder’s checklist — a technical requirements
pass covering behaviour, terminology, storage and stability.
- Unified memory — one pool shared by processor and graphics — no PCI Express
copies between system and video memory.
- System reservation — the slice the console keeps — memory and processor
time reserved for the operating system and background features.
- Compatibility layer — translating one platform’s calls to another — Proton,
which maps Windows and Direct3D calls to Linux and Vulkan without
emulating the processor.
- Lotcheck — Nintendo’s certification — the platform’s technical and content
compliance review before release.
45.15 Emulation#
PLAIN45.15.1 in simple words#
- An emulator is a program that pretends to be a different computer.
- The game it runs was compiled for a processor your machine does not have,
talking to chips your machine does not have.
- So the emulator reads the old machine’s instructions one at a time and does
whatever they were supposed to do, using your machine’s instructions.
- It also pretends to be the old machine’s graphics chip, sound chip,
cartridge slot and controller ports.
- There are two ways to run the instructions. Interpretation reads and
acts on each instruction every time it is encountered. Simple, accurate,
slow.
- Recompilation translates a whole block of old instructions into new
instructions once, keeps the translation, and reuses it. Complicated, much
faster.
- There is a third shortcut. Instead of emulating the old machine’s system
software, the emulator can spot a call to a known system function and do
the equivalent thing natively. That is high-level emulation.
PLAIN45.15.2 a picture in your head#
- Interpretation is a live interpreter at a conference, translating sentence
by sentence, every time, including sentences the speaker repeats.
- Recompilation is having the speech translated once and printed, so the
repeated parts are read from the page.
- High-level emulation is noticing that the speaker just said a standard
phrase, and saying the equivalent standard phrase in the target language
rather than translating it word by word.
- Accuracy is the trade in each case. The live interpreter catches every
nuance. The printed version cannot adapt if the speaker goes off script.
Where this comparison breaks: a speech does not care about timing to the
microsecond. Old consoles absolutely did, and many games depend on exactly
when a chip responded, not just on what it returned.
PLAIN45.15.3 a worked example#
- Why emulating a slow machine can need a fast one.
- The Super Nintendo ran at about 3.58 MHz. A modern processor runs at about
4 GHz, roughly 1,100 times faster in clock terms alone, and does far more
per clock.
- Yet a fully cycle-accurate SNES emulator such as byuu’s bsnes and higan
needed roughly a 3 GHz machine to reach full speed.
- The reason is not the instructions. It is the synchronization. A cycle
accurate emulator must interleave the processor, the picture processing
unit, the sound processor and the cartridge coprocessors many times per
emulated instruction, and each switch costs far more than the instruction
itself.
- A less accurate emulator that runs each chip in blocks and synchronizes
rarely is ten to fifty times faster and breaks a small number of games that
rely on exact timing.
| Approach |
Speed cost |
Accuracy |
| Cycle-accurate interpreter |
500 to 1500x |
Highest |
| Block interpreter |
20 to 100x |
Good |
| Dynamic recompiler |
2 to 10x |
Varies |
| High-level API emulation |
1 to 3x |
Lowest |
- Those ratios are approximate and depend heavily on the console being
emulated.
PLAIN45.15.4 what is really happening inside#
- An interpreter’s inner loop is: read the instruction at the program
counter, decode it, look up a handler, run the handler, update the
registers and flags, advance the program counter, add the instruction’s
cycle cost to a counter, and check whether any hardware event is due.
- That is 10 to 100 host instructions to do the work of one guest
instruction.
- A dynamic recompiler instead scans forward from the program counter until a
branch, translates that whole block into host machine code once, stores it
in a cache keyed by address, and jumps into it.
- The block then runs at close to native speed on every later visit.
- Self-modifying code and code overwritten by a memory bank switch force the
cached block to be thrown away and retranslated, which is why emulating
older machines with heavy bank switching is harder than it looks.
- Emulating the graphics chip is where the biggest shortcut lives. If the
emulator translates the old chip’s drawing commands into modern graphics
calls instead of simulating its pixel pipeline, it can also render at four
or eight times the original resolution, which the original hardware could
never do.
TECHNICAL45.15.5 the engineer’s version#
- Terms, precisely. Interpretation decodes per execution.
Threaded interpretation removes dispatch overhead by chaining handler
addresses. Dynamic binary translation, also called dynarec or JIT,
compiles per basic block or per trace. Static recompilation translates
the whole binary ahead of time and mostly fails on general programs because
indirect jumps make it impossible to tell code from data reliably, though
per-title static recompilation projects have succeeded, notably for
Nintendo 64 titles from around 2023.
- High-level emulation replaces the guest system’s own libraries with
native implementations, which is essential when the firmware cannot legally
be distributed. Low-level emulation runs the real firmware and is more
accurate but requires the user to supply it.
- Accuracy has axes: instruction accuracy, cycle accuracy, sub-instruction
bus timing, sample-accurate audio, and scanline or dot accurate video.
Choosing a lower point on any axis buys speed and breaks some titles.
- The legal position, stated neutrally and without advice.
- Writing an emulator has been upheld in United States courts. In Sony
Computer Entertainment v. Connectix, decided by the Ninth Circuit in 2000,
intermediate copying of the PlayStation BIOS for reverse engineering was
held to be fair use. Sony v. Bleem, also 2000, held that using screenshots
in comparative advertising was fair use.
- Copying game data you do not own is copyright infringement essentially
everywhere. Whether dumping a cartridge you do own is lawful varies by
country, and in several jurisdictions the act of circumventing copy
protection to make the dump is itself unlawful regardless of ownership,
under the United States Digital Millennium Copyright Act of 1998 and the
European Union Copyright Directive of 2001.
- Firmware and BIOS images are copyrighted works in their own right;
distributing them is infringement whatever the emulator’s status.
- Enforcement in practice: in March 2024 Nintendo settled with Tropic Haze,
developer of the Switch emulator Yuzu, for 2.4 million United States
dollars, and the project shut down. Nintendo’s complaint centred on
circumvention of encryption rather than on emulation as a concept.
- Where people disagree: emulator authors and archivists argue the tool is
lawful, general-purpose and necessary; rights holders argue that emulators
of current hardware exist principally to enable piracy. Both claims can be
true of different projects at the same time.
- Preservation is the strongest argument, and it has numbers behind it. A
study published in July 2023 by the Video Game History Foundation with the
Software Preservation Network found that about 87 percent of video games
released in the United States before 2010 are out of commercial
circulation entirely.
- The mechanisms of loss are concrete: digital storefronts close, as the Wii
Shop Channel did in 2019 and the Nintendo 3DS and Wii U eShops did in
March 2023; optical discs suffer disc rot; cartridge save batteries last
ten to twenty years; and flash memory loses charge over decades.
- Museums and libraries have argued for broader legal exemptions to preserve
and provide access to games. Some exemptions exist for on-site
preservation work; remote access for researchers remains contested.
WORDS45.15.6 remember these#
- Emulator — a program pretending to be another machine — software modelling
a foreign instruction set and peripheral hardware.
- Interpretation — decode every instruction every time — a fetch-decode-
execute loop in software, simple and slow.
- Dynamic recompilation — translate once, run many times — just-in-time
compilation of guest basic blocks into host machine code.
- High-level emulation — reimplement the system calls — replacing guest
firmware routines with native host implementations.
- Cycle accuracy — matching the original timing exactly — modelling
per-clock behaviour including inter-chip contention.
- ROM — a copy of the original game data — a dump of cartridge or disc
contents, copyrighted material unless the rights holder permits otherwise.
45.16 Making your first game, practically#
PLAIN45.16.1 in simple words#
- Build something tiny. Then build something slightly less tiny.
- The reason is not that you cannot handle a big idea. It is that finishing is
a separate skill from building, and it is the rarer one.
- A tiny game teaches you the whole pipeline: input, a loop, collision, a win
condition, a lose condition, sound, a menu, a build, and publishing.
- A big game teaches you one slice of that and then dies.
- The proven ladder is: Pong, then Breakout, then Snake, then Asteroids, then
a one-level platformer, then something of your own.
- Each of those should take days, not months. If it is taking months, the
scope is wrong.
- Then publish it. Publishing a bad small game teaches you more than not
publishing a good big one.
PLAIN45.16.2 a picture in your head#
- Nobody learns to cook by attempting a five-course dinner for twenty.
- You learn by making one dish, badly, then again, less badly.
- The dinner party teaches you timing, which the single dish does not, so you
do eventually need one. But you need it after ten dishes, not before.
- A game jam is the dinner party: a fixed 48 hours, a theme announced at the
start, and something submitted at the end regardless of quality.
Where this comparison breaks: a bad dish is eaten and forgotten. A published
game stays on the internet under your name, which is exactly why some people
never publish. Publish anyway. Nobody is looking as hard as you fear.
PLAIN45.16.3 a worked example#
- A thirty-day plan. It assumes about two hours a day, which is realistic
alongside study or a job.
| Days |
Task |
Deliverable |
| 1 to 2 |
Engine, one tutorial |
A window, a moving box |
| 3 to 4 |
Core verb only |
Move and jump feel good |
| 5 to 7 |
One obstacle, win, lose |
A 30-second playable loop |
| 8 to 9 |
Playtest with 3 people |
Written notes, a cut list |
| 10 to 13 |
Fix the top three problems |
The loop reads clearly |
| 14 to 16 |
Add exactly one system |
The game has some depth |
| 17 to 18 |
Second playtest |
Notes, cut list again |
| 19 to 21 |
Sound and feedback pass |
It feels good to touch |
| 22 to 24 |
Five levels or a curve |
Content, not features |
| 25 to 26 |
Menu, pause, settings |
Ship-shaped |
| 27 to 28 |
Build, test on a clean PC |
An installable build |
| 29 |
Store page, screenshots |
Page ready |
| 30 |
Publish on itch.io |
Released |
- Notice that only days 3 to 7 and 14 to 16 add features. Everything else is
testing, fixing, content and shipping. That ratio is correct and it
surprises everyone the first time.
PLAIN45.16.4 what is really happening inside#
- Scope is the number one killer of hobby projects, and the reason is
arithmetic, not willpower.
- Every feature costs its own build time plus its interaction with every
other feature. The number of interacting pairs grows roughly as the square
of the feature count.
- Five features have ten pairs to make work together. Fifteen features have
105. That is why the second half of a project feels ten times harder than
the first.
- So the discipline is a cut list: when you have a new idea, write it down
on a “version two” list, and carry on with what you were doing.
- Rough multipliers for common additions, approximate but directionally
right: multiplayer multiplies total work by about three; a save and load
system by about 1.3; procedural generation by about two; a narrative mode by
more than any of them.
- The classic failure is choosing a massive online role-playing game or an
open world as a first project. It has ended more hobby projects than any
technical difficulty.
- Prototype with untextured boxes. If a game is not fun as grey boxes, art
will not save it. Art makes a good game feel better; it cannot make a
boring game interesting.
- Playtest by handing someone the controls and saying nothing. Every time you
want to explain something, that is a design bug. Write it down instead of
speaking.
TECHNICAL45.16.5 the engineer’s version#
- Choosing a tool by goal, as of August 2026:
| Goal |
Tool |
Why |
| Understand the machinery |
raylib or SDL3 |
No magic, all yours |
| Ship a 2D game quickly |
Godot 4 |
Free, small, 2D-first |
| Reach mobile and consoles |
Unity 6 |
Widest platform support |
| Highest-end 3D visuals |
Unreal Engine 5 |
Best default look |
| Web game in a browser |
Godot or a JS engine |
HTML5 export |
- Code-first libraries worth knowing: SDL3 and raylib in C, LOVE in Lua,
pygame in Python, MonoGame in C#, Bevy in Rust, and three.js in JavaScript.
These give you a window, input, drawing and sound, and nothing else, which
is exactly the point when learning.
- Free asset sources with usable licences: Kenney’s public domain 2D and 3D
packs; OpenGameArt; Poly Haven and AmbientCG for CC0 textures, models and
environment maps; Quaternius for CC0 low-poly models; Adobe’s Mixamo for
free rigged characters and animations; Freesound for Creative Commons
audio; and Google Fonts. Read every licence and keep an attributions file
from day one, because reconstructing it later is miserable.
- “Juice” is the disproportionately effective polish layer: screen shake, a
two to six frame hit pause, particles on impact, layered sound, tweened
interface movement, and squash and stretch on jumps. The reference talk is
“Juice It Or Lose It” by Martin Jonasson and Petri Purho from 2012.
- Where to publish, with real numbers:
| Platform |
Cost to publish |
Revenue share |
| itch.io |
Free |
You choose, 10% default |
| Steam |
100 USD per game |
30%, 25% over 10M |
| Epic Games Store |
Free, curated |
12% |
| Google Play |
25 USD once |
15% under 1M per year |
| Apple App Store |
99 USD per year |
15% under 1M per year |
- The Steam Direct fee of 100 United States dollars per title is refundable
once the title reaches 1,000 dollars of adjusted gross revenue. Steam’s
share drops to 25 percent above 10 million dollars of lifetime revenue and
20 percent above 50 million.
- Game jams are the most reliable way to finish anything. Ludum Dare has run
since 2002, Global Game Jam since 2009, and the GMTK Jam is now among the
largest. A 48-hour deadline enforces scope better than any amount of
personal discipline.
- A practical technical checklist before publishing: test on a machine that
has never had your development tools installed; check that the game runs
from a path with a space and a non-English character in it; handle
alt-tab, minimize and display resolution change; provide key rebinding;
check it on a 16:10 and an ultrawide display; and make sure the game can be
quit with the keyboard alone.
WORDS45.16.6 remember these#
- Scope — how big the thing is — the total feature and content set, and the
dominant risk in any small project.
- Cut list — the ideas you deliberately postpone — a written backlog that
protects the current milestone from new ideas.
- Prototype — the ugly playable test — a minimal implementation built to
answer one design question, then usually discarded.
- Playtest — watching someone else play — structured observation of a naive
player without designer intervention.
- Juice — cheap polish that feels expensive — screen shake, hit pause,
particles and easing applied to feedback moments.
- Game jam — a short deadline with a theme — a fixed-duration event, typically
48 to 72 hours, used to force completion.
45.98 Common wrong ideas#
- Wrong: games are made by one genius programmer. Right: a modern game is
made by a team where roughly one person in five writes code, and the
largest groups are artists and quality assurance. Even the famous solo
games, such as Stardew Valley, took a single person four and a half years
and still used other people’s engine, tools and audio libraries.
- Wrong: more polygons means better graphics. Right: past a certain density
extra triangles are smaller than a pixel and cost performance for no
visible gain. What actually makes an image look good is lighting, material
response, texture quality, animation and art direction. A 2015 game with
good art direction routinely looks better than a 2026 game without it.
- Wrong: the engine makes the game. Right: the engine provides the machinery.
Every game in the same engine can look and feel completely different,
because the design, the art, the tuning and the content are the game. An
engine can make a bad game easier to build; it cannot make it good.
- Wrong: lag is always your internet connection. Right: what you feel as lag
is the sum of your input device, your frame rate, your render queue depth,
your display, your distance to the server, the server’s tick rate, and the
game’s interpolation delay. A player with a perfect connection on a
distant, low-tick server will feel worse than a player with a mediocre
connection nearby.
- Wrong: a higher average frame rate always feels smoother. Right: evenly
paced frames feel smoother than unevenly paced ones at the same average.
112 frames per second average with one 100-millisecond hitch feels worse
than a steady 90.
- Wrong: game physics is real physics. Right: it is a stable, cheap
approximation tuned for feel. Jump arcs, friction and gravity in most games
are deliberately unphysical because physical values feel bad to play.
- Wrong: game AI is machine learning. Right: shipped game AI is almost
entirely hand-authored state machines, behaviour trees, utility scoring and
pathfinding, deliberately weakened so it is fun to fight. Learned agents
exist in research and beat humans, and are not what is in your game.
- Wrong: emulators are illegal. Right: writing and using an emulator has been
upheld as lawful in United States courts. Copying game data or firmware you
do not own is what is unlawful, and the two questions are separate.
- Wrong: kernel anti-cheat means the game is secure. Right: it raises the
cost of software cheating, and it cannot see a direct-memory-access cheat
on a second computer or a screen-reading cheat driving a hardware mouse.
Server-side validation and not sending hidden data remain the only
defences that cannot be bypassed on the client.
- Wrong: consoles are just locked-down PCs. Right: the fixed target changes
what is possible. Precompiled shaders, unified memory, a known memory
budget and one optimization target let a console extract far more from the
same silicon than a PC of identical specification.
45.99 Chapter summary in 20 lines#
- A game is a program that redraws the world on a clock, whether or not
anything changed, unlike an application that redraws only on an event.
- That single decision produces the frame budget: 16.67 ms at 60 frames per
second, 8.33 ms at 120, 6.94 ms at 144.
- The loop is input, update, render, present, and it never sleeps except when
waiting for the display.
- Physics needs a fixed timestep because integration is not step-size
invariant; an accumulator collects real time and spends it in fixed steps.
- Rendering interpolates between the last two simulation states using the
leftover accumulator fraction, which is what makes 60 Hz physics look
smooth at 144 frames per second.
- Frame time is the real measurement; average frames per second hides
stutter, which is why 1 percent lows are reported.
- Games began as laboratory curiosities in 1958 and 1962, became wired logic
in 1972, gained processors and cartridges in 1977, crashed in 1983, and
were rebuilt around platform control from 1985.
- Doom in 1993 and 3D acceleration from 1996 moved the bottleneck from pixel
fill to triangle throughput, and then to per-pixel computation.
- A modern AAA game costs 80 to 300 million dollars and employs 200 to 600
people, of whom fewer than a quarter write code; content, not code, is the
cost.
- Engines supply the reusable machinery and an editor. Unity, Unreal and
Godot differ chiefly in language, licence and default strengths, and a
licence is part of your technology stack, as 2023 demonstrated.
- Entity-component-system layouts win on speed because contiguous component
arrays match how caches and prefetchers work.
- The asset pipeline converts editor formats into platform-specific runtime
formats, a process Unreal calls cooking; shader permutations and lightmap
baking are why builds take hours.
- Physics is broad phase, narrow phase, and impulse-based resolution;
momentum is conserved and restitution controls how much energy is lost.
- Floating-point results are not reproducible across machines in general,
which is why deterministic lockstep networking is hard.
- Game AI is state machines, behaviour trees, utility scoring, planners and
A-star pathfinding, deliberately weakened so that fighting it is fun.
- A rendered frame is culling, batching, sorting, shadow passes, a forward
or deferred lighting pass, transparency, post-processing, then interface.
- Latency cannot be removed, only hidden: client-side prediction, server
reconciliation, entity interpolation and lag compensation together explain
why you get shot after reaching cover.
- The client can never be trusted; server-side validation and not sending
invisible data are the only defences that cannot be patched out.
- Launch is loader, launcher, anti-cheat, device and swap chain creation,
shader compilation, streaming and finally the loop, which is why the first
run stutters and consoles do not.
- Start tiny, cut ruthlessly, playtest silently, and publish. Scope, not
skill, is what ends most projects.