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.


  1. Thanks for the update. Don't be too hard on yourself, game development is hard. Your plan for the next few steps seems sound. Good luck!

  2. Glad to see you are still looking at this. Could be worth updating kickstarter with this blog, however I would be prepared for a bit of flak.

    Having seen a few bigger projects get bogged down I am now much more forgiving over this one.

  3. Good to hear. The theme I'm hearing is simplification. This is good! Alternate between expansion (adding new ideas, new complexity, new features, exploring) and contraction (removing things that are lots of work for little reward). Dan Cook calls this the culling phase.

    1. Yes, tile based simplifies things. I'm leaning this way too for my current project.

    2. One way to look at it is that you can get a lot of interesting behaviors by combining a fixed number of parts. Consider the number of words you can build with the alphabet, or the number of sentences you can build with words. You don't need to be able to generate new random letters in order for the words to be interesting. Making a few substance types will be your alphabet; there can be plenty of interesting words to make out of them.

    3. It varies a lot, based on the type of game. Sometimes the randomness leads to worlds that are un-fun; sometimes the constraints on randomness leads to worlds that are boring. It's hard to know until you try, and you tried, so that's good :)

    4. When the game world is so large that you can't simulate it, you also have to wonder, is it so large that the player can't see everything that's going on? If the player can't see the effects, it may not be that interesting to simulate. A smaller world sounds like a good plan.

    5. Simulation is one of those things where a C module for Python might be useful. However, this is also one of those places where you might want to simplify even further.

    It's usually better to get something simpler working and then add features than to not have it working until you have those features. I find the best way to do this is to simplify, simplify, simplify. In the startup world it's called "minimum viable product". Good luck with the updated design!