logo

Gratuitous Space Battles 2 is approaching pre-orders + beta. You know the sort of thing by now. The game isn’t finished but you can pre-order now and get immediate access to the beta. Steam early access made it popular. So why not put the game into Early Access? basically this isn’t an early-access kind of beta. It’s a proper ‘we think it’s more or less done’ beta, like betas used to be back in the old days. It’s pretty much content complete (a few more extra graphics & voiceover await). It’s definitely feature complete. It’s definitely playable. it has been optimized a lot, and bug tested a lot. It’s essentially what my idea of a beta is, which is a finished game, with some rough edges, and maybe some compatibility issues. There are a few big things not done, namely translations and ports. The beta will be PC only, and English only. I plan on a Windows/Mac/Linux  and English/French/German/Spanish (maybe more) release when the game actually gets released on steam, Humble Store, GoG.

screnn1

So the beta will be direct-sales only, and will get you a download link & online challenge game serial (no DRM, don’t worry), and a steam key that will be useless until release.

So thats all the warnings and caveats. What will you get? You will get a VERY explodey, lasery, space-battley smorgasbord of laser-death and gratuitous zappyness that makes the battle at the start of the last star wars film look like an episode of Blakes Seven. I’ve kind of gone a bit overboard of the graphical shininess this time. I might have overdone the lens flares a bit, and the particles, and the everything else. And yup, the multi monitor stuff works fine in the beta.

wide

Gameplay wise, it’s Gratuitous Space Battles, but with more ship classes (hello dreadnoughts, destroyers and gunships) and better formation orders, better targeting AI, and *drumroll*… You get to design the ships yourself from components, so they look exactly how you want them. This is I suspect…a bit of a killer feature. It is VERY cool, to design a whole fleet of spaceships then watch them blow up your friends fleet.

So yup, it should be a lot of fun. It’s tons better than GSB1. I can’t believe how GSB1 looks and feels and plays now, this new version is basically laughing at it, like kirk laughed at khans superior intelligence.

Anyway…stay tuned. beta SOON.

Background: I use directx9 to develop Gratuitous Space Battles 2 using my own engine.

I’ve been doing my best to reduce the number of draw calls per frame for complex scenes in GSB2. Basically I have a lot of stuff with different textures and render states, and they are being drawn from front to back rather than z-buffer sorted (for reasons concerning sprites & high quality alpha blended edges).  What this means is, when you have 16 identical laser beam turrets, you may not be able to draw them as a single batch, because in-between them you might be drawing other stuff. As a result you get 16 draws instead of one. Ouch. That causes driver slowdown, directx slowdown, and inefficiency on the GPU, which prefers big batches.

Of course you can immediately see that it would be fine to go through the draw list (one of several actually, for composition reasons), and spot all those cases where you have 2 or more turrets (or any sprite) that use the same texture and which do NOT have anything in between them that overlaps the first one, and grab that second turret and draw it ‘early’ with the other one. And in fact, that works just fine. suddenly lots of draw calls get optimized away! (the green ones) In this case out  1,159 draw calls 713 get optimized away into batches.

megabatchedThere is an immediate problem though. This is extremely slow, even with every optimization trick in the book. Assume you have a list of 1,000 objects to draw (not inconceivable for big battles). In the worst case situation, that means comparing object 1 to 999 different others and doing a bounds check. Then object 2 gets compared to 998, then 3 to 997, and so on. That is a LOT of function calls (inlineable I know…), and a lot of bounding box comparisons, and a lot of texture comparisons (only a pointer compare, but I need to extract that texture pointer from each renderable object, and at 500,000 de-references per frame even that adds up.

Now granted this is all total worst case. Some of those 1,000 objects aren’t batchable, some of them *will* quit early as something overlaps, and when I do batch future ones with early ones, those future ones themselves don’t need to be checked as they have been optimized away.

The trouble is, after profiling, it is still about 70% slower for the CPU to do this, than not do it. The big problem here is that I’m making stuff light for the GPU, heavy on the CPU. Is that a good idea? maybe… But as it happens, if I assumed a dual core (or better) PC, it doesn’t matter because it is FREE. I have other threads just sat there. If I find a slot in my main loop between building the draw list and having to actually render from it, I can multi-thread that new slower batching code and actually have the whole app run faster, thanks to less draw calls later on. The Visual C++ concurrency profiler shows it works: (Click to enlarge)

visual_c++_concurrency_game

Previously I’d have gone through and built up the draw list (thats the blue), then done some particle drawing preparation(green), then batched my draw calls (purple) and then drawn everything (yellow). Because the particle stuff actually gets put into a different list, I can mess around with my slow batching in a new thread while the main thread prepares particle stuff. Hence the purple bar is now on a new thread and works alongside the main one. As it happens I also have 2 more threads doing some particle emitter stuff at the same time as well, so briefly I’m at 100% utilization on 4 threads, possibly 4 cores (other processes such as the music streaming/driver might be on one of them).

So in a sense, yay! faster code, but what a nightmare to measure. It depends on scene complexity, relative CPU/GPU speed, number of cores and god knows what else. However it is worth remembering that sometimes slower code will make your game run faster, it just depends where that slow code runs.

Gratuitous Space Battles was a relatively big hit game (at least for positech), but it managed it despite some hilariously bad decisions. The lack of any decent explanation of how the core game mechanics work has to be one of them… For example the whole thing where some beam lasers bounced off shields, and some did damage, and you had no idea how or why probably upset some people. It was all explained in the manual, which obviously nobody read, because it looked like an RTS or an arcade game and thus such things aren’t necessary…bah.

The mechanics in GSB2 are slightly different, in that weapons have a fixed ‘damage’ but the effectiveness of that damage varies by hull/armor/shield. So a weapon might do 100 damage, at 50% if it goes straight to hull, 75% to armor, and 200% to shields. That makes it an awesome shield-hammering weapon, but not one you’d want to deliver the killer blow.

At least now a new part of the pop-up tutorial stuff does this:

shields

Which should at least mean a higher percentage of people pay attention to that stuff. Now I think about it, I should probably add some code that encourages weapons to select targets based on their effectiveness. ARGHHHHH.

 

Want to see a GRATUITOUS graph of some sales stats for one of my games? I bet you do. People love info-graphics, especially those really long vertical things with lots of numbers. I’m not going to do one of those, but I will present to you for your delight the following sales graph showing two weeks of income on an un-named website…

graph1

If you sell games online, you may well have seen similar looking graphs when looking at your own data. The thing is, just staring at a graph doesn’t help you much unless you can tie it in to the events that have influenced that data. After all, people like me are always talking about return on investment, marketing, publicity, and how to get attention, and how to convert visitors into buyers and all that kind of stuff. In other words, sales data is USELESS. What you need is sales data with context. So lets add that in the version below…

graph2Now this is actually something useful, because we can use the sales data, in combination with our recent marketing efforts to deduce what is working, what is not, and how best to approach marketing and business stuff as we continue to promote and sell this indie game. You can tell immediately that the blog post where we mentioned the game resulted in a notable spike in sales, that the ad campaign had a big, but very short-lived boost, and that a new lets play that someone did had actually only a pretty small impact on our sales, ditto a new steam curator that listed the game.

From this we conclude that we should put more effort into blogging, probably keep up the ad spending, but not be too bothered about encouraging lets plays and steam curators, as they have less of an impact on our bottom line.

Except no, hold on.

That’s all bullshit.

Lets look at the real graph, through the lens of realizing that the top point on those spikes was about $1k a day, and that the game has been out a while now. We could zoom out and look not at two weeks data, but at a years data, and then with that context taken into account we can re-formulate the data for those two weeks as follows:

scroll down…

… keep going

graph3

Basically fuck-all happened in those two weeks. Did I blog about the game? Probably. Did we get a new lets play. Maybe. Did we get some new steam curators. I think we might of, I’m really not sure. But regardless what happened, it made absolutely sod all difference to our sales.

Do not fall into the trap of over-extrapolating information from noise. It is VERY VERY tempting to do so, especially when you are a new developer because you desperately want to know how sales for your game will be, and you desperately want them to be good. The problem is, as a new developer your ability to analyze this data is very very low, simply because (unless you made banished) your sales are likely, with your first game, to be low enough that any change in them is statistically irrelevant.

If you sell 5 games a week, and then suddenly one week you sell 7, thats a huge percentage boost in sales. Sales have SKYROCKETED. Sales are ‘up in a big way’. There has been a ‘boost’ in sales! But really there has not. Really, one of the people who bought last week told 2 of his friends how good the game was. This is a trivial thing you cannot analyze and cannot benefit from analyzing.

If you sell 5,000 games a week, and then suddenly sell 7,000 that IS actually significant, despite being exactly the same variation. You absolutely should draw conclusions from it.

That seems counter-intuitive, so keep re-reading it. The margin of error is basically lower with a big sample size. This is why pollsters try to have a decent sample size, so one or two outliers don’t skew the result. In our 5 sales example, we lucked out and one of the 5 had lots of similarly minded gamer friends. The thing is, we could have gone entirely the other way, we might havebeen unlucky, and sold to 5 people with even less friends than normal, and this might actual dent the next days sales as our ‘virality’ collapses. A single customers sociability can skew our popularity up or down hugely.

With 5,000 customers, we are going to get lots of sociable customers, AND lost of unsociable ones. They cancel each other out, and we get a steady stream of recommendations, and non-recommendations. Unless one of the buyers is notch or stephen fry, them tweeting about our cool game will make zero difference, in the grand scheme of things.

The vast majority of indie game post-mortems over analyze events in their sales curve. It’s absolutely worth reading them for the ‘we made a game about chickens and it was a hit’ or ‘we made a mobile game and then we ended up living off noodles’. That’s ‘big picture’ stuff. But buying an advert or releasing a  trailer and seeing your sales go from 5 to 7, or 7 to 5, is a total irrelevance. Ignore it.

Tell me if I’m wrong :D