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

The games programming advice that’s impossible to describe.

Occasionally I see some interesting posts on reddit or gamasutra or some other dev site where programmers are asking about stuff to do with game development, and I find myself thinking ‘these aren’t the things you really ned to know’, but because its such a DIFFICULT thing to articulate, I never even try. I’m going to try now…and it will be messy.

 

A long time ago, when the world was in black and white and you could get your milk delivered even in the cities, I went for a job as a game programmer with a smallish UK game studio. I didn’t get the job. I remember in the interview being asked about my code, and in some vague way trying to explain that I knew what I was doing and a proper software developer. I waffled really badly about how giving sensible names to variable meant that I knew what I was doing and not some n00b.

Hahaha.

In my mind…this:

for(int counter = 0; counter < total; counter++)


Made me so much better a software engineer than

for(int x = 0; x < total; x++)


That just goes to show how much I had to learn. The real problem is that the stuff you need to learn is big ‘hand-wavey’ stuff that its really hard to explain, let alone teach! if you haven’t already read a book like Code Complete, Now would be a good time. I will try and explain the sort of stuff that it really helps to learn, and it will be vague and awkward, and hopefully that kind of makes my point about how hard it is to grok this stuff.

I have a class in my latest game called GUI_Tile. Its the visual representation of an actual tile in the game world called SIM_Tile. Each SIM_Tile has a GUI_Tile, and anything that is on-screen is handled by GUI_Tile. In order to draw my world, I go through all of the GUI_Tile objects and call draw on them. Actually, thats what I used to do, but it turns out there are a lot of them and thats fairly time consuming. When I profile the code, looking at where the time is spent, I realize that a lot of it is not actually directx calls, but its transform stuff, and scaling stuff, and working out the sizes of sprites based on some animation they are doing, and their offsets and whether or not they are even on-screen given the current camera position. The actual DrawSprite() bit of each GUI_Tile call is only the last statement…kind of a footnote.

While all this is going on, the other 7 effective cores of my CPU are chatting about whats on TV and picking fluff from their navels.

So clearly, I should find a way to multi-thread all this, even though I’m using Directx9 which is effectively single-threaded.

Soo… I could create a new thread at the start of the app, and make that my directx render thread. it could then do nothing but make render calls, and all the other stuff could happen in another thread, thus allowing me to double up on what was going on. To keep things from going crazy, and me updating a sprites co-ordinates just as directx rendered it, I need a hard STOP! (or mutex etc) at the time I start rendering, but it will still allow some overlap surely? I could carry on with the windows message handling and sound/input processing in thread 2 while thread 1 was still rendering the previous frame.

Or

I could split the GUI_Tile::Draw() call into GUI_Tile::PreDraw() and GUI_Tile::ReallyDraw(). If all of the stuff in the PreDraw() is self contained or ‘read-only’ (in other words that function never changes the value of any data outside its own object), then I can run a whole bunch of those at the same time. I can keep my directx in the main thread, but pass all the tiles in bunches off to 7 other worker threads to do PreDraw(), then when they ALL finish, I can just quickly loop through the Draw() calls, which are way faster.

Or

I could not do a lot of this transform stuff or drawing stuff each frame anyway. I could use a dirty-rects system, where when I render a frame I keep a copy of the whole thing in an offscreen buffer. I then only bother calling Draw() on those tiles which I know have actually changed or done anything. That way I’m massively cutting down on the number of Draw() calls I make, and I can keep the entire thing in one thread and thus way simpler.

Or…

etc.

The real thing you need to learn to be a decent game developer, is which one of those solutions will work best for this game, with this hardware, with this API, with this data. Coding any one of those solutions takes TIME. Debugging them takes more time, and profiling and analysing to see which works best takes more. Maybe having 8 threads all running is actually slower than just one (this can happen if you do it badly). Maybe a dirty rects system falls apart dramatically when zooming and scrolling. Maybe assuming PreDraw() is a nice self contained function is a bug-prone disaster waiting to happen in obscure and impossible-to-debug ways.

This is the real hard stuff, and the main reason its real hard is that its very difficult to get on top of this sort of thing until you have done it a LOT. If you have programmed, for example, a sound engine…well done. Take a bow, its honestly not that easy, and I bet you learned a lot. You have programmed your FIRST sound engine. Now delete all the code and program it another way entirely. then again, then again, then again. NOW, you know how to program a sound engine. you know why method A is slow, why method B is buggy, why method C is hard to maintain, why method D doesn’t scale, and method E Is awesome, but only on Playstation 4.

This is why the top jobs often to go to coders with experience, and why the sheer amount of code you have written and the number of hours you have been typing code really does matter. Being a good programmer is rarely about those things that are often bandied around like ‘always comment your code’ or ‘use descriptive source control commit descriptions’ or ‘use this syntax in your code’. Its mostly about the big ‘code architecture’ decisions. The way you lay out your code, the overall designs, the thinking behind how the whole process snaps together.

The most efficient coding you ever do is probably with a pen and paper, or a big chalkboard on the wall. When you have done this a LOT, you can do that in your head, but that takes decades. The more you code, the better you get.

 

After 36 years of it…its mostly just typing

I guess that a lot of people who read my blog are programmers and a lot of them are younger than me. I’m now 47. I was coding a new feature for Production Line yesterday, (the colored overlay & icons for the zoomed-out view) and it occurred to me to kind of ‘live-blog’ it in my head as I was typing, wondering if it would be of interest to people if I recorded doing that sort of thing in a video. Maybe if you are new to coding, or wondered what the real-world dev process for coding a strategy game was like…it might be interesting.

As I did it, I started to realize it would be VERY hard to follow if I did it. Frankly I can code faster than I can describe what I’m coding. Much faster. In fact I write C++ code faster than I write this blog. Visual studio has Intellisense, and I use Visual Assist (from whole tomato) to make use of their even smarter intellisense, so I’m only typing a few characters of each word anyway. Plus…after coding since age 11…I can pretty much write the iteration of an STL container in a for loop and call member functions whilst drinking tea (or on the phone to someone).

I am often AMAZED at how long it takes some people to make a game. I know that sometimes these people are perfectionists and they put a lot of ‘craft’ into their games, and they agonize more about design features than I do..and often it pays off with those mega indie hits that don’t look technically hard to make, but have such good design or polish that they sell a bazillion copies. I totally understand that, and I admit that I don’t spend *enough* time on my games (although I intend to change that with production line, which deliberately has no schedule or end date.

What I do *not* understand is the time it seems to take people, or the effort they seem to think is involved, when it comes to implementing a particular feature from a technical point of view. This is especially true when those people use ‘managed’ code or a higher level language, or unity or some other middleware. Frankly if an old fashioned dinosaur like me can code a feature from scratch in C++ in a day, then the younger more savvy kids with their middleware should be able to do it in an afternoon, but that never seems to be the case. For a long time, knowing this has driven me nuts, until I eventually have concluded that its just because I’m older, and have a scary amount of experience doing one thing day-in and day out for DECADES.

I literally have been coding longer than most indies have been breathing, and its always been in C++ (Actually I think Asteroid Miner may have been C) , and always directx, and always for windows. I went from DX5 to 7 to 9, but thats it, I’m still on 9, and I know it well.  As a result, when I’m coding, unless its some complex multi-threading stuff…I’m probably not  ‘coding’ as much as I am just typing. I know the code to type, and it flows immediately from what I want to achieve. Its just a matter of hitting some keys on the keyboard.

image1

I think this is a big advantage to not being a magpie when it comes to new software and development environments. I still use Visual Studio. I still use C++/DirectX. I still use perforce, I still use Photoshop and paintshop pro, and AQTime and nvidia nsight. In the last year or two, the only change to my development environment has been that I now also use the Visual Studio Concurrency Profiler, which is excellent. Thats one new piece of development GUI I had to learn in 24 months of work.

As you can imagine, this makes life extremely easy. I also coded my own graphics engine, which means it never changes unless I want it to. I don’t have to ‘work out the bugs introduced by the latest changes’ in the engine, because there aren’t any, and if there are, I did them, and I know what I did. And obviously I have all the source code anyway, and can roll-back whenever I like. Its easy. Never underestimate how much keeping a stable work environment can boost your productivity.

In addition, I also am a bit of a workaholic (which helps), plus I have no kids and only low-maintenance pets (cats). I live somewhere incredibly quiet and am rarely disturbed. My office is dedicated to my work, not shared with anyone, and its quiet, and laid out very comfortably with a comfortable chair, big desk and lovely big monitors, so its a nice place to be. This all definitely helps.

My tip to anyone finding their coding productivity low is to resist that urge to upgrade to the new X, or the new Y, or to make any change to your work environment just because you like new things. Sometimes keeping things the same is the best way to boost your productivity.

Drawing a LOT of sprites

I’m doing early work on my next game, a completely new IP. I’ll be announcing it in a few months. Anyway… it involves drawing a big world with a LOT of objects in it. tens of thousands on screen probably. Drawing 10,000 objects in 2D is not as simple as you think.

If you are a non coder, or someone who only ever uses middleware, you might think ‘the new video cards can draw 10,000,000 polys per frame, what’s the problem? and indeed there is *no problem* if you want to set a single texture and then splat 5 million sprites on the screen that show it. Thats one (well…probably several) draw call, one render state, one texture. Even really old video cards like that.

The problem is when you have a lot of different textures and want to swap between them, because for engine-related reasons, you need to draw stuff in a specific order. In a 3D world, you can use a Z-buffer and draw out of order, but with 2D objects with some soft aliased edges, that looks BAD. The good old fashioned painters-algorithm is your friend. The problem is, if you draw back to front and the sprite textures needed go A B A B A B, you are kinda fucked…that means a lot of texture changes, and in directx9 (which I use for compatibility reasons), texture changes mean separate draw calls, which stalls the video cards, and is sloooowwwww.

Relevant video from GSB2:

So what are the workarounds?

Texture atlases. This is the obvious one. Stick A & B in the same texture, and you are laughing, suddenly stuff is a LOT quicker. This only solves the texture issue, not drawing to different render targets, but you can defer those draws anyway and do them separately (GSB 2 does this). Texture atlases are an obvious ‘win’ even if they only halve the texture changes. The problems here are that you either need to know what textures will follow each other and pre-compile texture atlases (something I’m trying right now), or you need to dynamically create texture atlases based on recent drawing, and effectively use an off-screen render target as a texture ‘cache’. I tried this recently…and it was actually slower :(

Dirty-rects. Basically draw the whole scene once, and save it in an offscreen buffer, and use it as your background, a single quad blaps the whole screen, and you only draw stuff that has changed / is animating. This, as I recall was used by sim city 4. The only problem is that scrolling really causes hell.

Intelligent grouping. The painters algorithm is only really needed where stuff overlaps. if I draw a tile, then draw a sprite on top of it, I need the tile first, but there is no reason why I can’t draw all the tiles first, then the contents. That means I can then sort the tiles by texture and draw them in a handful of calls (or one, if the tiles all fit into an atlas). You can do this at pretty much any level, effectively drawing ‘out-of-order’ but with caveats. Again, GSB2 does this, with various objects, especially debris and asteroids. In fact it goes one stage further by scanning ahead with each draw call to see if some non conflicting later objects could be ‘collapsed’ into the current draw call.

Multi-threading and other speed boosts. If you have too many draw calls and things are too slow, then you can expand on the time available to make draw calls. Essentially you have two threads, one which prepares everything to be drawn, and the draw-call thread, which makes all your directx calls. This way they both run in parallel (also note that the directx runtime will be another thread, and the video card driver another one, so you have 2 threads less than you think. With a hyperthreaded 4 core chip, you have 8 truly simultaneous threads, so you give away 2, have 1 core thread, 1 render thread and 2 extra ‘worker threads’ spare. Because of my own disorganisation, I tend to have directx called from my main thread, which means I do the inverse. GSB2 did this, with all of the transformation stuff for the asteroids, debris and other bits and pieces handed to a bunch of threads while I was busy with other stuff, then returning to the main thread to present the draw calls. Less efficient, but way better than single threading.

Hybrids. All of the above techniques seem valid to me. Although I am currently fixated on pre-compiled texture atlases, I’ll definitely use multithreading and probably some of the others. With some parts of a game, a specific optimisation system may work well, and with others it could be useless. It really is specific to what you draw, and is why I prefer a hand crafted engine to a generic one.

My basic problem is that (without explaining what the game is), I have a small number of ‘components’ that make up a tiny scene on a tile. There will be a lot of components per tile, as I want a fairly ‘busy’ look, but rendering them all individually may be ‘too much’. What I may end up doing is pre-rendering each conceivable tile as an offline-step, to reduce the number of calls. I’d like that to be a last minute thing though, so I can keep editing what the scenes look like. IU also want sections of each tile to animate, or be editable and customizable, which means there is less scope to pre-render them.

It will make a lot more sense once I announce the game :D

Sample C++ game loop : Democracy 3

When I first started coding, especially when I first did C++, there was a lot of confusion about where exactly the ‘game’ was, and more specifically, what a main game loop looks like. Because these days, all you hip kids code in Unity or Gamemaker or MyFirstIDE or some other colorful beginners IDE for the under 5s*, you never actually see your game loop, and have no idea where it is, let alone what it does., However, us real-men who code from the ground up have to write one. Here is mine from the PC version of Democracy 3. There are few comments, because in my godlike knowledge, I understand it all at a glance.

======================================================================================
void APP_Game::GameProc()
{
    HRESULT result = GetD3DEngine()->GetDevice()->TestCooperativeLevel();
    if(FAILED(result))
    {
        if (result == D3DERR_DEVICELOST )
        {
            Sleep( 50 );
            return;
        }
        else if(result == D3DERR_DEVICENOTRESET)
        {
            if (!GetD3DEngine()->Restore())
            {
                // Device is lost still
                Sleep( 50 );
                return;

            }
            Restore3D();
        }
        else
        {
            Sleep( 50 );
            return;
        }
    }

    GTimer looptimer;
    looptimer.StartTimer();
#ifndef _GOG_
    GetSteam()->Process();
#endif //_GOG_
    GetInput()->Process();
    GUI_GetCursor()->SetCursorStyle(GUI_Cursor::DEFAULT); //reset each frame...
    if(BActive)
    {

        GUI_GetMusic()->Process();
        GUI_GetSounds()->Process();
        if(PCurrentMode)
        {
            PCurrentMode->ProcessInput();
        }
        SIM_GetThreadManager()->ProcessFrame();
        GetTextureHistory()->Reset();
        LOCKRENDERTHREAD;

        GetD3DEngine()->BeginRender();
        if(PCurrentMode)
        {
            PCurrentMode->Draw();
        }
    
        GUI_GetTransition()->Draw();


        GetD3DEngine()->EndRender();

        RenderFont();
#ifdef _DEBUG
        if(GetInput()->KeyDown(VK_LSHIFT))
        {
            GetTextureHistory()->Draw();
        }
#endif //_DEBUG
        GetD3DEngine()->Flip();    

        RELEASERENDERTHREAD;

        looptimer.Update();
        if(looptimer.GetElapsed() < 16.0f)
        {
            looptimer.Update();
            if(looptimer.GetElapsed() < 16.0f)
            {
                Sleep(0);
            }
        }
    }
    else
    {
        ReleaseResources();
    }

    if(BRestartPending)
    {
        BRestartPending = false;
        SilentRestart();
    }
}

======================================================================================

*yeah I’m mocking different IDEs. deal with it :D This is sarcasm. There is no proven link between masculinity and choice of game development environment.**

**yet.

Theoretically auto-balancing Democracy 3

The problem with games like Democracy 3, or indeed Gratuitous Space Battles, is that they are VERY hard to balance. Balancing a game is exceedingly hard, even if you agree, like me, that ‘some’ inbalance is actually what can make a game fun. (If all choices are equally effective, why pretend there is strategy to the game?). DFor big AAA studios with huge testing teams, pre-release balance is easier. For one or two man indie studios, its almost impossible to do in house.

The common solution is early-access / pre-orders with beat access, which get a lot of people to play the game. However this assumes that

a) Those players are representative in terms of skill, time, and play style to the wider public

b) You get decent feedback from all those players, not just the hardcore and

c) The feedback from the players is impartial and can be relied upon.

With a game like Democracy 3, c) is a real issue. A lot of people complain that capitalists are hard to please, but how do we know if that’s true, or if its feedback from socialist players? Anyway, as a geek, and a coder, and someone who embraces complexity, an alternative strategy of letting the game balance itself obviously appeals. So clearly, getting the game to play itself constantly and discover, then report, and maybe even auto-tweak and adjust its own rules, is the ultimate goal.

This would be an ideal ‘summer vacation’ project for me.

Actually, the bit most people are probably wary of (coding the bit where the game comes up with a strategy, plays the game and developers improvements to its play style based on the results), isn’t the bit I’m worried about coding. That bit wont be too bad (i’m not aiming for alphago levels of skill here), the bit that makes me roll my eyes and go ‘Can I be arsed?’ is the mechanics of introducing a wrapper to the game that lets it play itself. The problem here is just doing a nice, clean job of introducing such a system without breaking the game or introducing anomalies.

This is where Alphago is AMAZING, because it simply uses visual input. Frankly that ain’t gonna happen, so I’d have to embed code in there…or would I? an ideal system would be hands off, a new ‘GeneticD3.exe’ that launches D3, non invasively, makes player decisions, then handles everything without touching any D3 code directly… Surely that cannot be done?

Mwahahahaha. It possibly can…almost, because D3 is already set up to autosave each turn. And because its turn based, all the ‘decisions’ happen at once. So all I really need to do is to write code that parses the D3 save game (handily already xml), makes decisions as to what to do, runs those decisions through the D3 engine (that bit gets tricky), and then dumps out the next turns save game, repeat ad finitum. To do some rough maths, lets say saving and loading D3 takes about 2 seconds (I rule at optimizing), and we give a generous 2 seconds to make a turns decisions, thats 4 seconds a turn, 64 seconds per term in office, or a 4 term complete game in 256 seconds, so roughly 14 games per hour, or 300 games a day. Thats actually remarkable slow. If AlphaGo needed 100,000 games to learn, I’d need the best part of a year. Still, assume some cunning multithreading and optimizing (I don’t ever need to touch the disk really, all save/loads could be trapped in a RAM buffer), I could probably quadruple the speed, so 1,200 games a day?

I am seriously thinking about it. It would definitely be fun.