Update: I've been reworking the resource management in the moonman engine, essentially implementing the system used in the bitsquid engine described
here.
I'm changing all of the resource specifications from Lua to
Simplified JSON. Currently sprite are defined in Lua files (I can have multiple definitions per file) and looks something like this:
// file potions.lua
sprite {
name = "potion1",
sprite_sheet = "entities/items/potion_sheet.png",
width = 8,
height = 8,
frame = {x=0,y=0}
}
sprite {
name = "potion2",
...
}
I then just execute this file with the Lua interpreter, and the function
sprite gets called twice, with the Lua table {...} as the single parameter.
This is really cool, but it has its drawbacks:
1. The mapping between resource and file is not necessarily one-to-one (which complicates hotloading the resource)
2. Any Lua code can appear in there -- for simple resources like a sprite definition this is actually bad, as it makes the sprite definition format harder to process by external tools or to automatically generate.
So, I've decided to:
1. separate the
passive resources (sprite definitions, shaders, block definitions, text files, gui settings, etc..) from the
active resources (Lua scripts).
2. make a one-to-one mapping between resource and file
3. use a consistent naming convention
So now the two potions above will be defined like this:
// file entities/items/potion1.sprite
sprite_sheet = "(sprite_sheets/potions,png") // (name,type)
width = 8
height = 8
frame = {x=0,y=0}
// file entities/items/potion2.sprite
...
Note that the name of the resource is simply its (relative) filename minus extension, e.g., for potion 1:
entities/item/potion1 is the name, and
sprite the type. Also, resource references in scripts are always of the form "(name,type)". This is a little bit peculiar, but allows simple tools to be written to easily process dependencies.
I'm also refactoring the resource management. At the moment I have something like this:
template <class T>
class ResourceManager {
public:
T* get(std::string name);
virtual T* load(std::string filename) = 0; // Given a filename, return a loaded T*
protected:
// string->T* map
};
class ImageManager: public ResourceManager<Image> {
...
};
class SpriteManager: public ResourceManager<Sprite> {
...
};
.. etc ..
Unfortunately having all those managers in the system makes it more complicated, and so I am centralising all the resource management back into a single
ResourceManager. The resource manager is fairly simple, it just stores a map from
(name,type)->void*, effectively being a dumb database. Loading of resources is done through callbacks
for each resource type. E.g.,
void* load(std::string filename), is called when loading a resource, and different
load functions are registered for the different resource types. (I'm also murmur hashing the names into 32bit IDs for efficiency.)
I've wanted moonman to be easily moddable from the start, and this is how I plan on supporting that: Resources are grouped into packages (a folder with a file
package.sjson inside). The core game is a package, as are any mods. The active mods are just listed in a file
mods.sjson, in the order in which to load them (in case there are dependencies between mods.) Even the core game folder can be copied, modified, and then referenced in the mod list (in which case its a
total mod).
One last thing I want to mention is that the bitsquid tech has three stages in its resource management pipeline, artist stage -> intermediate stage -> compiled stage. Currently moonman just has the
intermediate stage, i.e., there are no tools for making content and there is no efficient binary format for compressing the data. Due to the nature of this game, I don't know if I will need those other stages. The data seems to load quickly enough from the intermediate format to make implementing a compressed format unnecessary. And I've currently been specifying the data by hand, writing the lua/sjson specs myself -- so at this stage it seems unlikely that I'll need to make special tools for creating the data, or write converters for existing tools. Though I guess this depends on the eventual complexity of assets: the sprite animations, particle effects, etc (which I hope are very simple, givenb my intended aesthetic for mm.)
Well, that was a long post.
Now ... back to Crystal Cave ...