# Directory paths for resources and assets

If I have a file stucture for my final, released game something like:

• Main folder
• Media
• Images
• Other assets
• Sounds
• Executable
• List item

And a different one for my 'in development' project, with the same Media folder but:

• Main
• Source and .obj, etc.
• Media with everything
• Bin folder with executable

I obviously cannot hardcode file pathnames into this, like:  "../Media/Image/evilguy.png" or "Media/Image/foo.jpg"  because they wouldn't work with one of the builds and would require a lot of switching names.

Instead, does it make sense for my resource manager, that loads everything, to have some kind of prefix path? Then, I can just do  Get("foo.jpg") or Get("Sounds/boom.ogg")
And simply switch out, for the final release, the ctr argument from the relative path for the development build to the release layout?

If not, how have other people sorted these sorts of things out?

That absolutely makes sense. You should not have any constant path in the string you pass to your Get function, or else it ties you down later. For example, if you decide to package your assets into some sort of compressed/encrypted archive, you would then be locked down to create an useless Media folder in the archive and then put all the assets inside it, when really the archive itself is something of a Media folder.

Your resource manager should know where to go to find the resources, whether it's the file system, an abstraction (archive), perhaps a distributed file system, or even the network or internet.

I personally also think Get("Sounds/boom.ogg") might be redundant; doesn't the "ogg" extension establish it as a sound? Again, if this is the case, you could just use Get("boom.ogg") and the resource manager could look at the extension and know to go into the Sounds folder. But it's totally up to you.

• The point of the "Sounds" folder would be more of a file organizational part, rather than on the coding side. I mean, if I wanted to edit a sound, then I wouldn't have to trapse through our entire assets dir. And it's struck me now that having separate managers for different assets does make more sense to have each have their own path to their respective folders {sound to Media/Sound, etc. } – The Communist Duck Aug 6 '10 at 13:58
• @Cyclops No, MrCranky and I wrote our answers at about the same time. I'm quite familiar with SO, thanks though :) – Ricket Aug 6 '10 at 14:13
• @The Communist Duck Yes, and you can still organize your files, but my stance is that the resource manager can handle that organization rather than hardcoding it all over your program. You can have the resource manager do something like if(file ends with '.ogg') folder='sounds' rather than writing "Sounds/" all over your program when all sound files are .ogg. But it's totally up to you, and that might be too restrictive when for example ogg files can be sound OR music files. – Ricket Aug 6 '10 at 14:16
• +1, this is conceptually the same as what I'd have recommended. @The Communist Duck: the way I've done it in the past, is I had the resource manager recursively check for all filenames below the media root. This means, I phyisically could have a file boom.ogg in folder Sound, but could still load it specifying just "boom.ogg". – Janis Kirsteins Aug 6 '10 at 14:19
• What I actually meant is because SoundManager, ImageManager, et al are basically ResourceManager<T>s, I could give each of them a directory such as 'Media/Sounds/' or 'Media/Images/' without the need to do Sounds/ or Images/ all over my program. – The Communist Duck Aug 6 '10 at 14:30

You don't really need a full on resource manager in this case. But yes, it's pretty common to have your assets to be arranged in a particular structure under some root, but for the code to all be written in ignorance of what that root is.

Rather than a resource manager though, you can just have an indirection step that resolves a relative path into an immediately usable path. So:

LoadWAV(GetAssetPath("audio/SomeEvent.wav"));


which resolves to

LoadWAV("/projects/myproject/build/audio/SomeEvent.wav");


when running from your local machine or

LoadWAV("game:/audio/SomeEvent.wav")


when running from a DVD build.

• I can see what you mean, but the resource manager is not for just the relative path sorting. It's also for caching assets and the like. – The Communist Duck Aug 6 '10 at 14:00
• I'm not questioning the value of a resource manager - that's a whole different question :-) The question seemed to me to be about abstracting the actual physical location of assets from the references to them in code, and that doesn't care about resource managers. It's a general issue of organising assets into categories, e.g. Load(GetSoundPath("SomeEvent")) So the code doesn't even then have to know that all sound events actually live in the /audio folder. This centralises the structure knowledge into one place, e.g. sound events live in a certain folder, and always have .ogg extensions. – MrCranky Aug 6 '10 at 14:53

You could also use resource IDs to decouple your resources from paths. On your development environment you would have a file such as:

<resources>
<resource id="1" name="SomeFile" path="sounds/somefile.ogg" />
<resource id="2" name="TrollFace" path="images/trollface.png" />
</resources>


You would then have a tool that would auto-generate a file in your programming language, such as:

public static class Resources
{
public static class Sounds
{
public const int SomeFile = 1;
}
public static class Images
{
public const int TrollFace = 2;
}
}


Your resource manager would have the following interface:

public interface IResourceManager
{
}


You would then auto-generate a portion of IResourceManager from the XML file, for example:

partial class IResourceManager
{
private static string Lookup(int id)
{
switch(id)
{
case 1: return "sounds/somefile.ogg";
case 2: return "images/trollface.png";
}
}
}


Loading a resource would then simply be something along the lines of:

resourceManager.Load(Resources.Sounds.SomeFile);


The auto-generated files here would be specific to development. If, for example, you chose to use a zip container or such you could possibly use the id as the filename within the zip (e.g. '1.bin') and switch the IResourceManager implementation.

Keep in mind that this would eliminate the possibility of modding.