Skip to main content
GameDev.net gamedev.net
🔒 Locked

Is using static variables for input engine evil?

Started by SolDirix Nov 30, 2013 at 12:25 AM 12 replies 6.4k views
Original Post
SolDirix
SolDirix

Hello, I am currently writing a game engine, and I am thinking of switching to static variables for my input engine. At first, I would pass the input engine over to objects that need it, for example the Player. Every time I create a player, i would pass the input engine over to it, like this:

player1->inputEngine = inputEngine;

However, I found this to be very tedious, and have decided to instead make all the variables in the Input engine class static, so that i wont have to copy the reference over. Would you consider that to be a good idea? I have a feeling that this might be the same as using global variables, which I know is evil, but what other alternative do I have?

View my game dev blog here!
Paradigm Shifter
Paradigm Shifter

1 line of code is tedious? What if you have 2 players on one machine using different input methods? What if you want ghost players e.g. in a racing game which playback previous stored input?

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
SolDirix
SolDirix

1 line of code is tedious? What if you have 2 players on one machine using different input methods? What if you want ghost players e.g. in a racing game which playback previous stored input?

I meant in the long run, what if i have a graphics engine, sound engine, and a hundred objects that all use different engines

View my game dev blog here!
Paradigm Shifter
Paradigm Shifter

I don't really know what you mean by engine in this context. Maybe the engine should have a container of all the objects it does stuff with instead?

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
SolDirix
SolDirix

I don't really know what you mean by engine in this context. Maybe the engine should have a container of all the objects it does stuff with instead?

I want the game loop to first check the input, then loop through all the game objects and call their update functions. the update functions will use the input data to determine what to do.

I'l give example:

class InputEngine

{

public:

InputEngine();

static bool leftPressed;

};

View my game dev blog here!
TheChubu
TheChubu

Yes it is! You're Hitler to me now.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"   My journals: dustArtemis ECS framework and 
Squared'D
Squared'D

I want the game loop to first check the input, then loop through all the game objects and call their update functions. the update functions will use the input data to determine what to do.
I'l give example:

class InputEngine
{
public:
InputEngine();
static bool leftPressed;
};


There's nothing evil about this, but there's no need to make that static. Static means that all instances will of InputEngine will all use the same variable. In another post you said each player gets a reference to the input engine so this doesn't make sense and isn't needed.
SolDirix
SolDirix

I want the game loop to first check the input, then loop through all the game objects and call their update functions. the update functions will use the input data to determine what to do.
I'l give example:

class InputEngine
{
public:
InputEngine();
static bool leftPressed;
};


There's nothing evil about this, but there's no need to make that static. Static means that all instances will of InputEngine will all use the same variable. In another post you said each player gets a reference to the input engine so this doesn't make sense and isn't needed.

no, I meant that if I don't pass it by reference I use static variables.

View my game dev blog here!
alvaro
alvaro

Global state is a bad idea in general, and I am sure it's easy to find descriptions of why with a web search. I would much rather pass references to the InputEngine everywhere (I don't love the name: How about InputState?), and thus make the dependence explicit.

Here's an alternative that I find elegant: Use signals and slots, so the part of the code that manages the input issues a signal whenever left is pressed, and the player's character object has a slot that moves it to the left. There is some code that instantiates all the objects and hooks the signals and the slots, and that's the only part of the code that knows about the connexion between the input and the player's character. That way the input handler doesn't know anything about the character and the character doesn't know anything about the input handler.

One of the strong points of an architecture like the one I just described is that it allows you to test the individual objects, by hooking the signals and the slots to dummy versions of the objects that should be on the other side. If you have a lot of global state, you can't possibly test any class in your code without instantiating all the global objects that it might make use of.

Squared'D
Squared'D



I want the game loop to first check the input, then loop through all the game objects and call their update functions. the update functions will use the input data to determine what to do.
I'l give example:
class InputEngine
{
public:
InputEngine();
static bool leftPressed;
};


There's nothing evil about this, but there's no need to make that static. Static means that all instances will of InputEngine will all use the same variable. In another post you said each player gets a reference to the input engine so this doesn't make sense and isn't needed.
no, I meant that if I don't pass it by reference I use static variables.

Sorry, I didn't really explain well. I accidently hit the post button (I'm on my phone) and then my wife made me go out before I could really fix it.

Statics and globals seem like an easy fix early, but often they get in the way later. Then you have statics and globals, too many things have access to the variables. This can cause problems later if you want to change your implementation. Only use globals if it "needs" to be accessed by everything which is very rare. In your case, only the player needs to access that data so it would be better to just pass it by reference to what needs it.
Squared'D
Squared'D

Yes it is! You're Hitler to me now.


This is actually very useful. Don't worry about something being evil, worry about how it will affect your code down the line and see why it's not good. Statics aren't bad, but they can lead to habits that make the code hard to maintain.
L. Spiro
L. Spiro

At first, I would pass the input engine over to objects that need it, for example the Player. Every time I create a player, i would pass the input engine over to it, like this:

player1->inputEngine = inputEngine;

You have bigger issues than the use of statics.
People think of input as events because in event-based applications they are.
Games are not event-based (there are of course events in games etc., but they are not event-based like applications are), and input in games is not an event.
You don’t press a key and then directly send that to a character and make it jump.

You collect input events into a queue and then the game manager reads them on each cycle, and then at a specific point inside the game loop you handle inputs and the jumping of the character. Additionally, letting the player character handle its own input is flawed; the character then needs to know more about its surroundings than it otherwise should. For example, if the character is in the air it should not be able to jump again. Now the character class needs to know about the physics engine to get information as to whether or not it is on the ground to decide if jumping is possible.

The character is a slave to the physics engine, not the other way around. Note of course that that does not mean the physics engine knows what a character is, it just understands certain properties that the character has and a higher-level class (such as the engine itself) gets just that data from the character class and feeds it to the physics engine.

Handling input is done at a much higher level than at the character’s level. The higher-level game class knows what characters are and what physics is and what the game rules are (hence it is the game class). I want to reiterate, the game class knows what the game rules are. The game class decides if the character is able to jump in its current situation and it is what contacts the physics engine and possibly other modules (maybe the player can’t jump while a certain light is on or when a sound is playing) before deciding, “Okay, you can jump.”

With your proposed design, the character class would be absolutely monolithic, knowing about the physics engine, world lights, and sound engine, when really all it needs to be is a normal game entity with a health bar.


L. Spiro
I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid
DishSoap
DishSoap


At first, I would pass the input engine over to objects that need it, for example the Player. Every time I create a player, i would pass the input engine over to it, like this: player1->inputEngine = inputEngine;

You have bigger issues than the use of statics.People think of input as events because in event-based applications they are.Games are not event-based (there are of course events in games etc., but they are not event-based like applications are), and input in games is not an event.You don’t press a key and then directly send that to a character and make it jump.You collect input events into a queue and then the game manager reads them on each cycle, and then at a specific point inside the game loop you handle inputs and the jumping of the character. Additionally, letting the player character handle its own input is flawed; the character then needs to know more about its surroundings then it otherwise should. For example, if the character is in the air it should not be able to jump again. Now the character class needs to know about the physics engine to get information as to whether or not it is on the ground to decide if jumping is possible.The character is a slave to the physics engine, not the other way around. Note of course that that does not mean the physics engine knows what a character is, it just understands certain properties that the character has and a higher-level class (such as the engine itself) gets just that data from the character class and feeds it to the physics engine.Handling input is done at a much higher level than at the character’s level. The higher-level game class knows what characters are and what physics is and what the game rules are (hence it is the game class). I want to reiterate, the game class knows what the game rules are. The game class decides if the character is able to jump in its current situation and it is what contacts the physics engine and possibly other modules (maybe the player can’t jump while a certain light is on or when a sound is playing) before deciding, “Okay, you can jump.”With your proposed design, the character class would be absolutely monolithic, knowing about the physics engine, world lights, and sound engine, when really all it needs to be is a normal game entity with a health bar.L. Spiro

This is a really good way of handling input.

I will be implementing this from now on in my own games. Thank you.
Satharis
Satharis
Static is a perfectly legitimate tool but I notice people tend to always use it for the completely wrong reasons.

Where would you actually use static? Well static essentially has different meanings depending on context, but the general idea is that there is only -one- for the program. Where would you need one of something? Personally I tend to use static only when something belongs to a class and every instance of the class is supposed to share that object. For instance I might have multiple window objects but each window might want to use the same D3D device, or something like that.

I've also used static for things like stringstreams that each instance of a class uses as a utility to format their strings, things like that. The usual wrong way is to make something static just because you think you'll only ever have one, not because there being one is a design decision. Of course there are a few exceptions, loggers are a good example, but that's because they're one of the few objects that every corner of a program will need to have access to and utilize.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.