Hacker News new | past | comments | ask | show | jobs | submit login
Dev Diary: John Carmack on RAGE for iOS (bethblog.com)
94 points by turtlesoup on Oct 29, 2010 | hide | past | favorite | 38 comments



I had been harboring some suspicions that our big codebases might benefit from the application of some more of the various “modern” C++ design patterns, despite seeing other large game codebases suffer under them. I have since recanted that suspicion.

Quoted for truth.

I learned C++ during the Meyers/Sutter era. Then Andrei Alexandrescu came along and I had Boost libraries sprinkled all over my code. My beard is growing grey and these days my C++ looks more and more like straight up C.


My C++ also tends to be simple.

I also have never had a need for any formal "design patterns", as every time I've encountered a problem for which it turns out there is named pattern in the books, a few moments thought about the problem has always led me to discover the solution myself.

Now, it could be that this means I'm some kind of programming genius. I wish that were true, but alas I think it is not so much a reflection of how good I am, but rather how mediocre many programmers are today.


"Design Patterns" exists to give a common vocabulary to the things we do with code and discuss the proper application of the techniques.


Some more Carmack tweets on C++

IMO, good C++ code is better than good C code, but bad C++ can be much, much worse than bad C code. 10:17 AM Oct 6th

I wish C++ had a "functional" qualifier to enforce no global references or side effects. 11:16 PM Sep 21st

Reading More Effective C++. I have grown to appreciate at least some uses of most C++ features, but I still don't buy in on exceptions. 10:26 PM Aug 13th


I'm no C++ fan (anymore), either, but I don't understand Carmack's taking exception with exceptions. If the alternative is guarding every function call with an if statement to check for error codes, I'll take exceptions almost every time. (Many game programmers I know think that checking for errors is usually bad game programming style, period, but I'm assuming Carmack isn't one of those people.)

Exceptions do have possibly deleterious effects on performance, but then, you can just be judicious about where you use them. Exceptions are at least appropriate for catastrophic failures like, "Oops, the game just crashed," or, "Your network connection died." Thinking about manually unwinding out of a game-over failure like that makes me grimace.

Sigh, game programmers. :)


You're making two mistakes: One about how exceptions work, and another by not considering our constraints.

Exceptions don't just add an overhead when they're thrown, they add overhead for every function call. How else would the exception-handling runtime know to unwind the stack to the correct addresses? It is this performance degradation that we avoid. Why? For the PC, it doesn't really matter. The XBox360 doesn't handle the performance hit very well. The compilers for the Nintendo DS (edit: and the Wii) don't even support exceptions, and the PSP is so crazily architectured that things like floating point numbers or exceptions can cause a framerate to drop from 300 to 12. I've not worked on the PS3. You must understand that these consoles and handhelds are designed very differently from PCs, and are never as powerful.

We do check for errors, we just stay away from exceptions. And dynamic casting, when we can (the DS does a freaking string compare against the vtable!).


> Exceptions don't just add an overhead when they're thrown, they add overhead for every function call. How else would the exception-handling runtime know to unwind the stack to the correct addresses?

With unwind descriptors/exception handling tables, which can be stored in a read-only segment of the executable and don't need to be paged in until an exception occurs. They have no runtime performance cost until an exception is thrown.

Unwind tables are the default exception model on most modern gcc C++ targets. They're also the default exception model in Visual C++ x64, at least.

c.f.:

http://stackoverflow.com/questions/318383/exception-handling...

http://msdn.microsoft.com/en-us/library/1eyas8tf(VS.80).aspx


Yes, that's fair for the PC (I was aware of this for the PC, which is why I said exceptions don't really matter on the PC). But (from memory) I don't believe the Xbox allows for this, even though it uses a very similar variant of the same compiler. It's a moot point, though, for all the other reasons I mentioned. When you've got a cross-platform codebase - and there are precious few platform-exclusive codebases these days - it is far easier to turn exceptions off across the board than deal with individual platform's quirks.


Throwing an exception is a misnomer. An exception doesn't necessarily mean that an error happened. It means, "please unwind the call stack". Unwinding the call stack in a game is a no-no.

Games, especially the simulation, must be deterministic. An exception would most likely destroy determinism.

The simulation/AI is a big, hairy, ugly set of if/else and switch statements anyway. Adding extra error checking is not an extra burden.

The visualization sends asynchronous commands from the CPU to the GPU. The error condition won't be known right away. Querying the GPU will cause a flush of your command stream and ruin performance.

Dynamic memory allocation is reduced to a minimum during a frame so you don't get out of memory errors. Strings are allocated in a pool. Network sockets, file handles, and other performance intensive resources are not created mid-frame.

Exceptions are not a win for games. It is usually best to run the entire frame and then check for errors all at once at the end.


> Unwinding the call stack in a game is a no-no.

For the most part, I agree, which is why I said they're probably only appropriate in games when used judiciously, e.g., for fatal errors.


Exceptions are actually nice for single methods, even in a game.

  void    Horse::ImOnA()
  {
    try
    {
       Giddyup();

       if (IsDead())
         EX_ERROR("Guess I wasn't on it.");

       if (IsFlippingTheFuckOut())
         EX_WARN("Safety hazard!  Get the f outta the way!");
  
       Feed();
    }
    catch (CException& ex)
    {
      ex.Process("Horse::ImOnA() - ", NO_THROW);
    }
    CleanupAfterHorse();
  }
If the horse is dead, then "Horse::ImOnA() - Guess I wasn't on it." will be printed to the console.

If the horse is acting like my mother, then "Horse::ImOnA() - Safety hazard! Get the f outta the way!" will be printed to the console.

Etc.

So this is a nice way to report errors. It's basically a typed goto. But don't you dare try to use it for flow control! >:(

You can report various "levels": EX_DEBUG, EX_WARN, EX_ERROR, EX_FATAL

ex.Process() checks what kind of exception it is. And for EX_FATAL, for example, it will terminate the application (after writing the message to a log file).

It's quite nice to use exceptions in this way, because you rarely ever need to even think about making your methods "exception safe" at all.


I found this part of his article to be interesting. I'm working through a CS degree and learning C++ for the first time after cutting my teeth on Python and C#. What exactly does he mean by "(restrained) C++"? He mentions a contract studio using the STL and boost. We are using the STL in our data structures class...does John Carmack eschew the STL and roll his own data structures?


Kids these days with their allocations and virtual memory. shakes fist

You don't need std::vector if you don't need dynamic memory allocations. Game programming and systems programming is a whole lot different than web or desktop development.

For games, you create a memory budget up front. You decide how much memory sound, textures, models, AI will consume up front and then statically allocate that memory up front. http://gamesfromwithin.com/start-pre-allocating-and-stop-wor...

You can statically allocate at the start of a game, level, and frame.

From the original article: OpenAL appears to have a limit of 1024 sound buffers, which we bumped into. We could dynamically create and destroy the static buffer mappings without too much trouble, but that is a reasonable number for us to stay under.

It also sounds like Carmack is loading an entire level as a memory mapped file and then doing reads into specific indexes within the file.

Take a look at the source code that id has open sourced. That's the best way to get a feel how this style of development works. I believe RtCW is their last release. ftp://ftp.idsoftware.com/idstuff/source/ http://github.com/monoid/rtcw-rebirth


Actually, I'm 38...bit of a late starter :) Thanks for the reply and link. Modeling and simulation is my area of interest (I work in civil and environmental engineering), so it will be interesting to see what patterns will work best.


In his own words: http://twitter.com/#!/ID_AA_Carmack/status/21119808432

I consider myself a decent programmer but I have more trouble reading template heavy C++ than I do haskell code. To me, restrained C++ means keeping the unreadable bits outside the code base and isolated in their own library, like Boost :)


One problem with C++ templates is that they're infectious. You're right that the Boost source code is quite unreadable compared to vanilla C++, but even using Boost types and algorithms in your own code often makes it impenetrable, too.


Template meta programming is very neat stuff, but the problem is that it's basically another language that lives on top of your language. Except that it's not a full-fledged language so it lacks all of the features that keep other programming languages manageable. It's like assembly code, except instead of just twiddling some bits in registers and RAM you're working with a far more complicated entity (an entire program), making the problem that much worse.


C++ lends itself to a large variety of different programming styles and paradigms. C++ also lends itself to premature baldness, by developers ripping their hair out trying to make systems developed in different styles interact with each other.

A popular thought is that any given team or company should pick a particular subset of those styles -- and perhaps a subset of C++'s features -- and use them to the exclusion of others.


Google gives a good take on restrained C++: http://google-styleguide.googlecode.com/svn/trunk/cppguide.x...


Nice, I read this a long time ago before learning C++. It's interesting (and reassuring) that some of the stuff we are learning is considered bad practice by Google.


I'm on the same arc (especially the template Kool-Aid phase), except perhaps further along: now I forgo C++ entirely and write plain C because it's so much easier to wrap from higher-level languages.

I do miss smart pointers, but on the other hand, dealing with malloc and friends keeps me honest about what really needs to be written in C.


For the high performance stuff I write my kind of restrained C++: never STL in the interfaces of the "modules," use STL algorithms (they are good) but otherwise manage memory in custom ways (which is easier by not using STL containers!).

But I had to solve one interesting problem using some recursive definitions and code, and discovered that once I "freed" the code from classes (made them C functions) I was able to express it properly -- just having them as members prevented me to see that the solution is much more obvious when you actually use plain pointers and don't think about the same "object" even during the life of the function. Add to that in the member "this" can't be null.

When you need real expressiveness, C can't be beaten. C++ syntactic sugar helps sometimes, but limiting to it is... limiting!


Do you use STL then ? Because, that was pretty much the only reason I started using C++.

Or do you write your own containers


Provide Date of Birth to Continue

This site requires cookies. Please enable cookies and try visiting this site again.

is this a joke?


If they look at their logs, I bet they'll find that most people claim to have been born on the first day of January.


You can thank ESRB for that.


Speaking of ESRB ratings, how is this going to get on the iOs devices? Aren't the app store rules against the following:

"This is the perfect setup for a quintessential first person shooter game play experience — you pick your targets, aim your shots, time your reloads, dodge the bad guys, and try and make it through to the end of the level with a better score than last time. Beyond basic survival, there are pickups, head shots, and hit streak multipliers to add more options to the gameplay, and there is a broad range of skill levels available from keep-hitting-fire-and-you-should-make-it to almost-impossible." -JC

(off to go look...)

Sure enough, part 15 should prevent this app from ever getting to the public (see http://photos.appleinsider.com/App%20Store%20Review%20Guidel... ). I doubt Apple has the eggs to tell Carmack no. Time to see if Jobs' moral views outweigh his greed. (edit: BTW, I think his greed will win)


Oh come on... Here are the specific guidelines you are referring to:

Apps portraying realistic images of people or animals being killed or maimed, shot, stabbed, tortured or injured will be rejected

Apps that depict violence or abuse of children will be rejected

"Enemies" within the context of a game cannot solely target a specific race, culture, a real government or corporation, or any other real entity

Apps involving realistic depictions of weapons in such a way as to encourage illegal or reckless use of such weapons will be rejected

Apps that include games of Russian roulette will be rejected

How would those guidelines apply to someone's awesome first person shooter?

Maybe the "reckless use of weapons" part. But that's not the spirit of the law --- the spirit was likely to prevent people from e.g. making an app that gives a step-by-step photographic guide to creating a pipe bomb, or something of that sort.


Ruined my attempt to read it in Instapaper, too. Ugh.


I’m sure I could do it in four months or so (but I am probably wrong)

Perfectly encapsulates the essential pain of estimating.


John Carmack has always been my mancrush since the Quake days.


Youngster! I've had mine ever since Wolf3D was released. His plan file updates held the same place HN does now: I checked for updates constantly.

    finger johnc@idsoftware.com
    [idsoftware.com]
    finger: connect: Connection refused
sigh...


I consider myself sharp, but not smart. So I'm often humbled when I read stuff on Hacker News, but I am always completely dumbfounded when I read any of the technical pieces by John Carmack. I read 90% of that article and I comprehended about 20% of it.

I toil with silly web development side projects for months on end that evolve into nothing and he's coding complete games, single-handedly (though admittedly using some existing codebases and content) in a couple of months.

That guy is wicked smart.


You know he builds rockets in his spare time right? http://www.armadilloaerospace.com/


...and, just as important, has done his "10,000 hours" and then some, on the practice of game engine development.


I'm a game developer (though only ~3 years experience) and I only understood 50% of it. Gives me something to aspire to that someone can be that good at it.


I'm not even a game developer or a C++ developer but he gives me the same motivation. It blows my mind there's a guy who clearly has a significant level of wealth (healthy 8 digits, at least) yet gets down into the guts of coding an iPhone game for months at a time. That's world champion passion right there.


Please provide date of birth to continue?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: