I’ve had problems for at least a few years when it comes to coding purely for fun. Thats not to say I do not enjoy coding, I LOVE coding, its my passion, but I made the mistake (in some ways) of turning my passion into my job, and then my career and my whole livelihood & retirement plan, and when you do that, suddenly when you are writing code you have a little voice at the back of your head saying “who is going to buy this”. And thats not a problem, in fact its a GOOD thing because it means you release commercial games and not arty self-indulgent bullshit about crying and existential angst among cartoon Bolivian hamster-weaving. Thats how I’ve stayed in business.
But the problem with working for yourself, at home, when you are the boss, is that you can work WHENEVER you like, and this means the line between working and having fun gets not some much blurred but obliterated.
If I decide to take a day off work (madness!), I really can’t go near a PC, because the PC is where I work, and my office is for work, not for fun. Its hard enough to sit here at this desk and play games instead of work, but if visual studio is open then I am IN WORK MODE. My Brain goers all serious and strategic and long term.
So I’m trying to shake myself out of that and re-discover the joy of pure creation as a hobby, as fun, as something experimental and silly, and not something that I expect to ever charge money for. I will probably never get around to achieving anything, and certainly not making anything public (unless miraculously I make something I’m not ashamed of). The main goal is going to be to learn how to code some stuff without getting all world-domination and work-ethic about it.
I know a lot of people do one-game-a-month stuff and game-jams, but thats just not my scene. I prefer to code for fun, than design for fun. Design is too intense for me. I can practically code while I’m asleep. Ask anyone whose tried to use my code :D.
I was never 100% happy with the radiation effect in Gratuitous Space Battles 2, so I’ve coded a better version for the next patch. Here it is in very short silent video form:
I thought maybe some people may be interested theoretically in how it is done. Now I’m sure if this was in 3D in unity there is already a 99c plug-in that does it without you even having to understand coding, but thats not how its done so here we go…
The first thing to remember is that the spaceship is not a 3D mesh at all. its a series of sprites rendered to different render targets and then composited. That means that I’m not wrapping a texture around a mesh, but drawing one sprite on top of another, but cropping the final output to the alpha channel of the base (ship outline) sprite.
Before I learned much about shaders, I had a system that did this using mostly fixed function, which I use here, but build on with better shaders to do more stuff, making it a hybrid approach and fairly complex :D. To simply draw one sprite on top of another, but use the alpha channel from the bottom sprite, I use a custom vertex format that has 2 sets of texture co-ordinates. One set is from the splatted image ‘radiation’ and the other is from the alpha channel of the ship outline.
It gets a bit fiddly because where I’m drawing the splat sprite could be anywhere on the ship, so I need to work out the offset and dimensions of the splat in relation to the ship image, and store that in the second set of texture UVs, and pass that into a shader.
The shader then simply reads the color data and alpha data from the radiation splat, and multiplies the alpha by the alpha at that point on the base ship texture, and voila, the image is cropped to the ship.
But thats a very simplistic explanation because there is more going on. To make things fast, all of my radiation gets drawn together (to minimize texture / render target / state change hassle), so its done towards the end of processing. In other words, there is no painters-algorithm going on and I need to check my depth buffer against this ships Z value to see if the whole splat is obscured by some nearby asteroid or debris. That requires me passing in the screen dimensions to the shader, and also setting the depth buffer as a texture that the shader can read.
So that gets us a nicely Z-cropped image that wraps around the ship at any position. It also fades in and out so we need to pass in a diffuse color for the splat sprite and calculate that too. We also have to do all this twice, once for the splat, and once for the slightly brighter and more intense lightmap version, allowing the radiation effect to slightly light up areas of the ship hull during final composition.
At this point the shader is a bit complex…and there is more…
I wanted the radiation to ‘spread’, and to do that, I need to splat the whole thing at a fixed size, but gently reveal it expanding outwards. To do this I create yet another texture (the spread mask) which also gets passed to the shader. There were various ways to achieve this next bit, but what I did was to ‘lie’ to the shader about the current UV positions when sampling this spread mask. Basically I calculate and pass in a ‘progress’ value for the spread, and I use that, inverted, to deflate the UVs of the source image (which is CLAMPed). So effectively my first UVs are -4,-4,4,4 and the spread splat is a small circle in the center of the splat, expanding outwards to full size.
Because I’m only doing this when I sample the alpha channel from the spread mask, the color and alpha data from the base ‘splat’ texture remains where it is, so it looks like its a static image being revealed by an expanding circular (but gaussian blurred) mask.
I’m pretty pleased with it. The tough bit I’ll leave for you to work out is how that works when the source radiation image is actually a texture atlas of different radiation splats :D
Gah, I spent all morning wracking my brains to fix a rendering order batching bug (fixed! yay!), and now I suddenly have a second daily headache with some SQL. If you use SQL a lot you can probably tell me how trivial this is…
Imagine a table of scores
Dave PlanetA 4,200
Mike PlanetB 2,200
Dave PlanetA 4,100
Chas Planet A, 7,200
And so on. What I am doing right now is a SELECT to get the top 20 rows from this table where the planet is (for example ) PlanetA. What I *want*n to do is to get the top 20 rows, but only the TOP entry for each player. So you only appear once in each high score list.
I can’t get my head around how to do that. I want something like SELECT * FROM scores WHERE scores.planet == ‘zog’ AND scores.score IS HIGHEST FOR score.player ORDER BY score
But of course I’ve made that syntax up and its imaginary. Albeit cool.
Tell me there is an easy way to do this thang?
And ooh guest what! Democracy 3 is the #1 strategy game on the ipad right now, due to a rather insane price drop I’m experimenting with…
Yikes,. so we had a lot of MUST FIX NOW issues in the first four days of releasing Gratuitous Space Battles 2. I think in retrospect I had bitten off a bit more than in possible for a single coder / designer to do.
GSB2 involved a phenomenal amount of re-engineering to support the kind of graphical fidelity I wanted. I sometimes read comments like ‘its just a new engine’, as though I just went into a drop-down box in unity and selected ‘new engine’, then hit the ship-it button. Arrggghhh. This new engine took well over a year of mind-mangling stress to develop. I love it, but its still hard work.
Anyway… Lesson learned #1: Multithreading increases your bug count by at least tenfold. Especially on ‘other peoples hardware’.
Lesson learned #2: Don’t do a multi-platform release. Do a Windows release. Fix everything, THEN worry about mac & Linux. Or hire another 3 or four people. Or make a much, much simpler game.
The good news is that after tracking down some pretty obscure stuff, I’ve got version 1.26 out there, and early reports suggest it is MUCH better. MUCH more stable, and a lot of silly dumb-ass mistakes by me have been fixed. The only *big* bug left is some series of actions that leads to ship designs being (temporarily) deleted until you restart the app. I reckon thats easily fixable today. Which then means I can get on with what I wanted to be doing all along: tweaking values, improving GUI elements, supporting modders, and getting a feel for what features people would like improved or added. I know people want galactic conquest put in, but thats a HUGE project, and not one for the next few months. That didn’t ship with GSB1, and that was with good reason, I assure you. Every single weapon and module from every race & expansion pack of GSB1 is in GSB2. It also has more initial missions, but even then people complain it doesn’t have enough content. Argggghhh.
Anyway, at least I can smile now for the first time in a few days. If you are enjoying the game, please leave a positive steam review. Even better, tweet about it :D.
Supporting mods is normally pretty easy, especially if you have your data left pretty open. The place it gets tricky for GSB2 is online challenges. People post their fleet to other players as a challenge, and this works great when the only content in your challenge is content you *know* the other player has on their hard drive, but the minute you allow modding it gets kinda complex.
It’s pretty late in GSB2’s development for me to realize (less than two weeks from release) that the way I was handling it was not actually working, so yesterday I had to go back to the drawing board, and I have high hopes it will be cracked by the end of the day, especially regarding the most likely form of modding, which is extra hulls, modules and ship components (visuals).
When people posted a challenge in GSB1, it was just a binary GSB file. I had a really rubbish system where the player had to tick boxes when issuing a challenge saying what extra DLC content might be included. In fairness, the game did actually check on launching a challenge and warn people if they needed extra content, but it really did kinda suck.
With GSB2 I’m improving this. I hacked the mod-content code last night so it told each piece of moddable content (module/component/hull) what mod is came with. The base game has been designated as just another mod, which makes this nice and easy. Then, when I post a challenge, the game can scan through every ships hull, module and component and make up a list of all the content packs required, which in 99% of cases will be just the base game. In then sticks that in the header file for the challenge.
Theoretically I can parse that file on the server and store it in a database, and thus show a player what content requires mods and what doesn’t. Also theoretically I can direct them to the download page for that mod. In an ideal world, I’d break mods apart automatically upon submission and handle the file delivery along with the challenge, so you would magically get any extra required content. The bandwidth requirements there might be a pain, and this is all fantasy work for after release.
But I am at least confident that I will release with a system that at least lets people put together mods, and use them within challenges without any confusion or random crashing. Worst case situation is a popup on a challenge saying “sorry, this requires the ‘l33t ship hulls mod’ and you don’t have it yet!”. That will just be phase one.
GSB2 had a superb modding scene, and I want to be supporting that in GSB2 from day one. I suspect the ship design steam workshop submission stuff will help get people interested in the mod scene better, and the integration of a mod control panel will also make mod management a lot easier.