0
\$\begingroup\$

I have worked on creating a gameloop and so far all of the code was inside a main.cpp file and I want to separate it into different files.

Which caused several problems:

My code is separated into 3 main functions in main(); which are input simulate and render.

I was able to separate the input code into its own file, however I ran into 2 problems I had to fix:

#include <iostream>
#include <SDL.h>
#include "input.h"

extern bool isMainLoopActive;
extern bool isMoveRightPressed;
extern bool isMoveLeftPressed;
extern bool isMoveUpPressed;
extern bool isMoveDownPressed;

struct detected_keys {
    bool right = true;
    bool left = true;
    bool up = true;
    bool down = true;
};

detected_keys movement_keys;

void input() {

    // player control of box
    const Uint8* currentKeyStates = SDL_GetKeyboardState(NULL);

    if (currentKeyStates[SDL_SCANCODE_RIGHT]) {
        isMoveRightPressed = true;
        movement_keys.right = true;
    }
    if (currentKeyStates[SDL_SCANCODE_LEFT]) {
        isMoveLeftPressed = true;
        movement_keys.left = true;
    }
    if (currentKeyStates[SDL_SCANCODE_UP]) {
        isMoveUpPressed = true;
        movement_keys.up = true;
    }
    if (currentKeyStates[SDL_SCANCODE_DOWN]) {
        isMoveDownPressed = true;
        movement_keys.down = true;
    }

    return;
}

The 2 problems are:

  1. While I was coding in one large main.cpp file I was able to have a lot of functions and variables at the top of the file which were all global. Now that I moved the input() to a new file I lost direct access to the global variables.

So what I did first was use

extern bool isMainLoopActive;
extern bool isMoveRightPressed;
extern bool isMoveLeftPressed;
extern bool isMoveUpPressed;
extern bool isMoveDownPressed;

to simply get access to these variables back. However I read somewhere that one should avoid relying on global variables.

So I looked for a way to transfer the 4 key presses represented as boolean variables from one function to another as a struct.

However if I want to use a struct of the type "detected_keys" then I would have also declare that type in the other files, which would be the same as just using extern variables all over.

So what is the best approach here if global variables are supposedly to not be used?

Is all code in videogames basically functions passing values over to each other in large packages? And if so, is there a data type that is better for that than struct?

\$\endgroup\$
3
  • \$\begingroup\$ Are you familiar with the Singleton programming pattern? \$\endgroup\$
    – Vaillancourt
    Commented Mar 4 at 0:27
  • \$\begingroup\$ By the way, in game development it is often useful for the consumers of the input system to know whether a keypress began on this frame, is still being held down from previous frames or ended this frame. Just one example: Imagine you have a gun that does single fire, a gun that does automatic fire and a gun with a charge-and-release firing mechanic. The first would spawn a bullet if key down, the second if key held and the third if key release. \$\endgroup\$
    – Philipp
    Commented Mar 4 at 9:55
  • \$\begingroup\$ @Philipp That is good advice, I will bookmark your advice. \$\endgroup\$
    – snow_owl
    Commented Mar 4 at 19:50

1 Answer 1

2
\$\begingroup\$

The only difference between a class and a struct is that members within a struct are automatically public.

You could just create a class for all the input:

class Input
{
public:
    static bool isMainLoopActive;
    static bool isMoveRightPressed;
    ...
}

but a struct would also work, e.g.

struct Input
{
    static bool isMainLoopActive;
    static bool isMoveRightPressed;
    ...
}

The more important part is that they are static, since that would mean modifying them anywhere would change the values everywhere. Similar to global variables, also see Static keyword in c++.

The main difference between this and your method is that they are no longer global, but they do essentially the same thing. Instead of grabbing them normally, you would use something like Input::isMainLoopActive. This can also help code become more clean and understandable, as anyone can see its part of input, but thats just an example, you can change it to work with your scripts, and create multiple structs/classes if you need.

\$\endgroup\$
10
  • \$\begingroup\$ You could improve this answer by including an explanation describing why someone would want to use the strategy you described. \$\endgroup\$
    – Pikalek
    Commented Mar 3 at 23:37
  • \$\begingroup\$ @Pikalek I assumed he would understand from the question is there a data type that is better for that than struct? i provided an answer using a class, also im not really the best at c++ so i dont really know why it works either haha thats just how i would do it. \$\endgroup\$
    – Pow
    Commented Mar 3 at 23:51
  • \$\begingroup\$ I agree that's their question, but I don't understand why you would assume that they would know why your answer is better. If they had an intrinsic understanding that using a class was better than a struct, presumably they'd already be using that solution. You show how they could use a class, but there's no explanation why that's better than a struct. \$\endgroup\$
    – Pikalek
    Commented Mar 4 at 2:53
  • \$\begingroup\$ @Pikalek I updated it. \$\endgroup\$
    – Pow
    Commented Mar 4 at 10:01
  • \$\begingroup\$ @Pow The way I solved it was to create a class for input and simulation, then used the entire input class as a parameter in a function of of simulation and read out the booleans. This appeared to be the most "encapsulated" way I could find. What you describe is basically accessing the member variables directly? What is the most efficient method? \$\endgroup\$
    – snow_owl
    Commented Mar 4 at 19:48

You must log in to answer this question.

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