ResourceManager class for game engine












0












$begingroup$


Writing a very basic game engine (just a bunch of utilities that I may use later if I decide to make a game), and I'm currently working on designing the ResourceManager class that keeps track of all resources currently in use.



Resource.h



#ifndef RESOURCE_H
#define RESOURCE_H

#include<string>
typedef unsigned int ResourceId;
typedef std::string ResourcePath;
namespace Real
{
enum class ResourceType
{
NONE,
VIDEO,
TEXTURE,
FONT
/*
SFML streams audio, so don't really need a ResourceManager for that
*/
};
template<typename T>
class Resource
{
protected:
ResourceId id;
ResourcePath path;
ResourceType type;
T* resource;
public:
// creates an empty Resource object
Resource();
Resource(ResourceId _id, ResourcePath _path, ResourceType _type);

~Resource();

/*
* Leaving the creation of ResourceId upto the ResourceManager
* Checking whether resource already exists is the job of the ResourceManager.
* load() operators under the assumption that any new Resource object created is for
* a resource that doesn't yet exist
*/
void load();
void unload();

size_t getSize();

void setResourceId(ResourceId _id);
ResourceId getResourceId() const;

// on getting a new resource path, the current resource is destroyed, and a new resource is created with the ResourceId = current id
void setResourcePath(ResourcePath _path);
ResourcePath getResourcePath() const;

// the deference operator returns the pointer to the actual resource stored in memory
T* operator*() const;
};
}



#endif


Resource.cpp



#include "Resource.h"

namespace Real
{
template<typename T>
Resource<T>::Resource() : id(0), type(ResourceType::None), path(nullptr), resource(nullptr)
{}

template<typename T>
Resource<T>::Resource(ResourceId _id, ResourcePath _path, ResourceType _type): id(_id), path(_path), _type(type)
{
load();
}

template<typename T>
Resource<T>::~Resource()
{
unload();
}

template<typename T>
void Resource<T>::load()
{
resource = new T();
if (!resource->loadFromFile(path))
{
//TODO: define defaultpath inside Resource.h that points to default resource in case load fails
resource->loadFromFile(defaultpath);
}
}

template<typename T>
void Resource<T>::unload()
{
if (resource != nullptr)
delete resource;
}

template<typename T>
size_t Resource<T>::getSize()
{
//TODO
return 0;
}

template<typename T>
void Resource<T>::setResourceId(ResourceId _id)
{
id = _id;
}

template<typename T>
ResourceId Resource<T>::getResourceId() const
{
return id;
}

template<typename T>
void Resource<T>::setResourcePath(ResourcePath _path)
{
unload();
load(_path);
}

template<typename T>
ResourcePath Resource<T>::getResourcePath() const
{
return path;
}

template<typename T>
T* Resource<T>::operator*() const
{
return resource;
}
}


ResourceManager.h



#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H

#include<unordered_map>
#include "Resource.h"
namespace Real
{
template<typename T>
class ResourceManager
{
protected:
std::unordered_map<ResourcePath, Resource<T>> resources;
ResourceId nextId; // variables that hold the next ResourceId to be assigned to a resource
public:
ResourceManager();
~ResourceManager();


Resource<T> loadResource(ResourcePath path, ResourceType type);
bool unloadResource(ResourcePath path);

Resource<T> getResource(ResourcePath path);

private:
Resource<T> addNewResource(ResourcePath path, ResourceType type);

};
}

#endif


ResourceManager.cpp



#include "ResourceManager.h"

namespace Real
{
template<typename T>
ResourceManager<T>::ResourceManager(): nextId(0)
{}

template<typename T>
ResourceManager<T>::~ResourceManager()
{
resources.clear(); // Calls the destructor for every Resource object, ensuring that the heap-allocated objects are deleted
}

template<typename T>
Resource<T> ResourceManager<T>::loadResource(ResourcePath path, ResourceType type)
{
typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);

if (it == resources.end())
{
addNewResource(path, type);
}
else
{
return resources.at(ResourcePath);
}
}

template<typename T>
bool ResourceManager<T>::unloadResource(ResourcePath path)
{
typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
if (it == resources.end())
{
return false;
}

resources.erase(ResourcePath);
}

template<typename T>
Resource<T> ResourceManager<T>::getResource(ResourcePath path)
{
typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
if (it == resources.end())
{
return nullptr;
}
return resources.at(path);
}

template<typename T>
Resource<T> ResourceManager<T>::addNewResource(ResourcePath path, ResourceType type)
{
Resource<T> newResource(path, type);
resources.insert(newResource);
nextId += 1;
return newResource;
}
}


Here's where I am having trouble deciding on the best route.
1) I'm using SFML, and am assuming that the type being passed as template argument is going to be SFML types sf::Texture, sf::Font, etc. Keeping that in mind, is it better to keep the code the way it is, or should I create a base ResourceManager class, from which different types of ResourceManagers (TextureManager,FontManager) inherit from?



2) In Resource.cpp, there is defaultpath variable which points to a default resource if the user-provided path to the resource is not valid/cannot be loaded. Since I'm using templates, I don't really have a good way of making sure defaultpath would contain the path for the appropriate type of resource (for example, Resource<sf::Texture>'s defaultpath would contain the path to an image).



3) Since the iterator is being created every I want to update the map, should I create a single static iterator beforehand, and use that instead of creating a new one every function call?



Any feedback would be much appreciated!









share









New contributor




Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    0












    $begingroup$


    Writing a very basic game engine (just a bunch of utilities that I may use later if I decide to make a game), and I'm currently working on designing the ResourceManager class that keeps track of all resources currently in use.



    Resource.h



    #ifndef RESOURCE_H
    #define RESOURCE_H

    #include<string>
    typedef unsigned int ResourceId;
    typedef std::string ResourcePath;
    namespace Real
    {
    enum class ResourceType
    {
    NONE,
    VIDEO,
    TEXTURE,
    FONT
    /*
    SFML streams audio, so don't really need a ResourceManager for that
    */
    };
    template<typename T>
    class Resource
    {
    protected:
    ResourceId id;
    ResourcePath path;
    ResourceType type;
    T* resource;
    public:
    // creates an empty Resource object
    Resource();
    Resource(ResourceId _id, ResourcePath _path, ResourceType _type);

    ~Resource();

    /*
    * Leaving the creation of ResourceId upto the ResourceManager
    * Checking whether resource already exists is the job of the ResourceManager.
    * load() operators under the assumption that any new Resource object created is for
    * a resource that doesn't yet exist
    */
    void load();
    void unload();

    size_t getSize();

    void setResourceId(ResourceId _id);
    ResourceId getResourceId() const;

    // on getting a new resource path, the current resource is destroyed, and a new resource is created with the ResourceId = current id
    void setResourcePath(ResourcePath _path);
    ResourcePath getResourcePath() const;

    // the deference operator returns the pointer to the actual resource stored in memory
    T* operator*() const;
    };
    }



    #endif


    Resource.cpp



    #include "Resource.h"

    namespace Real
    {
    template<typename T>
    Resource<T>::Resource() : id(0), type(ResourceType::None), path(nullptr), resource(nullptr)
    {}

    template<typename T>
    Resource<T>::Resource(ResourceId _id, ResourcePath _path, ResourceType _type): id(_id), path(_path), _type(type)
    {
    load();
    }

    template<typename T>
    Resource<T>::~Resource()
    {
    unload();
    }

    template<typename T>
    void Resource<T>::load()
    {
    resource = new T();
    if (!resource->loadFromFile(path))
    {
    //TODO: define defaultpath inside Resource.h that points to default resource in case load fails
    resource->loadFromFile(defaultpath);
    }
    }

    template<typename T>
    void Resource<T>::unload()
    {
    if (resource != nullptr)
    delete resource;
    }

    template<typename T>
    size_t Resource<T>::getSize()
    {
    //TODO
    return 0;
    }

    template<typename T>
    void Resource<T>::setResourceId(ResourceId _id)
    {
    id = _id;
    }

    template<typename T>
    ResourceId Resource<T>::getResourceId() const
    {
    return id;
    }

    template<typename T>
    void Resource<T>::setResourcePath(ResourcePath _path)
    {
    unload();
    load(_path);
    }

    template<typename T>
    ResourcePath Resource<T>::getResourcePath() const
    {
    return path;
    }

    template<typename T>
    T* Resource<T>::operator*() const
    {
    return resource;
    }
    }


    ResourceManager.h



    #ifndef RESOURCE_MANAGER_H
    #define RESOURCE_MANAGER_H

    #include<unordered_map>
    #include "Resource.h"
    namespace Real
    {
    template<typename T>
    class ResourceManager
    {
    protected:
    std::unordered_map<ResourcePath, Resource<T>> resources;
    ResourceId nextId; // variables that hold the next ResourceId to be assigned to a resource
    public:
    ResourceManager();
    ~ResourceManager();


    Resource<T> loadResource(ResourcePath path, ResourceType type);
    bool unloadResource(ResourcePath path);

    Resource<T> getResource(ResourcePath path);

    private:
    Resource<T> addNewResource(ResourcePath path, ResourceType type);

    };
    }

    #endif


    ResourceManager.cpp



    #include "ResourceManager.h"

    namespace Real
    {
    template<typename T>
    ResourceManager<T>::ResourceManager(): nextId(0)
    {}

    template<typename T>
    ResourceManager<T>::~ResourceManager()
    {
    resources.clear(); // Calls the destructor for every Resource object, ensuring that the heap-allocated objects are deleted
    }

    template<typename T>
    Resource<T> ResourceManager<T>::loadResource(ResourcePath path, ResourceType type)
    {
    typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);

    if (it == resources.end())
    {
    addNewResource(path, type);
    }
    else
    {
    return resources.at(ResourcePath);
    }
    }

    template<typename T>
    bool ResourceManager<T>::unloadResource(ResourcePath path)
    {
    typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
    if (it == resources.end())
    {
    return false;
    }

    resources.erase(ResourcePath);
    }

    template<typename T>
    Resource<T> ResourceManager<T>::getResource(ResourcePath path)
    {
    typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
    if (it == resources.end())
    {
    return nullptr;
    }
    return resources.at(path);
    }

    template<typename T>
    Resource<T> ResourceManager<T>::addNewResource(ResourcePath path, ResourceType type)
    {
    Resource<T> newResource(path, type);
    resources.insert(newResource);
    nextId += 1;
    return newResource;
    }
    }


    Here's where I am having trouble deciding on the best route.
    1) I'm using SFML, and am assuming that the type being passed as template argument is going to be SFML types sf::Texture, sf::Font, etc. Keeping that in mind, is it better to keep the code the way it is, or should I create a base ResourceManager class, from which different types of ResourceManagers (TextureManager,FontManager) inherit from?



    2) In Resource.cpp, there is defaultpath variable which points to a default resource if the user-provided path to the resource is not valid/cannot be loaded. Since I'm using templates, I don't really have a good way of making sure defaultpath would contain the path for the appropriate type of resource (for example, Resource<sf::Texture>'s defaultpath would contain the path to an image).



    3) Since the iterator is being created every I want to update the map, should I create a single static iterator beforehand, and use that instead of creating a new one every function call?



    Any feedback would be much appreciated!









    share









    New contributor




    Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      0












      0








      0





      $begingroup$


      Writing a very basic game engine (just a bunch of utilities that I may use later if I decide to make a game), and I'm currently working on designing the ResourceManager class that keeps track of all resources currently in use.



      Resource.h



      #ifndef RESOURCE_H
      #define RESOURCE_H

      #include<string>
      typedef unsigned int ResourceId;
      typedef std::string ResourcePath;
      namespace Real
      {
      enum class ResourceType
      {
      NONE,
      VIDEO,
      TEXTURE,
      FONT
      /*
      SFML streams audio, so don't really need a ResourceManager for that
      */
      };
      template<typename T>
      class Resource
      {
      protected:
      ResourceId id;
      ResourcePath path;
      ResourceType type;
      T* resource;
      public:
      // creates an empty Resource object
      Resource();
      Resource(ResourceId _id, ResourcePath _path, ResourceType _type);

      ~Resource();

      /*
      * Leaving the creation of ResourceId upto the ResourceManager
      * Checking whether resource already exists is the job of the ResourceManager.
      * load() operators under the assumption that any new Resource object created is for
      * a resource that doesn't yet exist
      */
      void load();
      void unload();

      size_t getSize();

      void setResourceId(ResourceId _id);
      ResourceId getResourceId() const;

      // on getting a new resource path, the current resource is destroyed, and a new resource is created with the ResourceId = current id
      void setResourcePath(ResourcePath _path);
      ResourcePath getResourcePath() const;

      // the deference operator returns the pointer to the actual resource stored in memory
      T* operator*() const;
      };
      }



      #endif


      Resource.cpp



      #include "Resource.h"

      namespace Real
      {
      template<typename T>
      Resource<T>::Resource() : id(0), type(ResourceType::None), path(nullptr), resource(nullptr)
      {}

      template<typename T>
      Resource<T>::Resource(ResourceId _id, ResourcePath _path, ResourceType _type): id(_id), path(_path), _type(type)
      {
      load();
      }

      template<typename T>
      Resource<T>::~Resource()
      {
      unload();
      }

      template<typename T>
      void Resource<T>::load()
      {
      resource = new T();
      if (!resource->loadFromFile(path))
      {
      //TODO: define defaultpath inside Resource.h that points to default resource in case load fails
      resource->loadFromFile(defaultpath);
      }
      }

      template<typename T>
      void Resource<T>::unload()
      {
      if (resource != nullptr)
      delete resource;
      }

      template<typename T>
      size_t Resource<T>::getSize()
      {
      //TODO
      return 0;
      }

      template<typename T>
      void Resource<T>::setResourceId(ResourceId _id)
      {
      id = _id;
      }

      template<typename T>
      ResourceId Resource<T>::getResourceId() const
      {
      return id;
      }

      template<typename T>
      void Resource<T>::setResourcePath(ResourcePath _path)
      {
      unload();
      load(_path);
      }

      template<typename T>
      ResourcePath Resource<T>::getResourcePath() const
      {
      return path;
      }

      template<typename T>
      T* Resource<T>::operator*() const
      {
      return resource;
      }
      }


      ResourceManager.h



      #ifndef RESOURCE_MANAGER_H
      #define RESOURCE_MANAGER_H

      #include<unordered_map>
      #include "Resource.h"
      namespace Real
      {
      template<typename T>
      class ResourceManager
      {
      protected:
      std::unordered_map<ResourcePath, Resource<T>> resources;
      ResourceId nextId; // variables that hold the next ResourceId to be assigned to a resource
      public:
      ResourceManager();
      ~ResourceManager();


      Resource<T> loadResource(ResourcePath path, ResourceType type);
      bool unloadResource(ResourcePath path);

      Resource<T> getResource(ResourcePath path);

      private:
      Resource<T> addNewResource(ResourcePath path, ResourceType type);

      };
      }

      #endif


      ResourceManager.cpp



      #include "ResourceManager.h"

      namespace Real
      {
      template<typename T>
      ResourceManager<T>::ResourceManager(): nextId(0)
      {}

      template<typename T>
      ResourceManager<T>::~ResourceManager()
      {
      resources.clear(); // Calls the destructor for every Resource object, ensuring that the heap-allocated objects are deleted
      }

      template<typename T>
      Resource<T> ResourceManager<T>::loadResource(ResourcePath path, ResourceType type)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);

      if (it == resources.end())
      {
      addNewResource(path, type);
      }
      else
      {
      return resources.at(ResourcePath);
      }
      }

      template<typename T>
      bool ResourceManager<T>::unloadResource(ResourcePath path)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
      if (it == resources.end())
      {
      return false;
      }

      resources.erase(ResourcePath);
      }

      template<typename T>
      Resource<T> ResourceManager<T>::getResource(ResourcePath path)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
      if (it == resources.end())
      {
      return nullptr;
      }
      return resources.at(path);
      }

      template<typename T>
      Resource<T> ResourceManager<T>::addNewResource(ResourcePath path, ResourceType type)
      {
      Resource<T> newResource(path, type);
      resources.insert(newResource);
      nextId += 1;
      return newResource;
      }
      }


      Here's where I am having trouble deciding on the best route.
      1) I'm using SFML, and am assuming that the type being passed as template argument is going to be SFML types sf::Texture, sf::Font, etc. Keeping that in mind, is it better to keep the code the way it is, or should I create a base ResourceManager class, from which different types of ResourceManagers (TextureManager,FontManager) inherit from?



      2) In Resource.cpp, there is defaultpath variable which points to a default resource if the user-provided path to the resource is not valid/cannot be loaded. Since I'm using templates, I don't really have a good way of making sure defaultpath would contain the path for the appropriate type of resource (for example, Resource<sf::Texture>'s defaultpath would contain the path to an image).



      3) Since the iterator is being created every I want to update the map, should I create a single static iterator beforehand, and use that instead of creating a new one every function call?



      Any feedback would be much appreciated!









      share









      New contributor




      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      Writing a very basic game engine (just a bunch of utilities that I may use later if I decide to make a game), and I'm currently working on designing the ResourceManager class that keeps track of all resources currently in use.



      Resource.h



      #ifndef RESOURCE_H
      #define RESOURCE_H

      #include<string>
      typedef unsigned int ResourceId;
      typedef std::string ResourcePath;
      namespace Real
      {
      enum class ResourceType
      {
      NONE,
      VIDEO,
      TEXTURE,
      FONT
      /*
      SFML streams audio, so don't really need a ResourceManager for that
      */
      };
      template<typename T>
      class Resource
      {
      protected:
      ResourceId id;
      ResourcePath path;
      ResourceType type;
      T* resource;
      public:
      // creates an empty Resource object
      Resource();
      Resource(ResourceId _id, ResourcePath _path, ResourceType _type);

      ~Resource();

      /*
      * Leaving the creation of ResourceId upto the ResourceManager
      * Checking whether resource already exists is the job of the ResourceManager.
      * load() operators under the assumption that any new Resource object created is for
      * a resource that doesn't yet exist
      */
      void load();
      void unload();

      size_t getSize();

      void setResourceId(ResourceId _id);
      ResourceId getResourceId() const;

      // on getting a new resource path, the current resource is destroyed, and a new resource is created with the ResourceId = current id
      void setResourcePath(ResourcePath _path);
      ResourcePath getResourcePath() const;

      // the deference operator returns the pointer to the actual resource stored in memory
      T* operator*() const;
      };
      }



      #endif


      Resource.cpp



      #include "Resource.h"

      namespace Real
      {
      template<typename T>
      Resource<T>::Resource() : id(0), type(ResourceType::None), path(nullptr), resource(nullptr)
      {}

      template<typename T>
      Resource<T>::Resource(ResourceId _id, ResourcePath _path, ResourceType _type): id(_id), path(_path), _type(type)
      {
      load();
      }

      template<typename T>
      Resource<T>::~Resource()
      {
      unload();
      }

      template<typename T>
      void Resource<T>::load()
      {
      resource = new T();
      if (!resource->loadFromFile(path))
      {
      //TODO: define defaultpath inside Resource.h that points to default resource in case load fails
      resource->loadFromFile(defaultpath);
      }
      }

      template<typename T>
      void Resource<T>::unload()
      {
      if (resource != nullptr)
      delete resource;
      }

      template<typename T>
      size_t Resource<T>::getSize()
      {
      //TODO
      return 0;
      }

      template<typename T>
      void Resource<T>::setResourceId(ResourceId _id)
      {
      id = _id;
      }

      template<typename T>
      ResourceId Resource<T>::getResourceId() const
      {
      return id;
      }

      template<typename T>
      void Resource<T>::setResourcePath(ResourcePath _path)
      {
      unload();
      load(_path);
      }

      template<typename T>
      ResourcePath Resource<T>::getResourcePath() const
      {
      return path;
      }

      template<typename T>
      T* Resource<T>::operator*() const
      {
      return resource;
      }
      }


      ResourceManager.h



      #ifndef RESOURCE_MANAGER_H
      #define RESOURCE_MANAGER_H

      #include<unordered_map>
      #include "Resource.h"
      namespace Real
      {
      template<typename T>
      class ResourceManager
      {
      protected:
      std::unordered_map<ResourcePath, Resource<T>> resources;
      ResourceId nextId; // variables that hold the next ResourceId to be assigned to a resource
      public:
      ResourceManager();
      ~ResourceManager();


      Resource<T> loadResource(ResourcePath path, ResourceType type);
      bool unloadResource(ResourcePath path);

      Resource<T> getResource(ResourcePath path);

      private:
      Resource<T> addNewResource(ResourcePath path, ResourceType type);

      };
      }

      #endif


      ResourceManager.cpp



      #include "ResourceManager.h"

      namespace Real
      {
      template<typename T>
      ResourceManager<T>::ResourceManager(): nextId(0)
      {}

      template<typename T>
      ResourceManager<T>::~ResourceManager()
      {
      resources.clear(); // Calls the destructor for every Resource object, ensuring that the heap-allocated objects are deleted
      }

      template<typename T>
      Resource<T> ResourceManager<T>::loadResource(ResourcePath path, ResourceType type)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);

      if (it == resources.end())
      {
      addNewResource(path, type);
      }
      else
      {
      return resources.at(ResourcePath);
      }
      }

      template<typename T>
      bool ResourceManager<T>::unloadResource(ResourcePath path)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
      if (it == resources.end())
      {
      return false;
      }

      resources.erase(ResourcePath);
      }

      template<typename T>
      Resource<T> ResourceManager<T>::getResource(ResourcePath path)
      {
      typename std::unordered_map<ResourcePath, Resource<T>>::const_iterator it = resources.find(path);
      if (it == resources.end())
      {
      return nullptr;
      }
      return resources.at(path);
      }

      template<typename T>
      Resource<T> ResourceManager<T>::addNewResource(ResourcePath path, ResourceType type)
      {
      Resource<T> newResource(path, type);
      resources.insert(newResource);
      nextId += 1;
      return newResource;
      }
      }


      Here's where I am having trouble deciding on the best route.
      1) I'm using SFML, and am assuming that the type being passed as template argument is going to be SFML types sf::Texture, sf::Font, etc. Keeping that in mind, is it better to keep the code the way it is, or should I create a base ResourceManager class, from which different types of ResourceManagers (TextureManager,FontManager) inherit from?



      2) In Resource.cpp, there is defaultpath variable which points to a default resource if the user-provided path to the resource is not valid/cannot be loaded. Since I'm using templates, I don't really have a good way of making sure defaultpath would contain the path for the appropriate type of resource (for example, Resource<sf::Texture>'s defaultpath would contain the path to an image).



      3) Since the iterator is being created every I want to update the map, should I create a single static iterator beforehand, and use that instead of creating a new one every function call?



      Any feedback would be much appreciated!







      c++ c++17





      share









      New contributor




      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share









      New contributor




      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share



      share








      edited 1 min ago







      Rish













      New contributor




      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 8 mins ago









      RishRish

      1




      1




      New contributor




      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Rish is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Rish is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214586%2fresourcemanager-class-for-game-engine%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Rish is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          Rish is a new contributor. Be nice, and check out our Code of Conduct.













          Rish is a new contributor. Be nice, and check out our Code of Conduct.












          Rish is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214586%2fresourcemanager-class-for-game-engine%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Список кардиналов, возведённых папой римским Каликстом III

          Deduzione

          Mysql.sock missing - “Can't connect to local MySQL server through socket”