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

Programming RTS Unit selection outlines

Programming RTS Unit selection outlines is a pain. I had an amazing GUI mocked up by an artist, and most of it is now in Gratuitous Tank Battles, but today’s todo list included unit selection outlines. He had mocked up this:

And now I want to batter him with a baseball bat.

(I always tell artists to do the best stuff they can possibly imagine, and let me worry about how I’ll make it work. Reach for the stars etc…)

You might think it’s easy. Just draw the image bigger first, with a flat shaded effect (I use render states, but YMMV), and then draw the unit on top. WRONG!

Firstly, that means your UI doesn’t shine through smoke or other effects layered on top, which isn’t as cool. Secondly. it means the units shadows are cast onto its own selection UI (yuck) thirdly, it just plain doesn’t work.  It works with squares or circles or other basic shapes, but take a complex image, scale it up, then draw the smaller image inside it. See what I mean?

What I really need is some way of doing what photoshop calls the ‘stroke’ effect, where the outline of an image is expanded. Not expanded directly from the image center, but expanded in all directions.

One solution mentioned online is to draw the flat-shaded bit (enlarged selection) 4 times, moving it up down left and right by 1 pixel each time. That’s great if you want a 1 pixel outline, but 1 pixel sucks, and beyond that, you will get corner issues, plus… 4x rendering potentially every unit in your army every frame is not nice.

Another solution would be to have extra versions of each sprite, already-scaled up in photoshop, and render them for the enlarged versions instead. This has issues where the image already touches the sprite corners, and in any case, that means that the selection outline is a fixed percentage of the unit size, rather than a uniform 4 or 8 pixels, which would look tons sweeter.

So… how did I fix it?

I haven’t yet… It’s driving me bonkers :( I am considering an offscreen render target that blurs a matted sprite, but that wouldn’t be crisp, which I think would look better. I wonder how they did those outlines in age of empires 2?

Note, almost all discussions online about this refer to 3d meshes. I use 2d sprites with alpha channels. Totally different :(

 

edit: this is what I have so far, quite like it, may compromise on it…

Cross platform angst and my hatred of middleware.

I do not have cross platform capability. if you play my games on linux, it’s through WINE, and if you play them on Mac, they were ported by a third party company. In the long run, this is likely to be a business weakness of mine. The ipad is great, and I can see it’s a huge market. Inexplicably, people seem to want to play games on phones, and with Microsoft making it more and more difficult to let people just download an exe from the internet, and the dominance of portals online approaching 100%, a move towards html5 or php / flash games seems like a sensible move in the long term.

Of course, people say that the down-loadable PC market is huge and not to worry, but I’m thinking 10,15 years ahead. if I’m still in PC gaming in 15 years, I need to think on those sorts of timescales. (I’ve been reading lots of warren buffet, it’s affecting me :D)

I recently checked out unity, because a top-secret-side-project-i-wont-discuss-yet is being developed in unity, and I’ve never even seen it. I was immediately put off. I can see how for many developers, unity is AWESOME. It certainly provides a ton of tools, functionality and easy-to-use stuff. It seems a lot of the fiddly, hard work has been done for you.

The problem is, I just HATE middleware. I don’t like the way other people code (as a rule, ancient-james excepted), I hate it when documentation says “you can ignore this coding concern, we handle it under the scenes” and I fear black-box code which promises to be ‘optimised’ but doesn’t tell you how, or with what assumptions.

I hate the fear that a bug will crop up after I ship, and not only can I not find it, I can’t fix it even if I could. That sucks big time. It’s rare, but not unknown. Plus I fear that ALL middleware has been built with certain limitations, and certain assumptions. Make no mistake, Unity is designed for 3D real time games. It might be ok to make a 2D turn based game in it, but you will be fighting against the tide, not with it, and carrying a lot of 3D engine bloat with you.

I celebrate the existence of unity for making many devs lives easier, but so far (I may be converted), it really isn’t for me. I like to code from the ground up, with complete control of everything. I’m a guy who uses char* and fopen(). By 2025 I might have moved entirely to std::string and CreateFile, but don’t hold your breath. Also, there is an element of ‘if it ain’t broke…’. I’ve made quite a few games with my own engine, so maybe I should build upon that, not throw it away in favor of someone else’s code?

A decision for after GTB ships, methinks.

 

Handy optimising tip

If you have a profiler like aqtime that can be remotely enabled and disabled try this.

  1. Have a flag that is ‘bprofileframe’ and set it to false by default
  2. Bind a keystroke to a function that toggles the flag on
  3. In your render loop, before rendering, if the flag is true, enable debugging
  4. At the end of the render loop, if the flag is true, set false, and disable debugging.

Voila! you have a keystroke that will capture a single frames profiling data and ONLY that frame, making for really easy profiling on very specific situations. Works a treat. Now I just need to work out how to make it all faster :D

Deferred Rendering / lighting. Balls, maybe not

For a while I’ve been thinking about putting deferred lighting with normal maps into GTB. This was something I talked about briefly during the development of GSB but it never happened. it basically a way to ‘fake’ the 3D lighting effect with a 2D image, *if* you have the original 3D model the  2D image came from, and thus can make a ‘normal map’.

Here is what I mean:

http://experimentalized.blogspot.com/2010/07/2d-deferred-normal-lighting.html

This stuff is definitely not my area of expertise, and to confound the problem, all of the tutorials and explanations of the effect seems to concentrate on XNA or doing it with actual 3D scenes, whereas mine is a 2D engine.

Plus, it seems that it doesn’t do what i wanted it to, which is to take a lightmap full of various light sources (image the whole scene, with just the ‘light’ rendered onto it), and convert that into realistic looking shadows on 2D sprites. it appears to be a single-light source only solution, involving pixel shaders. Bah.

As I type this, I wonder out loud if bump maps are the answer to my problem? It’s not a disaster if there isn’t a solution, as GSB looked fairly pretty, but I’d like to take things up a level with GTB. There is only so far you can go with 2D top-down view rendered stuff, but I’d like to be the prettiest, shiniest 2D game of it’s type, if at all possible. The other effect I tried once but wimped out of was those distortion-map effects where you get a sphere that distorts the pixels accross it, and thus get a ‘shockwave-air-blast’ style effect. I think Call of Duty 4 used it a lot. I ran into ‘tearing’ and other bugs and eventually abandoned it in a strop :D

Anyone got any tips for fairly awesome 2D top-down effects in games?

(The minute I have my logo finished I’ll talk about GTB)

 

Optimising my ‘dumb’ textures

I have this class in my code called ‘smart texture’. I’ve had it for several games now. It basically lets me tell a sprite to use “gun.dds”, and it transparently converts that to the LPDIRECT3DTEXTURE9  and doesn’t mention it. It keeps ‘gun.dds’ in memory, and if I ever lose the screen (alt+tab), and need to rebuild stuff, it will replace the invalid surface pointer the next time it gets drawn with a fresh copy.

MAGIC.

Trouble is, that means keeping a list of every smart texture, so that I don’t miss any when recovering from alt+tab. That’s easy, but I ended up using texturedsprites (with a built-in smart texture) everywhere, and thus the list, for a full battle could be 20,000 textures long.

F**k.

So here I am, effectively keeping a record of me trying to fix this…

It’s 5.35PM Sunday. The wonders of aqtime show me that when I ditch the current level and load in a new one, I am killing off about 8,000 smart textures. Every one is going through it’s destructor and removing itself from the smart textured list. This sucks. I need this to be faster. First instinct is to speed up the destructor, but obviously that’s treating the symptom, not the cause. The real problem is 8,000 smart textures. That isn’t so smart, when 2,000 of them are probably pointing to the exact SAME surface in directx… I need to rethink this system, and NOT break any other code…

I *do* have a system called GUI_TextureCache which does some ‘fixed’ storing of textures I use all the time, like UI stuff, buttons etc. This is obviously a similar task to what I want to do here, in that I need a dynamic dumping ground for commonly used textures pointers. I’m concluding that the cleanest way to handle a fix would be within my SmartTexture itself. it can do some clever caching, and then nobody will ever know any code changed!

Realisation that this means I still keep all these smart textures knocking about, with their ‘gun.dds’ strings. That offends me, as a programmer, but tbh, even ‘longcomplextexturefilename.dds’ is only 30 characters, so with 2,000 units I’m wasting 60k here. Big deal.

Right, so the plan is when I call SmartTexture::SetTexture(“gun.dds”) it may, or may not add itself to a list of textures that would need rebuilding, based on if its already in the list.

Problem: I can’t do that, because it means checking the whole list every time I call SetTexture(). That might even be *slower*. However, my current ‘SetTexture’ goes through a list to grab the pointer, how slow is that? It looks like currently its about half as much time as all those smarttexture destructors, so it might be a win. Plus my SetTexture() stuff uses a MRU caching system which could make ti super fast when loading in 100 identical units…

5.50PM Actually realising I’ll need a totally new class to handle this. it needs to be done a different way, not with existing smart textures. Balls. Surely it can be done? Hold on.. Surely its just a matter of indirection. The purpose of a smart texture is to hold a surface pointer it can rebuild if needed, but it doesn’t have to hold a direct link. It could actually hold an indirect link.  One more piece of pointer indirection is trivial. I just add a new CLoadedTexture class that handles rebuilds, and the smarttextures can point at those, meaning no need to keep a list of them at all, as their pointers never go invalid or need rebuilding.

6.25PM everything coded except the actual rebuild() calls for alt+tab. I’ll comment the errors out for a quick test… GAH, it crashes immediately. fixed easily enoguh, and the code RUNS! hurrah, but it doesn’t seem AMAZINGLY faster,. Quick! to aqtime! what the hell… it’s slower?…

6.35OM. Hah! looking at it backwards, it’s about 75% faster. how much time does that knock off loading in a new level now? 5.28 seconds down to 2.1 seconds. That’s pretty good. I’ll code in the rebuilding stuff and give it a quick test…

6.50PM Alt+tab doesnt work, I get just a black window, but that may be something else. I’ve checked in my current code, and am investigating alt+tab issues now. It looks like the restore code hasn’t worked on this new game at all yet. I consider my (dumb) smart texture code fixed :D