Jump to content

- - - - -

Save Games and Goblinson Crusoe

Goblinson Crusoe isometric hex rpg turn-based
4: Adsense

There is a sort of unofficial rule about save-game functionality that I learned once, long ago, but which I still have a hard time applying: from day one of coding on your game, try to maintain the ability to save and load your game at all stages.

It's a tough rule to follow because it takes discipline and work, but it can really, really save you some effort down the road. It's a rule that, unfortunately, I haven't been following with GC. I've built some pretty complex systems and frameworks, I've fleshed out combat structures, implemented some spells and skills, but I still don't have the ability to save and load.

When prototyping a game, I have the unpleasant tendency to do lots of one-off, hand-constructed code to do things like build an enemy, build a test skill, etc... I'll construct an object and manually add components, initializing those components with hard values and magic numbers, in order to test out some aspect of the game. This tends to grow the code in a hideous, spaghetti fashion where lots of so-called temporary code infests the code-base like some kind of parasite, becoming harder and harder to eradicate.

Well, I've come to a point where I need to test some things that are getting a bit complicated, so I've decided to finally start on the saving and loading. And, as expected (and as taught to me many times in the past through bad experience) it is much harder to shoehorn saving/loading later in the process than it is to just design and build the framework from the start with saving and loading in mind. As I've pondered and thought and written pages of notes and ideas, I've come up with a plan. It's involving a relatively small yet fundamental change to the underlying component system on which the whole game hangs. It's going to take a bit of work, though.

I haven't touched the existing codebase yet; I've just forked the framework, and am testing it thoroughly before I start modifying a bunch of components.

As part of the change, though, I am redoing the way I handle engine interfacing, state management, UI, etc... So far, the component system has been strictly for game objects: mobs, triggers, player, etc... In the new system, though, everything is an object, including state context, world generators, etc...

A big part of the change has been to draw up a set of rules for creating new components, rules that have to be retroactively applied to the existing ones. This includes functionality that every component must provide: specifically, streaming. A component has to be able to load all of its data from a Lua table, and has to be able to stream all of its data and state (or, at least, what it requires to reconstruct itself) to a Lua table. This, of course, is where the discipline comes in. It's easy to just whip up a new component and toss it in, but writing the code to stream it requires a bit more work and foresight.

While I test this system and start phasing it in, I won't be adding anything new gameplay-wise to GC. I'll probably continue to tinker on the graphics a bit, but no new code until theold stuff is up to date and I have phased out all of the ugly manual constructions.

Oct 12 2012 01:32 AM
That's a good rule, wish I'd heard it before I began developing my isometric game.

I had a hard time fleshing out my save/load system when starting out. Hadn't done mush lua programming at all beforehand, I suspect you are more familiar with the language than I was/am. I ended up with a buffer containing my object tables which I saved to a binary file. It works well so far but I suspect that some holes will eventually arise.
Oct 12 2012 02:09 AM
Hehe, this seems to be a hobby project rule. I got caught in the same save-game trap (not touched the topic for years, then encountered the challenge to add save/load to an existing C++/Lua game). After all it was surprisingly easy and is stable (running now for 1-2 years). I've discussed my approach with O-san over here, providing some lua code which could be helpful. Doing this in lua is really easy, you even don't need to maintain the code because of an out-of-the-box solution which works fine for future updates. If you have an other engine part (C/C++/C#) you need to maintain the code, but from my experiences, changes in the scripting logic occurs more often.
Oct 12 2012 07:16 AM
Yeah, working in Lua is what's saving me on this one. It's nice when you can dump a save game, and have it be executable code that you can simply run to rebuild the game state. I've added version tagging to individual components, so if a component has changed since the game state was saved, it will log a warning and build the new component while attempting to reflect the old state as closely as possible. Really helps me with game versioning and keeping save files relevant across versions.

Note: GameDev.net moderates comments.