Splitting SDL tasks into classes. Need advice


#1

I am trying to migrate my game attempt from one big cpp file to a structure that uses multiple classes to handle things such as display and input. However, when splitting off my SDL parts, I found I now have multiple classes which require SDL includes in their headers so I can declare SDL types: display(SDL_Window, SDL_Renderer) and input (SDL_Event).

I’m not sure if this is the correct way to do it, because I read you don’t want to include the same thing multiple times. Add to that I now have an instance of SDL I have to start in both constructors, and then closeout in the destructors. This makes me question if the events from one instances of SDL will properly sync with actions within the window of the other SDL instance.

I have a feeling this is the wrong way to do it, so I would like to ask if there is a better way which I can split up these SDL tasks? Also, I’m using Ubuntu 16.04 if that matters.

Here is my display header (drawscreen.h):

#ifndef DRAWSCREEN_H
#define DRAWSCREEN_H

#include </usr/include/SDL2/SDL.h>
#include </usr/include/SDL2/SDL_ttf.h>

class Drawscreen
{

  public:
    Drawscreen(const char* title, int window_width, int window_height);
    ~Drawscreen();
    void display();

  private:
    SDL_Window *window = NULL;
    SDL_Renderer *renderer = NULL;

};

#endif

and my input header (handle_input.h):

#ifndef HANDLE_INPUT_H
#define HANDLE_INPUT_H

#include </usr/include/SDL2/SDL.h>
#include </usr/include/SDL2/SDL_ttf.h>

class Handle_Input
{

  public:
    Handle_Input();
    ~Handle_Input();
    void input();

  private:
    SDL_Event e;

};

#endif

#2

By SDL instance, do you mean that you call SDL_Init() multiple times? That doesn’t sound correct. For my own project, I have a simpler approach: there is only one class that wraps all features that I need from SDL at the moment. I need only an OpenGL window, some event handling and a tick counter.

Regarding headers, include only what you need and use. For example, SDL_ttf.h inclusion seems unnecessary so far. There is nothing in your headers using font. Maybe include should be in .cpp file, instead of. Also, having “/usr/include/” should be avoided. Point your include path to compiler in your makefile.

Regarding handle_input.h, SDL_Event is not visible in function signatures. This make me think that you are only using “e” locally in some function and a member variable is unnecessary. Both includes seem unnecessary in this header and you can decrease build dependencies moving includes to your .cpp file.

If you truly want to use “e” as a member variable, then consider giving it a more desciptive name :slight_smile:

In practise, due to include guards, a header file is included only once per compilation unit.


#3

Yes, I did mean calling SDL_Init() multiple times. A wrapper class sounds simpler for sure. My only concern about this is that the class may become too big. However, if you think it would be more efficient to put input and display in one class, since they both deal with SDL, then I’ll do that.

I erased the ttf include from my handle_input class and from the header for the drawscreen class, and now it is only in the drawscreen.cpp file. As for the makefile, I don’t know how to use those. I compile everything from command line (Ubuntu using g++). Any links to a forum post or other source you feel covers that topic so I can check it out?

To answer your question about the SDL_Event, here is my handle_input.cpp:

#include "handle_input.h"

bool Handle_Input::input()
{
  while (SDL_PollEvent(&e))
  {
    if (e.type == SDL_QUIT)
      return true;
  }
  return false;
}

The answer confuses me a bit about classes. Am I not supposed to declare all variables for a class in the .h file? Meaning, I can simply put the e or other variables not needed in function declarations always in the .cpp files?

The only reason I used e, is because all of the tutorials I saw did the same, so I assumed it was the proper format at the time, but I can rename it.

I’m not sure what you mean by the last sentence. Did I do something wrong with my include guards?

Thanks for the help!


#4

I don’t remember any good makefile tutorials but there must be many. I can try to help you to create a basic makefile.

I have used a single class for SDL wrapper because it was sufficient for me. It’s possible that in the future I need more features and then I may have to split the class into smaller ones. I agree with you that classes shouldn’t be too large.

No, you shouldn’t have to declare ALL variables in the class header in C++. I would declare only those that object has to “remember” for later use. Suppose you have opened a font. You probably want to store the font pointer for later use, to avoid re-opening it every time it’s needed.

Then you have local variables, like “int i” for loops or “SDL_Event e” for reading the last event. If you don’t want to memorize the last event, then there is no need to declare it as a member variable. Short variable names like “i” or “e” are ok in local scope (inside a small function, for example). Coding conventions tend to be quite subjective. Use what works for you.

I think your include guards were fine. Maybe I was trying to comment this: “I read you don’t want to include the same thing multiple times”. When you use include guards, every header will be included only once. But still, there is no need to include unused stuff. They create unnecessary dependencies.


#5

Sorry about my late response.

Any advice you have for a basic makefile would be nice. If it makes things easier/quicker than command line compilation, then that’s good.

Yes, I think that a wrapper class may be fine for now then. My program isn’t very big. I’ll also add the font pointer to the class header, because like you said, I may need to open it later. I’ll also move my event variable inside the functions where they are used. I’ll try to weed out any unnecessary included items too.

Thanks for all you help.