1
\$\begingroup\$

So for example I have a class called TypingKeyboard. It allows you to display a string while it's being typed by the computer with sounds. I need one in the menu, for the title. And one for the credits, and some in-game. So loading every sound and storing it to the RAM for every instance of TypingKeyboard is not very efficient.

So, I want to make a class that already holds these sounds, then call it when I need it, so I don't have to load everything.

How do I design this? I mean, how do you get these sounds loading and then make them accessible without initializing a class for it?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Game assets like sounds are usually best managed if preloaded in advance. You don't want the user to experience a delay in the sound effects every time a sound has to be loaded.

You should implement a ResourceCache helper that manages game resources for you. Then things like sounds could be preloaded at each level start and unloaded when the level ends. This is a very good approach if your game is not huge.

// This class will probably be a singleton, so I made the methods 'static'.
class ResourceCache {

    // Call when level loads
    public static void PreloadResource(string resourceName);

    // Call when level ends
    public static void UnloadAllResources();

    // Find a previously loaded resource 
    public static Resource FindResourceByName(string resourceName);
}

Then in the level load section:

void LoadLevel()
{
    ResourceCache.PreloadResource("foo.mp3");
    ResourceCache.PreloadResource("bar.mp3");
    ...
}

Now anywhere in the game, you can:

// No loading is done, just a cache/map lookup.
// "bar.mp3" was loaded at level start by PreloadResource().
Resource barSound = ResourceCache.FindResourceByName("bar.mp3");

And when a level ends, you can clear the resource cache:

ResourceCache.UnloadAllResources();

The cache should eventually use some management policy like LRU to handle scenarios when you want to load more data than what can fit into memory. Then the cache can evict old resources to make room for new ones. If you have the cache interface in place, adding a "real" caching scheme becomes very easy.

\$\endgroup\$
2
  • \$\begingroup\$ Great approach! But the problem is I think the ResourceCache.FindResourceByName("bar.mp3"); How can I call that void without creating an instance of the class? \$\endgroup\$
    – joppiesaus
    Jul 26, 2014 at 19:14
  • 1
    \$\begingroup\$ Well, that was some pseudo-code. But ResourceCache can be a singleton, if that's what you mean. So you can make every method and variable static or declare a global instance somewhere. If you make everything static, you can use it in the exact same way I did. \$\endgroup\$
    – glampert
    Jul 27, 2014 at 2:05
0
\$\begingroup\$

What you are looking for is the Object Pool pattern which provides reusability and efficient memory usage. At the initialization level of the application, you simply create the instance and give it to the object pool. When you need to use it, pop it from the pool and send it back to the pool after you finish. In this way, you don't have to instantiate a new component.

The object pool may be a static class which holds unique id's for each kind of reusable component. So, in order to pop a sound from the pool, you just call Pool.getObjectById(SoundType.Type).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .