Game Design, Programming and running a one-man games business…

At last reaching code size issues

For indie games, my games are pretty big in code terms. By the standards of big triple A games, they are fairly simple. The problem with any game, is not really the lines of code as such, but the interconnections and complexities.

Now, if you have coded big systems for ages, you get used to writing very modular stuff. All my games are split into SIM and GUI classes, which in theory have very very little overlap. The problem is, that games of the sim/management genre become more and more intertwined between those two concepts. This means lots of unintended side-effects, and that often means more bugs. It also means a lot of possible permutations to test, and that invariably leads to more bugs.

In theory, I suspect the real answer to scaling up code is to go beyond merely┬áthinking in a modular way, and to write totally distinct programs, or at least DLLs. Having a clearly defined interface between the Sim, the UI and the gameplay rules is very handy and if you actually stick the GUI in a separate project, it makes it easier to stick to that with real discipline. That also makes it easier to have people port your game, switch to a different graphics API, or mod the game. To be honest, I’m not as good at this stuff as I should be, and the campaign code for GSB is bringing that home. It’s been far too tempting for me to just stick a bunch of spaghetti into the GUI code for a dialog box that does some SIM stuff. I re-designed various code today to make it more organised, but I should probably do quite a bit more of it.

I wish I’d coded totally open AI that could have been scriptable, or at least existed as a DLL that modders could expand. Coding that sort of stuff is normally a full time job for someone for a year though, so you can imagine why I didn’t do it :D


7 thoughts on At last reaching code size issues

  1. The way I handle AI in Golemizer (www.golemizer.com) is that I have a manager class that have the basic stuff an NPC can do like go there, use that skill, say that, say this to that NPC, find a target, find a path … And then the AI is just VB.NET I dynamically compile when the AI starts (or when the server starts).

    So basically all NPCs have (or can have I should say) unique AIs that I can edit directly while playing on the live server. All stats are handled by variables scripted in the AI. Adding a new variable that must be accessed outside the AI is of course a bit more complicated but I could have handle it a bit smarter then it is currently.

    This system is used by GMs to run custom events or when they want to build an opponent a bit more fancier than what I have built.

    I have used this exact same AI system for Dungeon of Loot (www.dungeonofloot.com) and the half-dead Blimp Wars (www.blimpwarsonline.com) and switching from one game to another was painless. Golemizer took a year to code part-time so the AI in it probably took 2-3 months.

    This means that you can also really screw the game if you’re not careful so that’s why I usually keep an eye on any new planned AI. That’s also the reason I don’t allow players to build their own customized NPCs (though that’d be really cool). For an offline game where I don’t care about the stability of a server though it’d be really powerful.

  2. The initial system was using Lua and then I had to switch last minute as there was some kind of memory leak in the .NET library I was using. Had my hands full already so switching to VB was faster than trying to figure out the issue. Should have gone that way to start with obviously but eh.

  3. See that is what I dread about using third party stuff. You assume it is 100% bug free and fast, and waste ages thinking it is your code that must be wrong, and then when you finally dig down and find its a problem in the third party middleware, you are stuck with it.
    I just dread that.

  4. There’s a difference between free third-party and paid-for third-party. With paid-for there is usually a support team to deal with those kinds of issues and tbh I would rather save 6 months of time by buying in middleware to solve an issue than to try and code it myself.

    If however you go down the free third-party then yeah, personally, not worth the risk. I tried using Ogre once… god that was painful, soooo many bugs.

  5. its always about finding the right mix between
    super-clean modular design
    and
    quick and dirty prototype code.

    Where a modular design is always (especially when looking backwards)
    the thing that should have been done, it could also
    mean wasting time on something that does not need so much attention to
    get it working.

    in the end its an economical question.

  6. Something you should really look into for the future at least. Is Component Based Design and a really powerful intertwined Messaging System (and please, NO managers. Just the wording leads to uber-classes that are hard to maintain and bug prone).

    With Components, once its designed everything is super easy. You can prototype a game/GUI/etc in hours/days. You can have a WindowEntity that describes a basic window (using a GUI example here). That Entity file (this is all data driven) also has all the buttons, radio buttons, check boxes, text, rich edit controls, etc., that the WindowEntity is made up of. Each of these is a Component. You have a ButtonComponent, RadioButtonComponent, etc. You write these once (they’re just pure data) and you have a System (ButtonSystem) that knows how to render them/interact with them, etc. Also in the Entity file is the overriding values for each Component (ButtonComponent has a default setting and the file overrides these and places the button where it needs it, sets its image/text, etc). Each ButtonComponent used in the window has its own Name/ID (which ever you prefer).

    Each System has it’s own std::vector (assuming C++ here) or std::map list of its Components and the Entity has a smart/weak pointer to that. In my case the System also holds a list of Entities linked to them so that you have full access. Basically the Entity is just a std::vector/map of smart/weak pointers and nothing else.

    Then comes the Messaging System for System/Sub-system/etc inter-communication. It’s the one, the only global variable I have (and don’t even mention a singleton or the guns come out!).

    So if your game module needs to create a dialog box, this becomes fairly simple (compared to having to directly link to the GUI system, worrying about changes in that code etc). Send a message something like, Message(“CreateDialogBox”, “GameDialogEntity123.entity”, &ThisClass.ThisFunctionHandlesButton()); (I use Boost Bind).

    I believe in keeping things simple. The texture system doesn’t need to know anything about the rendering system. The rendering system doesn’t need to know anything about the sound system, etc. I also hate having a class of a class of a class. Mine at best are 3 levels deep (though I cannot think of any over 2 at the moment).

    Anyways, a few ideas. Hope they help/inspire. Game looks great and I plan to purchase it soon.

Comments are currently closed.