Sunday, November 6, 2011

Smart pointers are dumb

C++ requires one to manage heap memory. Memory management can be tedious and error-prone. If different things reference this memory, and you de-allocate the memory without someone knowing, bad things can happen. If you forget to de-allocate the memory, you have a memory leak.

One solution is to use smart pointers. They let a programmer use similar syntax as normal pointers, with the benefit of memory being automatically cleaned up when nothing references that memory.

What you’ve gained by using smart pointers:

  • Anxiety reduction as you believe you are insulated from having to think about memory management
  • Potentially less typing

What you’ve lost by using smart pointers:

  • Stuff is now happening behind the scenes, but the syntax looks as though nothing is happening behind the scenes. Operators are overloaded. Evil is in the air!
  • The timing of memory de-allocations is implicit. Hidden both in time and in the code.

Normally I’m fine with memory management being done behind the scenes. Our tools are written in C#, a language with a memory manager built in, and I could care less about memory. Tools can be memory hogs to a certain (certainly huge) extent.

However, our runtime game needs to care. I want the easiest, most transparent way to manage memory.

To ease memory management in C++ I do the following:

  • Memory allocations using “new” are only allowed when a chunk (or level) of the game is loaded. Not frame to frame. Likewise, de-allocations are only allowed when a chunk (or level) of the game is unloaded.
  • I use a naming convention for class attributes. An “m” prefix means member, an “mp” prefix means a member that is a pointer, and that the class is responsible for allocating and de-allocating its memory. Finally, I use “mpe” for member pointers for whose memory the class is responsible for neither allocating nor de-allocating. The “e” means external.
  • I use simple macros to ease the typing related to allocation/de-allocation.

So, I centralize (in time) allocations and de-allocations, choose names that immediately identify a class’s responsibility, and wrap some of the clunkiness (such as checking for null before a de-allocation, setting to null after a de-allocation) in macros.

Some people use memory pools to achieve centralizing allocations and preventing a ton of frame-to-frame allocations. If I weren’t the only programmer on this project I would research this. As it stands my solution is easy to implement and transparent, and I can’t waste time researching “best” solutions to a problem that’s under control.

Programming shiznits? Oh no he di’n’t!

I view programming as a tool, and am not interested in it for its own sake. A lot of people get hung up on being evangelists about certain styles. There are always tradeoffs, and if you’re the only programmer on a team you better value time-to-implement and ease-of-understanding-for-you over most anything else. That being said, reusability is still important as you hope to be lucky enough to make more than one game.

The runtime stuff is being written in C++. I’m not sure if there’s a “best” way to organize code when making a game. I found it nice to break out stuff as follows (each a library except for the executable):

  • Core - Platform-independent stuff (vector/matrix and file/memory parsers, some macros to ease memory allocation/de-allocation), and interfaces for stuff that will be platform specific.
  • Platform specific –  provides concrete implementations to stuff like audio, input, windowing, error handling, timer. It adheres to the interfaces laid out in Core. The name of this library contains the platform (for example MS_Windows).
  • Game engine – game-independent and platform-independent framework (entities, messaging, collision, animation, scenery, spawners, path-following, simple scripting, lighting, triggers, asset management, camera (and other generic entities and some AI helpers).
  • Game – game specific code
  • Executable – small as possible

Dependencies

  • Core – depends on nothing
  • Platform specific – depends on Core
  • Game engine – depends on Core
  • Game – depends on Game engine and Core
  • Executable – depends on everything, but care is made to have the least amount of code here as possible.

Everything other than “Game” and “Executable” are meant to be reused from game to game.

Coming soon, why I think smart pointers are dumb.

Tuesday, November 1, 2011

Just another full-time indie game developer…

Here are my thoughts, one month in of full-time work:

Cats are weird. We have two, and full-time exposure has swung my opinion from “furry guys with personality quirks” to “if these guys were any bigger, they’d have made a double-team attempt on my life by now, quietly munching my remains with cold dead stares.” That’s the same expression they wear when eating everyday kibble, by the way. I now have to coddle them each day less I get ambushed due to some random reptilian synapse firing in kitty #1.

This is fun. I love the magnitude of work and the challenge. Our tools and our engine are our own, which was the right decision. We don’t have a product yet, so don’t listen to me.  I trust my intuition though, and having an in-house engine and tools to fondle and nurture is a blast.

This was a great decision. Life’s about making rash decisions, failing, being humiliated, and slinking back to whatever soul-crushing “real job” you came from while that guy you hated re-enacts the “they’re reeling ‘em in!” scene from Shawshank Redemption.