AWESOME ENGINE / TECHNICAL GUIDE

Resources and persistence

Loading textures, sounds, fonts, and music; JSON saves and engine screenshots.

On this page

Where files are located

ResourceManager resolves names within specific directories. Pass a filename relative to the corresponding category, not the full path from the root.

API Directory Result
FetchTexture(filename) Content/Textures/ sf::Texture*
FetchSound(filename) Content/Sounds/ sf::SoundBuffer*
FetchFont(filename) Content/Fonts/ sf::Font*
FetchMusic(filename) Content/Musics/ std::optional<sf::Music>

Paths are relative to the application’s working directory. This is why you must run from the repository root, where Content exists.

How the cache works

Textures, sound buffers, and fonts are stored in maps indexed by filename. A subsequent request looks up the existing entry. The following function comes from the reference code:

sf::Texture *ResourceManager::FetchTexture(const std::string &filename) {
  if (!textures_.contains(filename)) {
    if (!textures_[filename].loadFromFile("Content/Textures/" + filename)) {
      LOG_ERROR("Failed to load texture: {}", filename);
      return nullptr;
    }
  }

  return &textures_.at(filename);
}

The manager retains ownership of these objects. Consumers must not delete the pointers they receive. There is also no public unload, cache invalidation, or automatic reload operation.

Check the result before using it: the first failed load returns nullptr. The implementation inserts the entry before attempting to load it, so a subsequent request for the same name does not automatically retry. With the current implementation, correcting a missing file usually requires restarting the application.

Music and sound

Short sounds use cached sf::SoundBuffer objects. The game creates and maintains its sf::Sound sources while using those buffers.

FetchMusic opens a file in an sf::Music object and returns it inside an optional; if it cannot open the file, it returns std::nullopt. Music is not retained in ResourceManager’s cache: the scene keeps the returned object and controls playback.

Not every project asset is loaded through the manager. The RenderManager background, shaders, and certain core resources are opened directly by their classes.

JSON saves

SaveManager reads Content/Save.json when constructed; if the file does not exist, it starts with an empty object. Its interface provides Set, Get, Has, Erase, and Clear.

On destruction, it writes the values if the object is not empty. This persists simple game data, but is not a transactional or cloud save system.

Two limitations to keep in mind:

  • There is no general recovery mechanism for an existing but invalid JSON file.
  • Clear() empties the values in memory, but the destructor does not overwrite the file when the object is empty. This does not necessarily delete the saved data on disk.

When testing persistence changes, keep a copy of your data before modifying the file.

Screenshots

F12 invokes ScreenshotManager::Take. The manager copies the window to a texture, retrieves the image, and saves a PNG in Content/Screenshots, creating the directory if needed.

The filename contains the date and time with milliseconds. The result is logged, and a sound plays when saving succeeds. The application needs write permission for that directory.

Sources

Based on verified source code.Found an issue? →