View previous topic - View next topic |
Author |
Message |
Gardon Scholar
Joined: 05 Feb 2006 Posts: 157
|
Posted: Thu Feb 23, 2006 11:33 pm Post subject: Receiving input in-game |
[quote] |
|
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
|
|
Back to top |
|
|
RuneLancer Mage
Joined: 17 Jun 2005 Posts: 441
|
Posted: Fri Feb 24, 2006 1:32 am Post subject: |
[quote] |
|
There exist various methods of simply polling the keyboard for keys being held down. I'm not sure what SDL has though.
One simple way of handling things is to have an array which you'd fill every frame. Poll the keyboard for keys being held down at the start of the game loop. Then during the phase where you handle, say, movement, check which "held down" keys have been set and handle them accordingly. Don't forget to reset keys once they've been released.
This largely depends on your API's implementation of input routines though. Check the SDL docs for how it allows you to poll the keyboard (or any other input device for that matter) and look things up in-game as needed. _________________ Endless Saga
An OpenGL RPG in the making. Now with new hosting!
|
|
Back to top |
|
|
Ninkazu Demon Hunter
Joined: 08 Aug 2002 Posts: 945 Location: Location:
|
|
Back to top |
|
|
RuneLancer Mage
Joined: 17 Jun 2005 Posts: 441
|
Posted: Fri Feb 24, 2006 2:59 am Post subject: |
[quote] |
|
Ahhh, excellent. That's perfect. :)
Well, at this point your job should be pretty obvious. Just poll the keyboard with the method Ninkazu linked to and, during the update phase of your game loop, see what's being held down. _________________ Endless Saga
An OpenGL RPG in the making. Now with new hosting!
|
|
Back to top |
|
|
Nephilim Mage
Joined: 20 Jun 2002 Posts: 414
|
Posted: Fri Feb 24, 2006 3:39 am Post subject: |
[quote] |
|
Note that this sort of routine probably only gives you the raw "keys held down" by the player. That's not going to cut it for a higher-level coordination of what a player is interacting with. For instance, if you have a key to toggle some option, then you're also going to have to keep track of "keyhandled" type concepts to keep from flashing between the options every frame the key is held down. In this case, once you toggle an option, you're going to want to ignore that key being down until the player lets up on it.
To do things like this, you're probably going to want to write some sort of input manager that sits between that raw key polling and your game engine. You only want your game logic engine to have to deal with abstract commands like "the player pressed the menu button", not all the gory details of raw key processing. This also assists with tasks like letting the player assign keys to different actions, routing keyboard input to the currently active interface, or allowing both keyboard and joystick input.
I talk about creating just such an object in one of the articles I wrote about the development of Sacraments. You can read it here. It's aimed at Director developers, so it may not be the best way to handle game input in SDL, but it should at least give you some things to think about in terms of abstracting your raw key input away from your game logic. _________________ Visit the Sacraments web site to play the game and read articles about its development.
|
|
Back to top |
|
|
DrunkenCoder Demon Hunter
Joined: 29 May 2002 Posts: 559
|
Posted: Fri Feb 24, 2006 12:33 pm Post subject: |
[quote] |
|
Friendly advice, input handling should be event driven not act in a polled by frame basis. _________________ If there's life after death there is no death, if there's no death we never live. | ENTP
|
|
Back to top |
|
|
NyanNyanKoneko Wandering Minstrel
Joined: 12 Dec 2005 Posts: 98
|
Posted: Thu Mar 16, 2006 10:05 am Post subject: |
[quote] |
|
For games, you usually need to figure out three things...
1) What keys were just pressed down this frame?
2) What keys are being held down?
3) What keys were released this frame?
To do this, you can create 2 character arrays. Each array stores all possible keys. One is an array for the current frame, and the other is for the last frame.
So you would have...
Code: |
char keys_prev_frame[TOTAL_KEYS];
char keys_this_frame[TOTAL_KEYS];
...
void UpdateInput()
{
memcpy(keys_prev_frame, keys_this_frame, TOTAL_KEYS);
GetCurrentKeyState(keys_this_frame);
}
|
GetCurrentKeyState() is a made-up function to fill keys_this_frame with keyboard data.
To check to see if a key was just pressed, check to see that it wasn't pressed the last frame, but it was pressed for this frame. Example:
Code: |
bool KeyPressThisFrameOnly(int key)
{
return (!keys_prev_frame[key] && keys_this_frame[key]);
}
|
To see if a key is being held down, just check to see if the key is down for this frame. To check if a key has been released, check to see if it was down the previous frame, but up this frame.
Some input schemes allow messages to be sent to the program if a key is pressed down, but the above method is pretty universal. Just remember to call UpdateInput() before every frame. _________________ INFP
|
|
Back to top |
|
|
DrunkenCoder Demon Hunter
Joined: 29 May 2002 Posts: 559
|
Posted: Thu Mar 16, 2006 4:42 pm Post subject: |
[quote] |
|
NyanNyanKoneko wrote: | For games, you usually need to figure out three things...
1) What keys were just pressed down this frame?
2) What keys are being held down?
3) What keys were released this frame?
|
This is quite a grave misconception that will only give you headaches down the road.
The only time "per-frame" (mostly) anything is a good solution is when doing console programming where you know the target platform will never change. _________________ If there's life after death there is no death, if there's no death we never live. | ENTP
|
|
Back to top |
|
|
NyanNyanKoneko Wandering Minstrel
Joined: 12 Dec 2005 Posts: 98
|
Posted: Thu Mar 16, 2006 7:23 pm Post subject: |
[quote] |
|
Quote: | The only time "per-frame" (mostly) anything is a good solution is when doing console programming where you know the target platform will never change. |
How so? How do you program a video game without drawing frames?
A frame usually consists of doing logic then drawing, which is sort of the basic structure of all the games I've written. ^_^
I suppose more realistically, you'd only need to know that stuff per logic loop if you're skipping the drawing of frames, but that's without saying. :) _________________ INFP
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: Thu Mar 16, 2006 7:57 pm Post subject: |
[quote] |
|
The better way to structure is to have a separation between the display logic and everything else: the only thing tied to the "frame" is the display logic; everything else is processed either by handling events (either directly supported by the language, or via some form of Observer/Callback/MVC model) or by timers. All that the display logic knows is a snapshot of the current state of whatever engine it is (indirectly) tied to at the moment in time that it decides to redisplay itself.
This has the advantage that all data within the game will be continuously updated regardless of what is going on in video memory.
Of course, it would probably also make sense, depending upon how onerous the processes are, to throw certain bottleneck operations into separate threads to prevent event handling lag. _________________ "...LeoDraco is a pompus git..." -- Mandrake
|
|
Back to top |
|
|
RuneLancer Mage
Joined: 17 Jun 2005 Posts: 441
|
Posted: Fri Mar 17, 2006 1:47 am Post subject: |
[quote] |
|
NyanNyanKoneko wrote: | A frame usually consists of doing logic then drawing, which is sort of the basic structure of all the games I've written. ^_^ |
That's not incorrect, but limiting yourself like this is no longer acceptable for higher-quality material. For instance, what happens if a lengthy operation takes place (say, saving a screenshot; by "lengthy" I mean maybe 250-300ms) and the user hits a key during that time? If you poll the keyboard, that keystroke may not go through because the user would've released the key long before that 250ms delay is up (seriously, tap a key and see how long it's being held down... probably less than 1/5th that long, if not less.)
Pretty much every modern OS I know of has a mechanism (typically something akin to Windows' well-known message-based events) that allows it to maintain a queue of events that can take place while your app is busy doing something else. Taking advantage of this is a necessity; in the same screenshot example, the message queue will have a message in it stating that, say, the player hit space to leap over a bullet during the time your app was busy saving the screenshot to disk.
('Course, you could just use a thread once you've rendered the screen to a texture so the game can continue while your lil' worker thread is busy doing the conversion/image compression and disk access, but that's not the point of this example. Consider "slow PC rendering a particularly intense graphic effect" if you prefer; isn't it annoying when your game won't respond because a whole slew of glowing particles from the enemy's cannon is slowing the game to a crawl and your keystrokes go completely unaccounted for?)
Careful seperation of your game's various processes and proper use of your dev platform's various sync mechanisms is essential to giving the player a hassle-free, smooth, professional experience. Of course if your aspirations are to just make a decent game and not some AAA title, handling everything in a linear fashion works too, but you'll have to deal with quirks. _________________ Endless Saga
An OpenGL RPG in the making. Now with new hosting!
|
|
Back to top |
|
|
zenogais Slightly Deformed Faerie Princess
Joined: 10 Jan 2006 Posts: 34
|
Posted: Fri Mar 17, 2006 4:43 am Post subject: |
[quote] |
|
Once again you need to get on board with the SDL_PollEvent while loop. SDL automatically queues all the events for you, all you have to do is read them all out during the SDL_PollEvent loop and act on them.
Basically what I've been doing is allowing objects to be attached to my input class as mouse listener or keyboard listener objects, then when the input Update() function is called (which happens every frame) I use while(SDL_PollEvent()) and any keyboard or mouse events are dispatched to all the appropriate listeners.
This gets rid of all input problems you might have been having (weird thing where you can't move the mouse and use the keyboard at the same time), and has the added benefit of making it really easy for different objects to handle different input events.
|
|
Back to top |
|
|
NyanNyanKoneko Wandering Minstrel
Joined: 12 Dec 2005 Posts: 98
|
Posted: Fri Mar 17, 2006 8:08 am Post subject: |
[quote] |
|
There are two ways to handle input: sampling (polling) or event-driven. There's no necessity, as you call it, to use event-driven input handling, unless you're absolutely planning to recieve multiple input strokes during a single frame. It's a matter of choice for the developer.
There are also problems that can arise from event driven input as well. Take for example, a player presses a key to fire, the user switches to another window, then lets go of the key to fire. Your game window may not recieve that message to quit firing. Not to mention, it can increase code complexity.
I find that missed input from a frame that takes more than 1/5 of a second to draw (5 frames per second draw rate) doesn't really matter most of the time. It's either not noticable or not consequential.
It's more of a personal choice the way you want to handle input. There's no right way or wrong way. If your game runs smoothly either way, you're set. :)
I just find using key states simplifies code a bit, and works well for most projects. _________________ INFP
|
|
Back to top |
|
|
DrunkenCoder Demon Hunter
Joined: 29 May 2002 Posts: 559
|
Posted: Fri Mar 17, 2006 8:43 am Post subject: |
[quote] |
|
NyanNyanKoneko wrote: |
I just find using key states simplifies code a bit, and works well for most projects. |
It's simple initially that's why people tend to use it, the problem is that over time it actually makes things more complex and people over time seems to duct tape events onto polling schemes, iv'e seen people struggling with getting text input working with polled solutions and they for the most part end up extremly clunky inefficent and complex.
But I guess you're basing your physics updates on frame drawing time to... _________________ If there's life after death there is no death, if there's no death we never live. | ENTP
|
|
Back to top |
|
|
NyanNyanKoneko Wandering Minstrel
Joined: 12 Dec 2005 Posts: 98
|
Posted: Fri Mar 17, 2006 9:06 am Post subject: |
[quote] |
|
You're right, it can get very tricky handling stuff like key-repeats using a simple polling. Plus it's slower since instead of checking for a single key press, you have to check all the keys to see if one had been pressed. It gets even worse if you're not saving your ascii conversions in your polling arrays. :)
If you're going to allow the user to type, definately use event-driven input. _________________ INFP
|
|
Back to top |
|
|