How do I design video games properly?

Pages: 123

Manual memory management is only a minor inconvenience if you do it properly.


What do you mean by "properly"? I've heard this statement many times from C++ coders, but everyone I ask gives a different recipe.
Also programmers I know that program in GCed language for a longer time commercially (not just a single project at university) don't want to go back to a non-GCed language, unless absolutely necessary.

Why? Manual memory management forces you to have some kind of an owner for every object. This imposes a serious limit on how you design your program. Even a trivial thing like managing two collections sharing objects can be a pain then. Additionally, imagine adding a caching layer to an existing application. Who should own the cached objects now? The cache, the previous owner (might be many owners), or the client? It is easy to introduce subtle errors, even with all the modern STL machinery. I'm not saying you can't do it, but that having to manage memory by yourself introduces new dependencies in code (e.g. between the cache and the owner of the cached objects). And dependencies are bad.

If you'd like to check your "manual memory managment skills" (and if it is really just a minor inconvenience), try to implement a persistent data structure [1] in C++ and make it fast on multi core system (this is the main purpose of persistent collections; you can't use reference counting, because it does not scale on multicore).


Also, Python code can never be truly self documenting because type informations are lacking


Agreed. But when compared to Scala, which can be also viewed a scripting language, C++'s type system is also lacking in this regard .


Now that's just plain wrong, in Python at least. You DO need to know that arguments are passed by reference, and what the difference between


Well, you need to know argument are passed by reference and what it means. Period. Nothing more. Never had to think about whether I should pass it by ref by val or by pointer, or by const ref... etc.


I guess my main complaint is that those languages aren't really much more expressive than, for instance, C++.


If code is much shorter, they are.

[1] http://en.wikipedia.org/wiki/Persistent_data_structure
Last edited on
closed account (S6k9GNh0)
Actually, manually handling memory generally doesn't have any design restraint, it only handles how memory is handled. Even in a garbage collected language, you still require the user to tell a library when they're done with a facility which is an ideal time to also deallocate the facility if wanted as well.

Also, just because the garbage collector hides object ownership doesn't mean its not handled. Doing it manually provides you more control over memory. None the less, you may not need that power.

I have a mindset that goes something like this: We often try to do everything at compile-time so as to not burden runtime. Why be different when it comes to handling memory?

EDIT: Although don't get me wrong, the uses of a garbage collector are not bad but it feels like people are just getting unnecessarily lazy by consistently relying on a garbage collector when they don't even take advantage of it's real purpose.
Last edited on

Even in a garbage collected language, you still require the user to tell a library when they're done with a facility which is an ideal time to also deallocate the facility if wanted as well.


In most of the cases you don't need to. Good 99% of resources is memory-only.


We often try to do everything at compile-time so as to not burden runtime. Why be different when it comes to handling memory?


Right, but manual memory management is not at compile-time, it is program-time:

1. We are trying to push as many things as possible to the compiler, to save on runtime overhead.
2. If not possible, push as many things as possible t o the runtime.
3. The rest is left to the programmer.

Manual memory management is really level 3. GC is level 2 and sometimes even level 1 (some clever VMs can remove heap allocation at all in some cases). Most features of C++ (and its speed benefit) is because it does most things at level 3. You can get fast programs but you do all by yourself. Not really so much more high level than assembly with a fancy syntax and sophisticated macro engine called templates.

On the other hand scripting languages stress the point 2., and statically typed VM languages like Java try to operate mostly on level 1 (and 2. when not possible).


it feels like people are just getting unnecessarily lazy by consistently relying on a garbage collector


Being lazy is a good thing. It means you don't want to solve the same problems again and again. Manual memory management is a thing like that - you have to keep it in mind whatever you program. You even need to document it, when you are library writer. You can't really run away from this. GC is a solution that moves all these tasks to a one single place, so that you can concentrate more on business logic than on technical details. This is what I call "higher-level".
Last edited on
The only place memory management becomes problematic is in the case of cyclic dependencies, and that's just as much a problem for GC collected stuff as it is for "manual memory management." In most other cases it's entirely reasonable to rely on standard containers or smart pointers to automate our manual memory management.
Last edited on

I disagree with palfil and darkestfright. A design document really only makes sense if you really know what you're doing, which clearly isn't the case for a beginner. And C/C++ doesn't automatically make anything low level.


Don't agree. Having some form of layout as to how to proceed is essential in keeping on track.

Beginners are learning 3D/2D vectors, cross products, etc. In such cases, they aren't making games, they are learning the principles of geometry. If that is your context, then fine, but if the programmer is making a game, they need something to base development off of. It's best not to start by learning sloppy habits of design.
Last edited on
closed account (1yR4jE8b)
Exactly.

A design document doesn't necessarily need to be 200 pages of technical details, it can be just a few pages of handdrawn diagrams, and organized brainstorming of bullet-points about the general idea.
Beginners are learning 3D/2D vectors, cross products, etc. In such cases, they aren't making games, they are learning the principles of geometry.


I'm not talking about beginners to geometry, I'm talking about beginners to game programming. What does a design document actually mean to that beginner? How does he know what he should put in there? If you've never actually written a game, how are you supposed to know about the pitfalls of any particular design idea?

No beginner would be able to cough up a design document that is of any use to him for anything else other than a completely trivial game for which he wouldn't have needed the design document in the first place.

How does he know what he should put in there?


By using that globular thing above his/her shoulders called a head. Maybe he/she won't know that he/she should use a verlet integrator for their problem, but by thinking about it, they may know they need to keep track of one or two historical iterations of position, acceleration, velocity, or that it's better to store a surface normal with the surface object, rather than do a cross product and normalize every time they need a unit normal, etc. Thought, whether applied to coding or to design, is something that gets better with use and experience.
closed account (1yR4jE8b)
how are you supposed to know about the pitfalls of any particular design idea


What a trivial argument, even professional game-designers get these wrong all the time.

What a trivial argument, even professional game-designers get these wrong all the time.


Doesn't a game company do a postmortem on their products after release?

I tend to see pitfalls during development and have to refactor. No big deal. You should be willing to refactor and re-write rather than give up. What do you learn from giving up anyway? I learned my game will never be made unless I make it.

Additionally, it's one thing to develop a fill in form for a business app, but defining a user interface for a game that doesn't hurt the overall appeal seems much harder to do. FPSs and third persons use the standard WASD and mouse developed by ID. What about a flight sim? A side-scroller? RTS?

Then, there is the AI. Gawd awful AI in almost every single FPS I've ever played. The best enemy AI to date was F.E.A.R. Worst to date is probably Crysis but the ally AI in L4D/2 and HL2 is pretty horrendous.

There has never been a good ally AI made yet.
Last edited on
That's because it's really, really hard to do.

And the only problem with L4D(2)'s AI is that it's too accurate for multiplayer (also sometimes they get in the way of gunfire and then complain at you for shooting them, but players do that too).
I never had much issues with the L4D AI. The only annoying thing is that they don't communicate. When I get grabbed by zombies, I can shout at my teammates and, if they're physically nearby, kick them repeatedly. The AI will just disappear quietly.

In most other cases it's entirely reasonable to rely on standard containers or smart pointers to automate our manual memory management.


Yeah, it is correct, but it is slow and doesn't scale. Smart pointers have a huge memory and runtime overhead, much larger than properly tuned GC, and they are a scalability killer on multiprocessor machines. They are useful only for managing big and costly objects.

I also can't see how cyclic references can be a problem to a GC, care to elaborate?

Last edited on
closed account (S6k9GNh0)
auto pointers (auto_ptr) and often folded down to no runtime hit at all and often useful in exception handling. Aside from that, I agree. Smart pointers are a terrible method of going about memory management (if it can be considered a method of memory management at all). I would much rather someone use a proper garbage collector than reference counting or reference counting pointers.
computerquip wrote:
I would much rather someone use a proper garbage collector than reference counting or reference counting pointers.
So why?
Because reference counting is *slow*.
closed account (3hM2Nwbp)
With reasonably sized heaps, GC wins in my eyes, hands down. The problems start popping up when you get up to >4GB. If only there were a collector out there like C4 that was freely available (or at least doesn't cost a years wages for a license), then I would probably be doing all my server work in either Java or Scala. I really can't justify using a dozen systems to manage a solution that can easily be managed by a single one.

To make this post not complete spam, I'll comment that the FEAR AI were decent.
Last edited on
Java CMS GC works fine with heaps > 4GB. We used it with heaps of size 64 GB and no noticeable pauses. The only problem with CMS is you should keep garbage production rate not excessively high, because if CMS lags behind, it eventually pauses the application. You can also use off-heap manually managed storage for big objects, e.g. images, data buffers etc. Anyway, yeah, C4 definitely rocks. I think it is a matter of time as the ideas beghind it get implemented in other collectors.
closed account (3hM2Nwbp)
You've never had an issue with heap fragmentation using the CMS collector with a 64G heap? How often did you restart your instance?
Topic archived. No new replies allowed.
Pages: 123