tags:

views:

625

answers:

5

I put his name in the title, but his book is Tricks of the Windows Game Programming Gurus. I got the first chapter online, and in his very first code example, he uses void main() and several define macros, and his game loop consists of a long switch statement (not even pseudo use of objects).

Can I take this book seriously as a C++ programmer?

+2  A: 

Maybe the point of the book is not to teach C++ but game programming. Also, The book is somehow old. Honestly, I haven't read the book, but bad C++ code is all over the place, so recode it your way.

AraK
Actually, the book was pretty bad even when brand spanking new. It's firmly in the "Learn X in 24hrs" camp, and therefore one to be avoided.
Andy J Buchanan
+20  A: 

You must remember, most older games programmers use C++ as C with classes, not as C++.

You just have to learn to pick out the good things. Even though the code may be bad, the concepts in them are still valid. Even then, some engine designs have changed (OOP versus Component-based design). It's best to read many books to get a good perspective on them. Don't focus on the code itself, but how it works with other code to bring things together.

I would recommend writing the same game with several different design styles so you can see the advantages of each. (Something simpler, like Pong, where you can worry about design rather than code logic). Try to pick out modern books, too, but get a good mix, so you can see and appreciate the changes game architecture has gone through.

For a little tip in the right direction, check out Game Programming Gems 5: Component Based Object Management (pg 25). Also, try to do things differently in more ways than one. Rewrite the same game, but use Lua to script your objects, so you can see how design effects the implementation of other concepts, too.

It's a lot of coding, but after it all you'll definitely have a good grip on not only the way games work, but different styles too, along with their advantages & disadvantages. That gives you more to say than many game programmers.

That all said, we can't be too harsh on Andrè. Like another answer had (but now it's gone :( ...):

André LaMothe is a computer scientist, author and embedded systems developer. He was responsible for the development of hardware and software for artificial intelligence research and worked specifically on the sparse distributed memory project at NASA's Research Institute for Advanced Computer Science (RIACS).

He obviously knows his algorithms and designs well. I'd just say he was just like all the other C++ programmers at the time: new, and trying to come from C. That's why you get lots of "C with classes" approaches in the older books. Games needed to be fast, C++ compilers were pretty iffy back then, and so it was, "use what I know works, but use classes once in a while to help keep it nice."

Edit

So it turns out there is a second edition which still contains these bad things. So no, don't trust his C++, even today :)

GMan
I saw that response too, don't know why it was deleted. Fair enough. Thanks for the answer.
Hooked
Yup. I know what you mean, "wtf, `void main`, how can this guy be good?". Just gotta work around it :) Game's industry has always been a bit behind, since it's mostly been, "who cares how it works, make it work and make it fun". But now it's starting to shift to, "make this extend-able, clean and manageable, but still fast!"
GMan
Please explain your down vote. I can't improve my answer if I don't know what's wrong with it.
GMan
Who downvoted? Not I, sir.
Hooked
+1 "C++ compilers were pretty iffy back then"
AraK
That's okay. I'm not trying to sound like a rep whore, but I really just would like to improve my answer. nothing drives me bonkers more than being told, "this answer is bad" without knowing why:( No improvement for anyone, there.
GMan
I mostly ask questions on SO, and I fear I might actually BE a repwhore, not just look like one. I feel dirty. Let me go take a shower reaul quick =(
Hooked
Haha, but you do ask good questions, and are obviously well on your way to being a solid programmer.
GMan
Thank you. I hope to be one, so I'm on target.
Hooked
The compilers weren't _that_ iffy in 1999. Most of the stuff he's mentioning when talking about code optimization tricks (not algorithmic tricks) was already wrong then.
Pavel Minaev
Is it paranoid to think he didn't want to put much work into the second edition, so he let some things he knew he ought to change slide?
Hooked
+14  A: 

I don't know how good this book is on the topic it claims to be about (as reflected in its title), but I definitely wouldn't use it as a C++ or Win32 textbook. A few blunders I've spotted straight away:


void main(void)

Neither ISO C nor ISO C++ allows return type of void for main. You'll get at least a warning from any decent compiler (including modern versions of VC) for such code.


WIN32_LEAN_AND_MEAN instructs the compiler (header file logic, actually) not to include extraneous MFC overhead.

See here for an explanation of what it actually does.


// enter main event loop
while(GetMessage(&msg,NULL,0,0))

See the warning in "Return Value" section in documentation for GetMessage


However, some statements make me extremely skeptical about it being a good reference book for game development as well. For example:


Many computers will speed up or slow down due to the game's level of complexity. For example, if there are 1,000 objects running on the screen, the CPU is going to have a higher load than if there were only 10 objects. The frame rate of the game will vary, which isn't acceptable. Hence, you must synchronize the game to some maximum frame rate and try to hold it there using timing and/or wait functions. Usually, 30fps is considered to be optimal.

Any modern game will try to get as much FPS as possible. Timing the game logic to display update, and consequently delaying the redraw to ensure timing, hasn't been acceptable for over a decade. In addition, 30 FPS is rather low by today's standards; 60+ is considered to be optimal.


Don't be afraid to use global variables. Many video games don't use parameters for a lot of time-critical functions, instead using a global parameter passing area. For example, say a function looks like this:

void Plot(int x, int y, int color)
{
// plots a pixel on the screen
video_buffer[x + y*MEMORY_PITCH] = color;
} // end Plot

Here the body of the function takes less time than the function call. This is due to the parameter pushing and popping on the stack. In this case a better method might be to create a global parameter passing area and then make assignments before a call, like this:

int gx,gy,gz,gcolor; // define some globals

void Plot_G(void)
{
// plot a pixel using globals
video_buffer[gx + gy*MEMORY_PITCH] = gcolor;

} // end Plot_G

Aside from obvious stylistic problems with globals, the claim that using them is faster is false. In C++, the default calling convention for functions typically puts as many arguments as possible into registers. Thus, the first version of the function, with parameters, will receive both in registers, and do all arithmetic using registers as well (which is also faster). The one with globals will have to read and write the actual memory locations.


Use inline functions. You can improve the preceding trick even more by using the inline directive to get rid of the function call completely. The inline directive instructs the compiler to make its best attempt to put the code for the function right where it's called, rather than making the actual function call. Of course, this makes bigger programs, but speed is more important. Here's an example:

inline void Plot_I(int x, int y, int color)

Any modern C compiler treats inline specifier much like it treats registry - "whatever you say, I'm going to do as I see fit anyway". In other words, marking (or not marking) the function as inline has absolutely no relation to whether it will actually be inlined by compiler.


Always use 32-bit variables rather than 8- or 16-bit. The Pentium and later processors are totally 32-bit. This means that they don't like 8- or 16-bit data words, and in fact, smaller data can slow them down due to caching and other related memory addressing anomalies. For example, you might create a structure that looks something like this:

struct CPOINT
{
    short x,y;
    unsigned char c;
} // end CPOINT

Although creating this structure may seem like a good idea, it's not! First, the structure itself is now 5 bytes long— (2*sizeof(short) + sizeof(char)) = 5. This is really bad, and it's going to wreak havoc on the memory addressing. A better approach is the following structure:

struct CPOINT
{
int x,y;
int c;
} // end CPOINT

A bunch of wrong things here. The whole part about 32-bit words being faster than 8- and 16-bit is broadly wrong. In many cases you actually want smaller words for many reasons - first, because if you use them as arguments, they can often pack into registers (e.g. you can pack 2 shorts into a 32-bit register, but 2 ints would take two registers, contributing to starvation, and forcing something else on the stack). Second, when you copy those structures around, again, copying two shorts is just copying 32 bits as one word, but copying two ints is copying two 32-bit words.

In fact, the very claim that working with 32-bit words is faster than working with 8-bit chars is most likely a confusion with memory alignment (you definitely want stuff to be aligned at 32-bit boundaries).

Second, the claim that first version of struct - the one with char - consists of 5 bytes, and is "going to wreak havoc" - is totally wrong. The compiler will insert padding to align struct fields such that they are accessed with optimal performance. In this case, VC with default settings would pad the struct with 3 bytes at end, giving 8 bytes - and ensuring that arrays of this struct have all fields of all elements aligned at 32-bit boundaries.


Use binary shifts for simple multiplication of integers by powers of 2.

Mostly pointless, as compilers will automatically use shifts for that purpose whenever possible. In fact, this is a very old optimization, one of the first that appeared (because of its triviality to implement). Furthermore, compiler can actually do even better, and use some special purpose instructions, such as x86 LEA, to do certain arithmetic operations even more efficiently.

Pavel Minaev
Indeed, back in that day these tricks probably needed to be done. The compilers were meh :/
GMan
I am also a novice, and some of those sound reasonable. The bit shifting trick and the objects seem sound enough (I don't think the global variable idea is that great, especially because he uses a raw array in the function).
Hooked
The thing is, now modern compilers will optimize the multiply by 2 for you, letting you write readable code. Back in that day it wasn't so true, C++ compilers were still worrying about compiling C++. (Fun tid-bit, it actually optimizes it to x+x, rather than x << 2. there's a SO questions somewhere on it)
GMan
"Back in the day" - yeah, except the book is published in 2002. All of those things I've listed are incorrect, some of them blatantly so.
Pavel Minaev
Hm, my book was published 1999.
GMan
More details about each of there statements would be very interesting, they badness is not obvious at first sight.
Nicolas Simonet
I'm looking at Second Edition, publication date June 19, 2002. It's clearly an updated version as it mentions Windows XP quite a few times.
Pavel Minaev
I've updated the comment to include explanations on each point. It should also be noted that they still apply even when talking about VC6 (which, as I understand, was the suggested compiler in the first edition of the book - it still is in the second, by the way).
Pavel Minaev
Ah, then I guess he no longer has an excuse :)
GMan
This might be horribly wrong, but I thought VC6 was not a good compiler because it did not comply with C++ standards. I have not used it, but could that be an excuse for his workarounds?
Hooked
VC6 was indeed not quite ISO C++ compliant (which is no surprise as it was released in 1998, the same year ISO C++ standard was finalized - at the time, `g++` wasn't really much better). However, none of the examples given have much to do with it.
Pavel Minaev
+1 for the details (that was fast!)
Nicolas Simonet
+3  A: 
MadKeithV
+1 For mentioning the "Black Book".
Andy J Buchanan
+1  A: 

The second edition of the book was published in 2002. Visual C++ 7.0 came out in 2003. So he was still working with Visual C++ 6.0 users where C++ wasn't funny ANSI/ISO standard on that compiler.

Phil