Loading sprites, I want an easy way to make them non-hardcoded later

This topic is 2801 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Working on a new game, I need to start loading sprites from PNG files. The loading process in itself is the easy part, the problem is, believe it or not, the filenames. Since I just want to start I'm going to hardcode them for now, but I want to make it relatively easy to change it if I get time later to read the sprite list from a file instead (probably from the animation files).

So, what are your suggestions? I'm just looking for algorithms/ideas, not specific implementations.

Share on other sites
What I do is use xml to lay out my sprites, something like this:
 <Sprites> <Sprite Name="Hero" Filename="HeroFilename.png" /> <Sprite Name="Enemy" Filename="EnemyFilename.png" /> </Sprites> 

 Sprite *HeroSprite = LoadSprite("Hero"); 
I use tinyxml for my xml parsing
You can do something similar with animation as well.

Share on other sites
I usually just hardcode all of my image paths in my content loader. Alternatively, I may also use XML.

Another idea is to use file system libraries to get a list of all the files in a directory. If you know that all of the files in your directory are going to be PNG files, then you can attempt to load them into memory (use try/catch blocks in case you hit a non-image file). Then, the only challenge is to associate a game object with an image file name...

Share on other sites

Working on a new game, I need to start loading sprites from PNG files. The loading process in itself is the easy part, the problem is, believe it or not, the filenames.
...
So, what are your suggestions? I'm just looking for algorithms/ideas, not specific implementations.

I assume you have a [font=courier new,courier,monospace]LoadSprite(String resourceName)[/font] function. If you have, a good part of your code is possibly ready to go. If you don't, that's your first step.
Then there's the need to make this data-driven. It is more complex than it seems at first glance.

1. Where do you plan to store the file names? Animation files might contain them, as you write. I have resources referred all around, from the world description, the scripts, some get loaded as a byproduct of loading another resource... some even as a byproduct of error handling (I consider this extremely brittle). For each source, you'll need to focus and figure out what you want to allow it to load and then specify its format. Don't even try to mess up with the strings: just use (numChars,chars[]) pairs if you're using a constant-length encoding or (numBytes, bytes[]) for variable length.
2. What are the file names? In my case, I mandated each resource to be located in a specific directory so scripts get loaded from "Content\Programs", levels from "Content\World" etc... I even plan to deploy some more involved path validation to strictly enforce this.
3. More subtle stuff such as: is loading "atomic"? If multiple resources are referred from a source asset, are they loaded in the specified order? What about aliasing rules? Do I want to support resource remapping/substitution? Do I want to allow loading by checksum?

In line of concept at this point we have a function which can load arbitrary stuff and a set of resources which want to be able to load this stuff!
So we "just" need to connect them.
This is no easy task in some cases. Loading a mesh for example involves multiple subsystems: rendering, collision detection, perhaps scripting.

I suggest JSON. XML is possibly "better" somehow but I'm unsure it's worth it.

Share on other sites
Oi, I just want something that works for now but won't require me to rewrite everything from scratch when I'm ready to move everything into separate files. That's something that will take a while.

Also just so you know: all sprites are in a "graphics" directory. Inside it there are several subdirectories, e.g. "player", "enemies", "level_harbor", "level_factory", etc. The game will just check which subdirectories needs for a given level, check the valid sprite files in it and load them all. It won't attempt to be smarter than that (sprites are quite small anyway, I can afford to load all that, and custom user levels may demand loading all the resources in a directory anyways).

To make a quick example of the above: for e.g. a factory themed level it may load all the sprites in "graphics/player", "graphics/enemies", "graphics/objects" and "graphics/level_factory" (in fact, the only level-specific directory is the last one, which changes based on the level theme).

(use try/catch blocks in case you hit a non-image file)

I'll just make the loader ignore those files. If an animation attempts to use a non-loaded sprite then it will throw an error.

Also not all the files are PNG files. The animation files will go there too (those are text files). And I expect some dumb user to put completely irrelevant files in those directories if they go to that extent in modding the game.

I assume you have a [font=courier new,courier,monospace]LoadSprite(String resourceName)[/font] function. If you have, a good part of your code is possibly ready to go. If you don't, that's your first step.

I don't, that's why I posted this, I don't want having to change all the code around because I need to modify the function prototypes or something =P

Loading the PNG files will be easy though, since I actually have PNG loading code from something else I made before. In fact, it will be simpler this time since I don't need to keep palette information at all (the game only renders in true color). I also have sprite code working already (made some tests using a procedurally generated sprite). It's this whole filename shenanigans what's holding me back.

Where do you plan to store the file names? Animation files might contain them, as you write.

Pretty much this, I guess. Actually, since all the sprites from a directory are loaded, animation files would literally be used for just getting the sprite by its name (OK, error checking, etc., you get my point).

What are the file names? In my case, I mandated each resource to be located in a specific directory so scripts get loaded from "Content\Programs", levels from "Content\World" etc... I even plan to deploy some more involved path validation to strictly enforce this.

Already mentioned this before. In fact, there are even more strict rules (i.e. filenames can only contain alphanumeric characters and underscores (no spaces!), and must end in ".png" extension - this is so it doesn't mess with the animation scripts later)

If multiple resources are referred from a source asset, are they loaded in the specified order?

Sprites are loaded first, then the relevant animations. Not much else to say...

I suggest JSON. XML is possibly "better" somehow but I'm unsure it's worth it.

Animations are going to have a format like this (example snippet):
 idle - idle_1 16 39 8 - idle_2 16 39 8 - idle_3 16 39 8 - idle_2 16 39 8 crouch - crouch_1 16 39 4 - crouch_2 16 31 4 - crouch_3 16 31 forever 
(the lines without a dash indicate the animation name, while the lines starting with a dash are the frames, containing sprite name, X and Y offsets and how long to show them - and before you ask about potential issues with filenames, there are restrictions on them too to be considered valid sprites, see above)

So, I was thinking on this:

• Pass a string to the sprite manager with the name of a directory and have it load all sprites in it. Function returns some sort of handle that identifies the directory (to reduce time spent in string comparisons).
• When parsing the animations, have a function that takes the directory handle and the name of the sprite and returns a pointer to the sprite.
• The sprite manager can be told to unload all sprites with just a single call, since it knows the location of all the sprites in memory. This will save lots of time in the long term.

Share on other sites

[quote name='Krohm' timestamp='1329643802' post='4914463']What are the file names? In my case, I mandated each resource to be located in a specific directory so scripts get loaded from "Content\Programs", levels from "Content\World" etc... I even plan to deploy some more involved path validation to strictly enforce this.

Already mentioned this before. In fact, there are even more strict rules (i.e. filenames can only contain alphanumeric characters and underscores (no spaces!), and must end in ".png" extension - this is so it doesn't mess with the animation scripts later)
[/quote]Perhaps it is only personal opinion but since you mention modding, I'd say you need to allow spaces. What's the problem with them?

Example JSON script (I'm not 100% sure the syntax is actually correct but you get the look and feel).
 { "anim" { "name" : "crouch" "frames" : [ [16, 39, 4], [ 16, 31, 4], [16, 31, forever] ] } } 
I'm not saying you should use JSON. Or YAML. Or XML. Just think at it.

I still have some difficulty in understanding why you keep thinking in terms of directories but then you clearly note sprite names are required to be somehow resolved. I'd personally just drop this whole directory thing, perhaps I have not understood the whole point in using them.
As a last note, it is unclear to me what you're expecting from saving "lots of time in the long term" when unloading assets. I always assumed this was 101 of every content management system.

Share on other sites

Oi, I just want something that works for now but won't require me to rewrite everything from scratch when I'm ready to move everything into separate files. That's something that will take a while.

I am just wondering exactly what it is you feel you would end up rewriting should you hard-code image file names within loading routines.

I often (well not recently) go on dates and usually my dates ask my job, to which I reply that I make game engines.
Usually my dates don’t know what a “game engine” is, and I explain it thus (intended for the most laymen of laymens):
“The game engine knows how to load and use data, but not which data to load and use. The game is then built by telling the game engine which data to load/use.”

The file names of images you plan to load for usage as sprites is something that definitely falls under the “game” side of things rather than the “game engine” side of things.
The “game” side is not meant to be reused.

So if your game engine supports loading a sprite given whatever file name you provide it, I am not sure exactly why you are concerned with this. What exactly do you think you will be rewriting in the future should you hard-code paths now? Your next game will have a totally new set of paths, so there isn’t much point in a system that “re-uses paths that would have otherwise been hard-coded.”

That being said, I am not against some kind of system that abstracts away the fact that a game-specific path is being used.
But:
#1: That would apply to anything, not just sprites.
#2: Aside from enforcing a bunch of rules within your engine, such as, “The image shown on the title must be named this,” etc., the system for abstracting this all away would be so generalized it would defeat the purpose of avoiding hard-coded paths.

I get the feeling you are not asking the right question.
The above (posts prior to mine) advice could be used to easily associate data (including animation data) with image paths, but those paths are still hard-coded, just in a different place.

So what is the real question you want to ask? Your current question makes no sense.

[quote name='Krohm' timestamp='1329643802' post='4914463']What are the file names? In my case, I mandated each resource to be located in a specific directory so scripts get loaded from "Content\Programs", levels from "Content\World" etc... I even plan to deploy some more involved path validation to strictly enforce this.

Already mentioned this before. In fact, there are even more strict rules (i.e. filenames can only contain alphanumeric characters and underscores (no spaces!), and must end in ".png" extension - this is so it doesn't mess with the animation scripts later)
[/quote]
Why all the hassle? Why even bother checking the extension if you are checking the data header?
My engine checks only data headers and has never yet failed to properly identify files as either TGA, BMP, PNG, GIF, or my own LSI.
In fact not only is checking extensions an extremely bad idea for the sake of user-friendliness, it obviously won’t help you when an image has already been loaded to RAM and is being decoded from there (which should always be the case, even if the loading routine was given a file name—load the file to RAM and pass it off to a “from RAM” loader).
This can easily happen if you were ever to, say, receive an image from a network stream. Or generate one internally for whatever reason.

These extra checks are misguided and serve no practical purpose but to limit the functionality of your engine. Get rid of them and check headers and other verifiable data instead, and only that. Extensions have no meaning in the world of game programming, so just get that thought right out of your head.

Think of it this way: If it is possible for someone to try to load a .PNG file but it somehow ends up messing with your animation scripts later, you are doing it wrong.
And whether it is or is not possible, you are basically forcing 100 people to conform to your standards just so that 1 idiot won’t mess things up. Now 101 people have a problem (one of whom apparently has a huge problem) instead of just 1 person who ultimately deserves to have that problem since he or she brought it on him- or her- self.

Make your system flexible and—well I am not sure what to say if there is a possibility that trying to load an image file with the wrong extension could mess up animation scripts. Don’t write code that doesn’t make sense?

L. Spiro

Share on other sites
I think you might just want to let your level determine which resources need to be loaded. Let the level file contain the hard coded paths to the sprites, so when you load the level, you iterate through each required sprite file and load it into memory.

Share on other sites
I still have some difficulty in understanding why you keep thinking in terms of directories but then you clearly note sprite names are required to be somehow resolved. I'd personally just drop this whole directory thing, perhaps I have not understood the whole point in using them.

It's easier to just tell the program to load all the sprites from a few directories it knows will be needed beforehand than having to scan the level data to find out which objects are used, then the objects to find out which animations are needed as well as which other objects they may spawn (which in turn will need to be processed the same way), then the animations to know which sprites are needed, and then load that.

(and directories were already being used for organization for starters, I'm just taking advantage of that)

As a last note, it is unclear to me what you're expecting from saving "lots of time in the long term" when unloading assets. I always assumed this was 101 of every content management system.

There's a huge difference between making a single call to unload all sprites and making a call for every sprite that needs to be unloaded, especially if said calls could end up scattered all over the place =P

I am just wondering exactly what it is you feel you would end up rewriting should you hard-code image file names within loading routines.

This is what I used to do in earlier games (OK, just a general idea). You can see how this can interfere:
spr_idle[0] = load_sprite("graphics/player/idle_1.png"); spr_idle[1] = load_sprite("graphics/player/idle_2.png"); spr_idle[2] = load_sprite("graphics/player/idle_3.png"); spr_run[0] = load_sprite("graphics/player/run_1.png"); spr_run[1] = load_sprite("graphics/player/run_2.png"); spr_run[2] = load_sprite("graphics/player/run_3.png"); spr_run[3] = load_sprite("graphics/player/run_4.png"); // ...
As you can see, if I ever want to change the animation or add a new object, I need to change the code itself, since everything is extremely hard-coded. It is made even worse if I ever dare to add a new character that would need its own set of animations that don't match the original.

That's the easy way out, but would eventually end up requiring quite a rewrite if I ever go non-hard-coded, which is what I'm trying to avoid.

Your next game will have a totally new set of paths, so there isn’t much point in a system that “re-uses paths that would have otherwise been hard-coded.”

My next game wouldn't be using this code for starters most likely (other than maybe some game-independent code), I'm not making a flexible game engine =P I just want to allow some degree of modding (mainly custom levels), otherwise I'd be making a generic game engine, not a game.

#1: That would apply to anything, not just sprites.

It's likely the rest of the resources will end up like this sooner or later, actually. To which degree, not sure yet. I'm just asking for sprites since that's what I'm doing right now.

The above (posts prior to mine) advice could be used to easily associate data (including animation data) with image paths, but those paths are still hard-coded, just in a different place.

The idea is that they aren't hard-coded in the program, period. If I can specify my own files without having to modify the executable, that does the job (which is also why I don't care about imposing restrictions).

I think you might just want to let your level determine which resources need to be loaded. Let the level file contain the hard coded paths to the sprites, so when you load the level, you iterate through each required sprite file and load it into memory.

What if I modify an object and it needs different resources? The level file becomes invalid sudden of all. Unless we go again at what I mentioned before, having to scan every single thing just to see what resources are needed. The amount of memory taken up by these resources isn't big enough to be worth the effort trying to load only what's known to be absolutely needed.

• Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 11
• 9
• 11
• 15
• 21