# Receiving in-game input

9 replies to this topic

### #1gardon

Valued Member

• Members
• 282 posts

Posted 23 February 2006 - 11:33 PM

Ok, so I've never had to deal with this before. With the game acting in real time, constantly updating itself and moving things around, how would I handle input?

I'm using SDL, so it's not like Windows where I can handle message box functions and the like, and I'm unsure of how to do it.

If the game is constantly looping... frame by frame by frame, how do I prompt for input, read in that input, and store it over multiple frames?

Thanks,

Jason

### #2Reedbeta

DevMaster Staff

• 5308 posts
• LocationSanta Clara, CA

Posted 23 February 2006 - 11:39 PM

I assume you're talking about allowing users to type in things like a console, as opposed to "move left if the left arrow key is down"-type stuff? This is called buffered input, and normally your computer's device drivers handle it for you, but in games you have to do it yourself.

Basically, keep an array of booleans, one for each key, and check the state of each one every frame. You can use this to detect 'events' like key press (key was up last frame, now it's down) and key released. From there you can build your own buffered input system, i.e. on key press, check if there's an active 'text box' and add the character to it. You'll have to include logic for backspacing, shift and capslock, tabs and newlines etc yourself.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #3gardon

Valued Member

• Members
• 282 posts

Posted 23 February 2006 - 11:46 PM

Fast reply! Yes, that's what I meant, like console and such.

So what I was thinking of is only allowing input if the user pressed the Enter key (which can be surpassed by specifically declaring console-allow function), which activates a variable.

I can have a switch statement of keypressed, and if that variable is set, I'll see what keys are currently pressed.

the only prloblem with that though is that I can't tell which keys are pressed at what time. I do currently have a boolean array of keypresses:

bool keysHeld[323]

that keeps track of what keys are currently held down. Do I have to go back and specifically design something (or use SDL's keypress functions) to see what key was pressed when?

I mean, I'd have to make one huge ass statement,

jason

### #4Wernaeh

Senior Member

• Members
• 368 posts

Posted 24 February 2006 - 01:07 AM

Hi there :)

There are several options to get around a huge switch statement.
Usually, you should create an enum containing all possible keys,
and then just write a few methods to query an arbitrary key,
i.e.


bool IsKeyDown(EInputKey key)

{

return bKeyDownState[key];

}

bool IsKeyHit(EInputKey key)

{

return !bKeyDownStateLast[key] && bKeyDownState[key];

}



which looks lots nicer than a switch / or single calls for each key.

bKeyDownStateLast is simply created by copying over the bKeyDownState array before you update it.

For translating EInputKey values into ASCII or similiar for input into text boxes, I'd use another field, and fill it with the ascii representation for the input keys, i.e.


enum EInputKeys

{

eIK_ArrowUp,

eIK_ArrowDown,

/* ... */

eIK_A,

eIK_B,

eIK_C,

/* ...*/

eIK_InputKeyCount

};

const char* pAsciiScan[eIK_InputKeyCount] =

{  "", "", /* ... */, "a", "b", "c", /* ... */ };



Now you only need to look up your input key within the ascii scan array, and then instantly get the appropriate character code.
The only thing this system does not handle correctly is modifiers (i.e. shift keys, arrow keys, ...) I'd put an empty string in for those, and then handle them specially in the actual input code (which usually results in 3 or 4 handleable extra cases...)

Hope this helps,
Cheers,
- Wernaeh

### #5gardon

Valued Member

• Members
• 282 posts

Posted 24 February 2006 - 04:15 AM

kind of.... how will that tell me the order they are pressed in though?

Jason

### #6Wernaeh

Senior Member

• Members
• 368 posts

Posted 24 February 2006 - 04:39 AM

What do you mean by the order they are pressed in ? :)

I take it you are not doing an event - but rather a cycle-based input testing.
That is, you should somewhere have a loop of some sort where you regularly update your input, something like

while (pGame->IsRunning())
{
GetInput();
DoFancyGameLogics();
Render();
}

/* .... */

void GetInput()
{
memcpy(pLastKeyState, pKeyState, iKeyCount);

// Call the operating system functions for retrieving the
// current state of all your keys.
OperatingSystemGetInputForAllKeys(pKeyState, iKeyCount);
}



To determine which key was pressed first is now the responsibility of the client application using this interface, since it doesn't save when and for how long a key was pressed - only if it is currently down, and if it was down the last tick. For example, if you wanted the user to first press the A key, then the B key, the caller would have to declare some variable to note for himself when the appropriate keys were pressed, and react accordingly, i.e.

if (state == eST_WaitingForA)
{
if (KeyPressed(eIK_KeyA))
{
state = eST_WaitingForB;
}
}
if (state == eST_WaitingForB)
{
if (KeyPressed(eIK_B))
{
React();
}
}


Note this is ugly for everything that goes over more than just few states.
If you want to recognize a string the user entered, store an index to the next symbol that the user should enter. If the appropriate key is hit, go to the next symbol index, otherwise, reset the running index.

What do you need to know the key order for anyways ? :)
Usually, for caps lock, alt, and control keys, the input order isn't relevant.
Just use capitals if the shift key is down, and lowercase if it isn't.

Also note that for buffered input systems, it is always possible that there is more than just one keypress at the same time. Just imagine the user hits 2 keys in the timeframe of 20ms that your main loop runs.

Hope this helps.
Cheers,
- Wernaeh

### #7Wernaeh

Senior Member

• Members
• 368 posts

Posted 24 February 2006 - 04:46 AM

Anyways, for console input, you now may do something like

CString console_line;
int console_position;

void UpdateConsole()
{
for (int i = 0;
i < eIK_KeyCount;
++i)
{
if (IsKeyHit((EInputKey)i)
{

{
/* Some special char (arrows, del, etc) */
/* So handle appropriately */
if (i == eIK_ArrowLeft)
{
--console_position;
}
/* other special chars here.. */
}
else
{
/* A normal ascii char */
if (IsKeyPressed(eIK_Shift))
{
/* Shift pressed, so it needs to go uppercase */
}

/* Add char to console line at current position */
}
}
}
}


Hope that helps,
Cheers,
- Wernaeh

### #8gardon

Valued Member

• Members
• 282 posts

Posted 24 February 2006 - 05:50 AM

What about lag? Would that constant loop of 323 keys every frame really slow down gameplay?

I basically want this for text input, like for commands and such.

Is there any other way to do it? I don't want to have to stop my game to receive input.

Thanks,

Jason

### #9Reedbeta

DevMaster Staff

• 5308 posts
• LocationSanta Clara, CA

Posted 24 February 2006 - 06:03 AM

No, it's not going to slow you down anything measurable.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #10Wernaeh

Senior Member

• Members
• 368 posts

Posted 24 February 2006 - 06:10 AM

To detail Reedbeta's post, your average computer these days runs at 1,8 Ghz, not counting any internal optimizations, special instructions, and similiar. Considering any slowdowns (operation system, cache misses, paging, ...), you still have _at least_ 1 Ghz left for pure application logic.

Consider a game running at 60 logic fps. This leaves you with 1 / 60 = 30 Mhz per frame maximal time. If you further assume a single test operation takes 20 Hz (which is really much), and you use 300 of these, you end up with 6 khz taken.
6 Khz / 30 Mhz is around 0,02 percent of the entire time your logic may take to still fit in the desired 60 fps time window.

This is a _very_ naive calculation, but should show you the order of cpu load we're talking about here.

Cheers,
- Wernaeh

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users