Friday, March 29, 2013

Design realignments

I've been thinking hard about the future of the project and the best way to go from here.

1. I'm more and more convinced a platformer, or at least not the style the engine currently runs, is not the way to go.  The thing is that the cellular engine can change the world, from turn to turn, in ways that it's not simple for a real-time platforming engine to overcome, at least not one developed by a single guy.

Solution: Go with something more tile-based.  Not abandoning the real-time aspects, but instead of worrying about subpixel-level movement accuracy, instead have the player move from cell to cell.  That doesn't mean it would look exactly like a roguelike, we can have intra-cell animations, but under the hood movement will be discrete, one block at a time.  And by not trying to be an action game, the framerate consistency problems, searching for a solution to which having been the secondary cause of the development delays (the primary one being having to keep myself fed and clothed -- I live well beneath the poverty line) are no longer a problem.

2. The high-degree of substance property randomization isn't as interesting as I thought it would be, and the code is a snarl in any case and difficult to maintain.

Solution: Ditch the lot of that and simulate, for the most part, a number of preset, interesting substance types, that each might have zero or one special properties.  There are too many substances that it's just plain out useful to have around for gameplay purposes: water for swimming, sand for piling up, oil for burning, and so forth.  There are reasons World Of Sand games always tend to simulate those basics.

3. The game world generator doesn't produce interesting spaces to explore.  Oddly, the nearly completely random world builder that I had in the earlier versions made much more interesting terrain than the current maze builder algorithm.  This is actually a case where more randomness is more fun than less.

4. The game world is so large that we can't simulate the whole thing easily, which makes large-scale structures (such as flowing rivers) difficult or impossible to do accurately.

Solution: Try simulating a smaller world.  Also, I've come to realize that 8 levels of fluid in each cell is almost certainly too many.  We could get away with 4 or even 2 levels, and the result would be far less calculation.

5. There is still work to be done towards optimizing the cellular engine.

Solution: There are four possible approaches to the engine, which I've tried to different degrees over time:
A. The one that I've been using the most lately uses a "spiral" scheduling system; cells are calculated going in a square-cornered spiral around the current view focus (either the player or the cursor).  Advantage: if we want to calculate fewer or more cells due to real-time requirements, we can just stop whenever we want.  Disadvanges: iteration overhead, if we're not trying to be an action game, unnecessary, and iterates over every (well, every other) in its region regardless of need.
B. The obvious alternative is a rectangular region around the focus.  Advantage: the sim
plest scheduling system, so the least overhead.  Disadvantage: Iterates over every cell in region regardless of need.  If there's nothing in a cell it moves on fairly quickly, but it's still a matter of concern.
C. Use a list of "dirty" cells, compiled as the previous frame is worked on, and only calculate those spaces.  Advantages: We can calculate much more of the world each turn within the same period of time.  Disadvantages: More complex, and thus more fragile.  This is one of the reasons I moved away from this approach before since the increase in complexity wasn't matched by the performance gains.  With a smaller world, however, we might be able to use this approach to simulate the whole world... making the large-scale structures I really want to implement possible.  I think this is the most promising avenue.  Since we're using random world building, instead of one gigantic world we could instead explore a series of smaller worlds.
D. Use the weird column-based "sort" I've been working on and wrote about in the past few posts.  I think it might be viable eventually... but it is a weird thing, it's good for moving fluids vertically quickly, but we still have to iterate through those cells anyway to handle side-to-side fluid movement.  And it's so weird that I think it'll also be even more fragile, that is, vulnerable to being broken by other engine changes, than the dirty cell list system.  So I'm not using this technique for this project, it might be an interesting experiment some other time but now isn't the time for that.

Tonight I went into the code and switched it from the spiral turn scheduler to a rectangular field one.  I also tried running the game with a smaller world, and it seems to work okay if I make sector sizes smaller.  If I make fewer sectors I get an error, but so it goes.  It'll get fixed, and so will the next one, and the one after than.  Until it's done.

It's nice to think it'll be done.  You've all been waiting all this time.  I've been laboring under this weight, this sword of Damocles, for two years now.  I don't ask for pity or for forgiveness -- I'm not sure I deserve either.  I just say, I have not forgotten it over all this time.  I have never considered abandoning the project, for even a second, and I'm not going to abandon it now.  When I make a promise to do something, I get it done, even if it takes a while.  If you thought to yourself "sure, we've heard that before," I wouldn't blame you in the least.  I'm still trying to think of this in constructive ways, though.

Well, that's where we are.  Next up: getting the smaller world size to work, derandomizing the substance properties, and designing a better world generator.