I'm coding the Input part of an engine and this is the "flow" of command:
1. (Startup) GameCode defines Commands such as MOVE_LEFT, MOVE_RIGHT
- This command is saved in a vector _commandList
2. OS sets the values via the Input class by passing an Input ID and Value
- This changes depending on the OS, so the programmer just have to call the input methods to set values to keys
3. Whenever the OS sets a new value by Input ID, the Input checks if there's a command assigned to it, if there is, it adds a new element in a vector specifying everything
- This is where the issue is, I'm using new everytime
4. During the Game Loop, before the Update(), I check all values in this vector (InputQueue) and update the _commandList current state.
- After this the Update() loop will have a list of all commands and their state during that time
It's working fine for key presses and such, since there's only a few commands to each game. But now I added the movement X/Y input code and the InputQueue vector is growning HUGE when I move the mouse.
In the Input Update function I do remove inputs after a time, but I'm worried that when I move the mouse, on Windows, I get a message for every pixel I moved the mouse to.
So if I move the mouse 10 pixels left, I get 10 messages and that's 10 new inputQueues, 10 new checks, and 10 new deletes... if it's half a 1920 screen, that's 1000 news and deletes and I that seems worrisome...
So I'd like to remove this new/delete in this function since it's called thousands of time per second so I was thinking in moving to an array of fixed size, but then there's the cons of iterating over all elements in the array instead of a dynamic vector one, and that I don't know how to deal with moving elements in the array.
This is how it is currently:
vector<Command*> _commandList; //commands that will be defined per game
vector<InputQueue*> _inputQueue; //vector to hold all input to be processed in the next UPDATE
InputKeys _inputKeys[300]; //each one of these has 3 float values
//function when any input from the OS comes to the engine
void Input::SetInput(int inputCode, float valueX, float valueY, float valueZ)
{
//Defining the inputKey values
inputKeys[inputCode].valueX = valueX;
inputKeys[inputCode].valueY = valueY;
inputKeys[inputCode].valueZ = valueZ;
//If there's a game command assigned to this input
//Add a new input to the queue to be processed in the next main Update()
if(inputKeys[inputCode].command != 0)
{
InputQueue* newInput = new InputQueue();
newInput->valueX = inputKeys[inputCode].valueX;
newInput->valueY = inputKeys[inputCode].valueY;
newInput->valueZ = inputKeys[inputCode].valueZ;
newInput->command = inputKeys[inputCode].command;
newInput->time = timeModule.GetRealTime();
_inputQueue.Add(newInput);
}
}
//function called right before the main GAME CODE update
//I update all the game commands' states so the GAME CODE can use them
void Input::Update(uint64 currentTime)
{
for(uint i = 0; i < _inputQueue.size(); i++)
{
if(_inputQueue[i]->time <= currentTime - inputTimeOnQueue)
{
delete _inputQueue[i];
_inputQueue.erase(_inputQueue.begin() + i, _inputQueue.begin() + i + 1);
i--;
continue;
}
if(_inputQueue[i]->inputTime >= _lastUpdate && _inputQueue[i]->inputTime <= currentTime)
{
Command* command = _inputQueue[i]->command;
//update the command state
command->valueX = _inputQueue[i]->valueX;
//etc
}
}
_lastUpdate = currentTime;
}
After this, during the main Update I can check the _commandList values and they'll be updated ready for checking.
I'd like to change it to something like this:
vector<Command*> _commandList; //commands that will be defined per game
InputQueue _inputQueue[20]; //I set a maximum of 20 input queues per update - anymore and I'll erase the older ones
InputKeys _inputKeys[300]; //each one of these has 3 float values
//function when any input from the OS comes to the engine
void Input::SetInput(int inputCode, float valueX, float valueY, float valueZ)
{
//Defining the inputKey values
inputKeys[inputCode].valueX = valueX;
inputKeys[inputCode].valueY = valueY;
inputKeys[inputCode].valueZ = valueZ;
//If there's a game command assigned to this input
//Add a new input to the queue to be processed in the next main Update()
if(inputKeys[inputCode].command != 0)
{
//I need to figure how to get this ? - probably an int and I'll check if it's 20 or > and reset to 0 if is
_inputQueue[?]->valueX = inputKeys[inputCode].valueX;
//etc
}
}
//function called right before the main GAME CODE update
//I update all the game commands' states so the GAME CODE can use them
void Input::Update(uint64 currentTime)
{
for(uint i = 0; i < 20; i++)
{
if(_inputQueue[i].time <= currentTime - inputTimeOnQueue)
{
//need to figure how to check current to last, considering the current might be 0~20
//and break so I don't loop through all 20 when it's not needed (not sure if I need to worry about this)
}
if(_inputQueue[i].inputTime >= _lastUpdate && _inputQueue[i].inputTime <= currentTime)
{
Command* command = _inputQueue[i].command;
//update the command state
command->valueX = _inputQueue[i].valueX;
//etc
}
}
_lastUpdate = currentTime;
}
Any suggestions on how can I get this to work or any other way to handle this?