Skip to content

Commit 60a4f3e

Browse files
committed
Apply proofreading changes to web. Also:
- Ackknowledgements - Add chapter navigation to top of pages - Some other minor style tweaks
1 parent ce07b04 commit 60a4f3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+659
-333
lines changed

asset/style.scss

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ nav {
4444
}
4545
}
4646

47+
nav.top {
48+
margin-top: 0;
49+
}
50+
4751
.page {
4852
background: hsl(40, 30%, 98%);
4953
max-width: 640px;
@@ -248,6 +252,10 @@ aside {
248252
}
249253
}
250254

255+
aside + aside {
256+
margin-top: 10px;
257+
}
258+
251259
// The front page gets a bit of special styling.
252260
.index {
253261
h1 {
@@ -538,7 +546,7 @@ footer {
538546

539547
nav {
540548
margin: 20px -18px 0 -18px;
541-
padding: 10px 18px;
549+
padding: 6px 18px;
542550
font-size: 13px;
543551
}
544552

asset/template.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@
2525
<body id="top">
2626
<div class="page sidebar">
2727
<div class="content">
28+
<nav class="top">
29+
{{prev}}
30+
{{next}}
31+
<span class="toc">&equiv; <a href="/">The Book</a></span>
32+
</nav>
2833
<h1>{{header}}</h1>
2934
<h1 class="book"><a href="/">Game Programming Patterns</a>{{section_header}}</h1>
3035
{{body}}
3136
<nav>
3237
{{prev}}
3338
{{next}}
34-
<span class="toc">&equiv; <a href="/">Table of Contents</a></span>
39+
<span class="toc">&equiv; <a href="/">The Book</a></span>
3540
</nav>
3641
</div>
3742
</div>

book/acknowledgements.markdown

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
^title Acknowledge&shy;ments
2+
3+
I've heard only other authors know what's involved in writing a book, but there
4+
is another tribe who know the precise weight of that burden -- those with the
5+
misfortune of being in a relationship with a writer. I wrote this in a space of
6+
time painstakingly carved from the dense rock of life for me by my wife Megan.
7+
Washing dishes and giving the kids baths may not be "writing", but without her
8+
doing those, this book wouldn't be here.
9+
10+
I started this project while a programmer at Electronic Arts. I don't think the
11+
company knew quite what to make of it, and I'm grateful to Michael Malone,
12+
Olivier Nallet, and Richard Wifall for supporting it and providing detailed,
13+
insightful feedback on the first few chapters.
14+
15+
<span name="editor">About</span> halfway through writing, I decided to forgo a traditional publisher. I
16+
knew that meant losing the guidance an editor brings, but I had email from
17+
dozens of readers telling me where they wanted the book to go. I'd lose
18+
proofreaders, but I had over <span name="colm">250 bug reports</span> to help improve the prose. I'd give
19+
up the incentive of a writing schedule, but with readers patting my back when I
20+
finished each chapter, I had more than enough motivation.
21+
22+
<aside name="editor">
23+
24+
What I didn't lose was a copy editor. Lauren Briese showed up just when I
25+
needed her and did a wonderful job.
26+
27+
</aside>
28+
29+
They call this "self publishing", but "crowd publishing" is closer to the mark.
30+
Writing can be lonely work, but I was never alone. Even when I put the book on a
31+
shelf for two years, the encouragement continued. Without the dozens of people
32+
who didn't let me forget that they were waiting for more chapters, I never would
33+
have picked it back up and finished.
34+
35+
<aside name="colm">
36+
37+
Special thanks go to Colm Sloan who pored over every single chapter in the book
38+
*twice* and gave me mountains of fantastic feedback, all out of the goodness of
39+
his own heart. I owe you a beer or twenty.
40+
41+
</aside>
42+
43+
To everyone who emailed or commented, upvoted or favorited, tweeted or
44+
retweeted, anyone who reached out to me, or told a friend about the book, or
45+
sent me a bug report: my heart is filled with gratitude for you. Completing this
46+
book was one of my biggest goals in life, and you made it happen.
47+
48+
Thank you!

book/architecture-performance-and-games.markdown

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ It's weird to think that this is literally an OCR process.
8383
</aside>
8484

8585
We tend to gloss over this step, but it's often the most time-consuming part of
86-
programming. If you think paging some data from RAM into disk is slow, try
86+
programming. If you think paging some data from disk into RAM is slow, try
8787
paging it into a simian cerebrum over a pair of optical nerves.
8888

8989
Once you've got all the right context into your wetware, you think for a bit and
@@ -103,7 +103,7 @@ code, but a large fraction of the codebase is perfectly testable.
103103

104104
I won't get on a soapbox here, but I'll ask you to consider doing more automated
105105
testing if you aren't already. Don't you have better things to do than manually
106-
test stuff over and over again?
106+
validate stuff over and over again?
107107

108108
</aside>
109109

@@ -137,9 +137,9 @@ Patterns* is about the same idea.
137137

138138
You can define "decoupling" a bunch of ways, but I think if two pieces of code
139139
are coupled, it means you can't understand one without understanding the other.
140-
If you *de*couple them, you can reason about either side independently. That's
140+
If you *de*-couple them, you can reason about either side independently. That's
141141
great because if only one of those pieces is relevant to your problem, you just
142-
need to load it into your monkey brain and not the other half too.
142+
need to load *it* into your monkey brain and not the other half too.
143143

144144
To me, this is a key goal of software architecture: **minimize the amount of
145145
knowledge you need to have in-cranium before you can make progress.**
@@ -216,7 +216,7 @@ It takes you forever to trace through all of that scaffolding to find some real
216216
code that does something. When you need to make a change, sure, there's probably
217217
an interface there to help, but good luck finding it. In theory, all of this
218218
decoupling means you have less code to understand before you can extend it, but
219-
the layers of abstraction themselves end up filling up your mental scratch disk.
219+
the layers of abstraction themselves end up filling your mental scratch disk.
220220

221221
Codebases like this are what turn people *against* software architecture, and
222222
design patterns in particular. It's easy to get so wrapped up in the code itself

book/bytecode.markdown

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ language's grammar. The simplest one is numbers:
125125

126126
A literal number expression simply evaluates to its value. Addition and
127127
multiplication are a bit more complex because they contain subexpressions.
128-
Before they can evaluate themselves, they need to recursively evaluate the
128+
Before they can evaluate themselves, they need to recursively evaluate their
129129
subexpressions. Like so:
130130

131131
<span name="addition"></span>
@@ -150,7 +150,7 @@ you!
150150

151151
</aside>
152152

153-
It's a <span name="ruby">beautiful</span>, simple pattern, but is has some
153+
It's a <span name="ruby">beautiful</span>, simple pattern, but it has some
154154
problems. Look up at the illustration. What do you see? Lots of little boxes,
155155
and lots of arrows between them. Code is represented as a sprawling fractal tree
156156
of tiny objects. That has some unpleasant consequences:
@@ -248,7 +248,7 @@ implemented using it.
248248
## The Pattern
249249

250250
An **instruction set** defines the low-level operations that can be performed.
251-
These are encoded as a **sequence of bytes**. A **virtual machine** executes
251+
A series of instructions is encoded as a **sequence of bytes**. A **virtual machine** executes
252252
these instructions one at a time, using a **stack for intermediate values**. By
253253
combining instructions, complex high-level behavior can be defined.
254254

@@ -335,9 +335,7 @@ we'll see later, it may not be as bad as you think.
335335
Programming is hard. We know what we want the machine to do, but we don't always
336336
communicate that correctly -- we write bugs. To help find and fix those, we've
337337
amassed a pile of tools to understand what our code is doing wrong, and how to
338-
right it.
339-
340-
We have debuggers, static analyzers, decompilers, etc. All of those tools are
338+
right it. We have debuggers, static analyzers, decompilers, etc. All of those tools are
341339
designed to work with some existing language: either machine code or something
342340
higher level.
343341

@@ -408,7 +406,7 @@ operation you want to perform. We can enumerate them:
408406

409407
To encode a spell in data, we store an array of `enum` values. We've only got
410408
a few different primitives, so the range of `enum` values easily fits into a byte.
411-
This means a spell is just a list of <span name="byte">bytes</span> -- ergo
409+
This means the code for a spell is just a list of <span name="byte">bytes</span> -- ergo
412410
"bytecode".
413411

414412
<img src="images/bytecode-code.png" alt="A sequence of bytecode instructions: 0x00 HEALTH, 0x03 SOUND, 0x004 PARTICLES, ..." />
@@ -852,7 +850,7 @@ laundry list of the different kinds of instructions you may want:
852850

853851
### How are values represented?
854852

855-
Our sample VM only works with one kind of value, integers. That makes it easy --
853+
Our sample VM only works with one kind of value, integers. That makes answering this easy --
856854
the stack is just a stack of `int`s. A more full-featured VM will support
857855
different data types: strings, objects, lists, etc. You'll have to decide how
858856
those are stored internally.
@@ -1000,7 +998,7 @@ only option.
1000998
ways.
1001999

10021000
Most non-programmers don't think of plaintext like that. To them, text
1003-
files feel like filling in tax forms for a robotic auditor that yells at
1001+
files feel like filling in tax forms for an angry robotic auditor that yells at
10041002
them if they forget a single semicolon.
10051003

10061004
* **If you define a graphical authoring tool:**
@@ -1031,7 +1029,7 @@ only option.
10311029

10321030
<aside name="lines">
10331031

1034-
Except for line endings. *Sigh...*
1032+
Except for line endings. And encodings.
10351033

10361034
</aside>
10371035

book/command.markdown

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Four has a predictably abstruse description:
1313
I think we can all agree that that's a terrible sentence. First of all, it
1414
mangles whatever metaphor it's trying to establish. Outside of the weird world
1515
of software where words can mean anything, a "client" is a *person* -- someone
16-
you do business with. Last I checked, people can't be "parameterized".
16+
you do business with. Last I checked, human beings can't be "parameterized".
1717

1818
Then, the rest of that sentence is just a list of stuff you could maybe possibly
1919
use the pattern for. Not very illuminating unless your use case happens to be in
@@ -233,7 +233,7 @@ making a networked multi-player game.
233233

234234
## Undo and Redo
235235

236-
The last example is the most well-known use of this pattern. If a command object
236+
The final example is the most well-known use of this pattern. If a command object
237237
can *do* things, it's a small step for it to be able to *undo* them. Undo is
238238
used in some strategy games where you can roll back moves that you didn't like.
239239
It's *de rigueur* in tools that people use to *create* games. The <span
@@ -338,7 +338,7 @@ pointer
338338
and then execute that command. If they choose a new command after undoing some,
339339
everything in the list after the current command is discarded.
340340

341-
The first time I implemented this in a level editor, I felt like a wizard. I was
341+
The first time I implemented this in a level editor, I felt like a genius. I was
342342
astonished at how straightforward it was and how well it worked. It takes
343343
discipline to make sure every data modification goes through a command, but once
344344
you do that, the rest is easy.

book/component.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ One of the biggest challenges for me in writing this book is figuring out how to
250250
isolate each pattern. Many design patterns exist to contain code that itself
251251
isn't part of the pattern. In order to distill the pattern down to its essence,
252252
I try to cut as much of that out as possible, but at some point it becomes a bit
253-
like explaining how an engine works without mentioning fuel or oil.
253+
like explaining how to organize a closet without showing any clothes.
254254

255255
The Component pattern is a particularly hard one. You can't get a real feel for
256256
it without seeing some code for each of the domains that it decouples, so I'll

book/data-locality.markdown

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,12 @@ this won't help.
262262

263263
The cheap way to profile is to manually add a bit of instrumentation that checks
264264
how much time has elapsed between two points in the code, hopefully using a
265-
precise timer. To catch cache misses, you'll want something a little more
265+
precise timer. To catch poor cache usage, you'll want something a little more
266266
sophisticated. You really want to see how many cache misses are occurring and
267267
where.
268268

269269
Fortunately, there are <span name="cachegrind">profilers</span> out there that
270-
report cache misses. It's worth spending the time to get one of these working and make
270+
report this. It's worth spending the time to get one of these working and make
271271
sure you understand the (surprisingly complex) numbers it throws at you before
272272
you do major surgery on your data structures.
273273

@@ -325,7 +325,7 @@ keep in mind that the general technique can be applied anywhere it fits.
325325

326326
### Contiguous arrays
327327

328-
Let's start with a <a href="game-loop.html" class="pattern">Game Loop</a> that
328+
Let's start with a <a href="game-loop.html" class="pattern">game loop</a> that
329329
processes a bunch of game entities. Those entities are decomposed into different
330330
domains -- AI, physics, and rendering -- using the <a href="component.html"
331331
class="pattern">Component</a> pattern. Here's the `GameEntity` class:
@@ -644,7 +644,8 @@ both pieces will be at the same index in their respective arrays.
644644
</aside>
645645

646646
You can see how this starts to get fuzzy, though. In my example here, it's
647-
pretty obvious which data should be hot and cold, but it's rarely so clear-cut.
647+
pretty obvious which data should be hot and cold, but in a real game it's
648+
rarely so clear-cut.
648649
What if you have fields that are used when an entity is in a certain mode but
649650
not in others? What if entities use a certain chunk of data only when they're in
650651
certain parts of the level?

book/dirty-flag.markdown

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,6 @@
77

88
## Motivation
99

10-
"Flag" and "bit" are synonymous in programming -- they both mean a single micron
11-
of data that can be in one of two states. We call those "true" and "false", or
12-
sometimes "set" and "cleared". I'll use all of these interchangeably. "Dirty
13-
bit" is an equally <span name="specific">common</span> name for this pattern,
14-
but I figured I'd stick with the name that didn't seem as prurient.
15-
16-
<aside name="specific">
17-
18-
Wikipedia's editors don't have my level of self-control and went with [dirty
19-
bit](http://en.wikipedia.org/wiki/Dirty_bit).
20-
21-
</aside>
22-
23-
### Locating a ship at sea
24-
2510
Many games have something called a *scene graph*. This is a big data structure
2611
that contains all of the objects in the world. The rendering engine uses this to
2712
determine where to draw stuff on the screen.
@@ -49,13 +34,13 @@ transform to it, and then renders it there in the world. If we had a scene
4934

5035
However, most scene graphs are <span name="hierarchical">*hierarchical*</span>.
5136
An object in the graph may have a parent object that it is anchored to. In that
52-
case, its transform is relative to the *parent's* position and isn't its
37+
case, its transform is relative to the *parent's* position and isn't an
5338
absolute position in the world.
5439

5540
For example, imagine our game world has a pirate ship at sea. Atop the ship's
5641
mast is a crow's nest. Hunched in that crow's nest is a pirate. Clutching the
57-
pirate's shoulder is a parrot. The ship's local transform will position it in
58-
the sea. The crow's nest's transform positions it on the ship, and so on.
42+
pirate's shoulder is a parrot. The ship's local transform positions the ship in
43+
the sea. The crow's nest's transform positions the nest on the ship, and so on.
5944

6045
<span name="pirate"></span>
6146
<img src="images/dirty-flag-pirate.png" alt="A pirate ship containing a crow's nest with a pirate in it with a parrot on his shoulder." />
@@ -146,7 +131,7 @@ world transform *four* times when we only need the result of the final one.
146131
We only moved four objects, but we did *ten* world transform calculations.
147132
That's six pointless calculations that get thrown out before they are ever used
148133
by the renderer. We calculated the parrot's world transform *four* times, but it
149-
only got rendered once.
134+
is only rendered once.
150135

151136
The problem is that a world transform may depend on several local transforms.
152137
Since we recalculate immediately each time *one* of the transforms changes, we end up
@@ -168,12 +153,26 @@ engineering a little slippage.
168153

169154
</aside>
170155

171-
To do this, we add a flag to each object in the graph. When the local transform
156+
To do this, we add a *flag* to each object in the graph. "Flag" and "bit" are
157+
synonymous in programming -- they both mean a single micron of data that can be
158+
in one of two states. We call those "true" and "false", or sometimes "set" and
159+
"cleared". I'll use all of these interchangeably.
160+
161+
When the local transform
172162
changes, we set it. When we need the object's world transform, we check the
173163
flag. If it's set, we calculate the world transform and then clear the flag. The
174164
flag represents, "Is the world transform out of date?" For reasons that aren't
175165
entirely clear, the traditional name for this "out-of-date-ness" is "dirty".
176-
Hence: *a dirty flag*.
166+
Hence: *a dirty flag*. "Dirty bit" is an equally
167+
<span name="specific">common</span> name for this pattern, but I figured I'd
168+
stick with the name that didn't seem as prurient.
169+
170+
<aside name="specific">
171+
172+
Wikipedia's editors don't have my level of self-control and went with [dirty
173+
bit](http://en.wikipedia.org/wiki/Dirty_bit).
174+
175+
</aside>
177176

178177
If we apply this pattern and then move all of the objects in our previous
179178
example, the game ends up doing:
@@ -238,7 +237,7 @@ There are a couple of other requirements too:
238237
that's often a better choice than using this pattern and calculating the
239238
derived data from scratch when needed.
240239

241-
All of this makes it sound like dirty flags are never appropriate, but you'll
240+
This makes it sound like dirty flags are rarely appropriate, but you'll
242241
find a place here or there where they help. <span name="hacks">Searching</span>
243242
your average game codebase for the word "dirty" will often turn up uses of this
244243
pattern.
@@ -481,7 +480,7 @@ up like this.
481480
This is similar to the original naïve implementation. The key changes are that
482481
we check to see if the node is dirty before calculating the world transform and
483482
we store the result in a field instead of a local variable. When the node is
484-
clean, we skip `combine()` completely and use the old but still correct `world_`
483+
clean, we skip `combine()` completely and use the old-but-still-correct `world_`
485484
value.
486485

487486
The <span name="clever">clever</span> bit is that `dirty` parameter. That will
@@ -552,7 +551,7 @@ This pattern is fairly specific, so there are only a couple of knobs to twiddle:
552551

553552
<aside name="hysteresis">
554553

555-
The term in human-computer interaction for in intentional delay between
554+
The term in human-computer interaction for an intentional delay between
556555
when a program receives user input and when it responds is [*hysteresis*](http://en.wikipedia.org/wiki/Hysteresis).
557556

558557
</aside>

0 commit comments

Comments
 (0)