I am working on a personal 2D game engine development in my free times based on SDL and I faced with an encapsulation problem.
I divided and encapsulated all my classes such as Application, ApplicationWindow, Renderer, Texture, and so on. Renderer class encapsulates SDL_Renderer and it is used to render every frame. My Texture class encapsulate SDL_Texture and as you know, if you want to load a texture in SDL, you have to send SDL_Renderer as a parameter and this situation has begun to give me real a headache.
When I checked the various tutorials, books, etc. I saw that people usually chose the easy way out:
Making the SDL_Renderer global, or
Making the Renderer class as singleton and adding a getSDLRenderer() method
I do not agree any of these approaches and I believe that these are not the real solutions, only some easy "work around"s.
A common c++ solution I have seen is to use a context struct that holds pointers to the Renderer, and whatever else that is used in many many classes.
In my case I have a TitleScene request this from the SceneManager via Protected BaseScene function.
struct Context {
SDL_Renderer *renderer;
// Whatever
}
class BaseScene {
protected:
SharedContext* getSharedContext() const;
}
void TitleScene::render() {
SDL_Renderer* renderer = getSharedContext()->renderer;
// Do whatever with Renderer
}
Thousands, perhaps millions of games have shipped with globals and singletons, and guess what, NO ONE CARES. If it works then use it. Why waste time on creating structures and doing things “correctly”, I got news for you, what you think is “correct” another person thinks is incorrect, just make a global and call it a day. Unless you plan on having multiple renderers active at the same time then I would definitely not make it a parameter in every call.
This guy is right about singletons
Have a look for CppCon 2014: Nicolas Fleury “C++ in Huge AAA Games” on youtube, its a good watch.
“Works or did work for Ubisoft”
One of the things he talks about is singletons.
Don’t get caught up in writing the best code ever because you will never finish anything.
I would use a context then. But why even encapsulate it? SDL is open source, if it dies just take the code and maintain it, or whatever you have to port to make a wrapper for that using the SDL syntax if the time ever comes. If you don’t ever think you’ll remove SDL then save yourself a ton of time and headaches and use it directly.