Sign in to follow this  
Drew_Benton

Unity SDL Input Library & Input Discussion [renamed]

Recommended Posts

Drew_Benton    1861
Bold words, but I challenge you to prove me wrong [grin]. I have finally made a SDL input library that wraps up a lot of the functionality of using input in SDL (of which I have numerous posts scattered about covering all of the various aspects). Anyways, here it is, it comes with the library header and cpp file as well as a complete demo cpp file showing how to use it all. I will be adding it to my web page eventually. If you have any questions or comments about it, feel free to share! If you find any bugs, annoyances, or anything that you'd like to see changed, I'm open to all suggestions as well. I will be working with this a bit as part of my SDL engine I am working on, so I will be adding fixes and updates here and there. I will also make some more advanced demos of showing what you can do with this as well for those looking for some neat things to do with it. Enjoy! [smile] Download Input Library + Demo (7.98kb)
Now for some quick FAQs: Q - How do I integrate it into my current SDL project A - Integrating the library into your current project is very simple. Here are the steps: 1. #include "Input.h" 2. Add Input.cpp to the project work space so it is compiled 3. Create a derived class from the Input class 4. Overload the member functions you will want to use (OnKeyDown, OnKeyUp, OnMouseMove, OnMouseButtonDown, OnMouseButtonUp, OnMouseWheelUp, and OnMouseWheelDown) 5. In your event polling loop, call the Poll function, passing in each event. 6. After the polling has been completed, call the Update function. 7. Now you are ready to use the class and its functions! Q - What license is this released under A- The good ole' ZLib license, which means you can use this in your [4E4] entry without any problems if you take the SDL approach. Still note that SDL is released under the LPGL license and you must link dynamically to it. Q - Do I have to derive from the Input class? A - No. The functions are non-pure virtuals, so it is optional if you want to use that functionality. Q - Speaking of functionality, what does this input library provide A - Right now it has complete functionality for the mouse and keyboard. Joystick functionality will be added later. Keyboard Functions: IsKeyDown, SetKeyUp, SetKeyDown, OnKeyDown, OnKeyUp Mouse Functions: GetMouseX, GetMouseY, SetMouseX, SetMouseY, SetMouseXY, IsButtonDown, SetButtonUp, SetButtonDown, OnMouseMove, OnMouseButtonDown, OnMouseButtonUp, OnMouseWheelUp, OnMouseWheelDown Q - So how does it all work? A - This input system works to be as accurate as possible, which is why the Poll method has to be called. The library uses a buffered input style of processing. As events are sent into the Poll function, if they are input events, they are send to the input buffer vector. After all have been collected, the Update function then goes though and processes all of the data. It will call the On_XXX functions when necessary for each event and then remove the events from the buffer. The system is made for advance users as well, so if events need to not be removed from the buffer, that too is possible with the design (return false instead of true in the On_XXX function). Q - Any other extras? A - Yes! Each event comes with a time stamp if you want to use that for input tracking for use in a replay system or whatever you want to do. That information is avaliable in the On_XXX functions. Next is the way the SetMouseX/Y/XY functions work. It is known that when you simply call SDL_WarpMouse events are generated which throw off your camera looking in FPS games. I have come up with a little way of taking care of that so that problem is no longer and issue. Finally the library is made so it is very clean, easy to use, and well documented. Perhaps a little over commented, but there is no way anyone reading it will have no idea of what is going on. [edit]Updated link to my UTD space...I really need to fix all my links on GD [Edited by - Drew_Benton on December 13, 2005 3:39:07 PM]

Share this post


Link to post
Share on other sites
Ademan555    361
Very cool Drew, i'll be sure to check it out when i get done with this yard work im avoiding :-) But out of curiousity, have sdl's events been deemed reliable enough for game use?

cheers
-Dan

Share this post


Link to post
Share on other sites
clayasaurus    139
I have one too http://svn.dsource.org/projects/warbots/trunk/current/core/input.d , but it is written in the D language. You still should be able to understand it, to a certain degree. It doesn't only handle all mouse/input, it handles screen resizing (using input to resize the screen), to test against keyHit (one action per key) vs KeyDown (for machine gun effect), mouseHit, mouseDown, keeping track of 2D coordinates vs 3D ones for the mouse and keeping 2D mouse coordinates relitive to screen size, and the handling of all modifiers plus support for typing, returning the character of the last key you hit, so that you can type in an input box.

edit: forgot to mention, handles wheelUp and wheelDown

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by Endogenous
Looks nice and clean, if I use it I'll be sure to tell you about any bugs.
All in all, looks like a handy little class. :)


Thanks, if you do use it tell me how it works for you. [wink]

Quote:
Original post by Ademan555
Very cool Drew, i'll be sure to check it out when i get done with this yard work im avoiding :-) But out of curiousity, have sdl's events been deemed reliable enough for game use?


With the default SDL event processing, probabally not for high event games. However, someone has made a little LPGL library that makes SDL process more events, so it is much faster. What I am talking about is FastEvents. At first I thought it didn't do much, but I just tried it out, and wow, it works great. Without the library on the thread4.c program (with SDL_net removed) the app was processing 20,178.346496 events a second. However, when the library was used, the events processed a second rocketed to 54067.893211. And that test was the app just running without any events being sent! When I sent in a lot of events though mouse and keyboard, the numbers were a little lower, but it ended up around 19k vs 53k. Now there's a big difference between those two numbers, so I can say at least, I am not worried about not being able to handle SDL events anymore [smile].

Quote:
Original post by clayasaurus
I have one too, but it is written in the D language. You still should be able to understand it, to a certain degree.


Cool! D looks really similar to C [lol]. Not too bad of a library either [wink]

Anyways, if anyone uses this and finds it useful, I'd love to hear about it. I have not update anything yet officially, but I have added in joystick support. I'm still testing that out and debugging it, but when I get that done I will put the complete library here. I'm also working on a SDL game engine (which is why I made this input library) so I'll just tack on that project if it's done to this thread and add it my sig.

Share this post


Link to post
Share on other sites
Promit    13246
Not bad, not bad, but...[grin]

I use the asynchronous input system, and read the entire keyboard once per frame. Buffer the results one frame, and you can determine if a key was just pressed/unpressed, and whether it's down right now or not. No callbacks, those things are damned annoying. So if you want to know what's going on, instantiate a keyboard and a mouse and just read from them.

I've been meaning to write a layer that abstracts away the keyboard and mouse and joysticks, haven't gotten around to it yet.

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by Promit
I use the asynchronous input system, and read the entire keyboard once per frame. Buffer the results one frame, and you can determine if a key was just pressed/unpressed, and whether it's down right now or not. No callbacks, those things are damned annoying. So if you want to know what's going on, instantiate a keyboard and a mouse and just read from them.


Thanks! [wink] My old methods of input worked in a similar way, but I did not think about simply buffering those results - I just used them as they came. Hmmmm, that's a good idea [lol]. What I've read though is that it's possible that you end up missing events with though functions though (something from Sam on the mailing list) when you just use the data as is, but your buffering idea should take away that disadvantage. I have not had a project that I've used any of this stuff in yet to compare the two, so I will see about that. Promit, kudos for the good ideas as always [grin].

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by evolutional
This is kinda like my input system for my upcoming 4E4 game, except I'm using GLFW and mine is waaaaaay cooler :P (tehe).


Shush you! [grin] I remember last time I used GLFW, basically all the input functions are there right? You just gotta wrap them up into a nice neat class, correct? I think in those little learn GLFW examples I've seen, the input can get quite klunky if it's not wrapped up. I'll have to take a look at your libary sometime later to see just how cool it is [wink] Are you gonna make your code avaliable later on? (And I have still not looked that the old messaging code you sent me like 4 months ago [headshake])

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by evolutional
provide async input.


Since you are the second one to mention that in this thread, is async input the most preferred method for games? Is it because it's more on demand or what?

While I am at it, I was also going to ask what you guys think aout joystick support? I mean it's always there, but rarely do I see people use it. Is it good to just have it there in case, or should developers not bother and let the user add it in if they wanted to? For my engine at least, joystick support is already there and all, so I've decided to add it in.

Share this post


Link to post
Share on other sites
evolutional    1393
I don't know if I'm a special case, but I've found it useful to have both.

For example, my game input is managed with IInputHandlers, which are registered to receive input events. This is all well and good when it comes to checking for 'up, down, left, right, etc' presses and releases, but short of buffering the events locally for each object, how will you say "three keys are pressed at once"?

Share this post


Link to post
Share on other sites
Drew_Benton    1861
The thing is though, by doing it event based, as long as you track it that is, you will achieve the same thing. Right now, as my input system is, the On_XXX are for those events that happen the first time, so they are like callbacks as Promit mentioned, but they aren't themsevles callbacks. They are functions that are just called on an event (which is done though the update function after all the events have been buffered). Basically, that is for functionality that the WM_CHAR provides. You can just process key by key if you need to. Otherwise, everything is as what the so called async functions provide, even though my system is event based. So I can have something like:

if( inputClass->IsKeyDown( SDLK_a ) && inputClass->IsKeyDown( SDLK_s ) && inputClass->IsKeyDown( SDLK_d ) )
abort();

And it works as expected. Does the fact that I store all the buffered input and process thatt way, to which I have a means similar to async input make those functions async? Not that it matters, just something to think about [wink]. In the class I do have:

std::vector<bool> mouseButtonStates;
std::vector<bool> keyStates;

that store the information so I guess I do have both means employed in my system, just though buffered events.

Share this post


Link to post
Share on other sites
TheMoebius    112
Hey guys, I'm writing the input class for an open source game I'm working on called Epiar ( www.epiar.net ) and I'm looking for your input on my methods for handling the whole input system. I'm attaching the same cInput class proposal that I sent to the other developers.

Because the current cInput needs to be reworked to make more extensible and easier to add actions, etc. My newly proposed cInput class I think does the job and also gets rid of keys.cpp. It uses Drew Benton's SDL Input Library found at http://www.gamedev.net/community/forums/topic.asp?topic_id=328994

Now I want your comments and feedback on how you think it will work and don't be nice. I'm just figuring this stuff out as I go so I'm sure theres room for improvement. Since I'm a bit of a programming n00b theres probably a bunch of syntactical errors and I'm not totally sure if I used enum right, but those are minor details that I can work out when I get the compile errors. I'm really interested in the over all method of doing this.



keys.xml has declarations like:
<controlsFlyMode>
<fire1>
<device>mou</device>
<value>1</value>
</fire1>
<orbit>
<device>key</device>
<value>9</device>
</orbit>
</controlsFlyMode>

<controlsSelectMode>
<select>
<device>mou</device>
<value>1</value>
</select>
<fire1>
<device>key</device>
<value>64</value>
</fire1>
</controlsSelectMode>

There are two different control modes because we (or at least I?) were/was talking
about being able to toggle between flying mode where you'd use the mouse to point
the ship and the mouse1 button would be fire, etc. But then you could hit tab to
select other ships, interact with the HUD, open the right click menu, etc. Many of
the controls would be the same,but it can pretty easily be taken out.

The value for the keyboard is the int value of SDL_a or KMOD_CTRL or whatever.
They're just plain and simple ints. The SDL documentation has these values in a
table somewhere. The values for the mouse are simply the button numbers.



LoadConfig() fills the following arrays with values from the keys config file. Of
course the index matches the enumed action values like ACT_FIRE1 and ACT_ORBIT.
int flyModeDevices[numberOfKeys];
int flyModeValues[numberOfKeys];
int selectModeDevices[numberOfKeys];
int selectModeValues[numberOfKeys];


Problems to solve that I can think of off the top of my head:
* We should figure out an easy way to make it case insensetive. It's also probably
not terribly hard and could be done either in LoadConfig() or in GetActionValue(),
so SDLK_a and SDLK_A return the same int.
* I don't show anything for setting and getting new keys or input, but thats fairly
trivial.
* Alternatively the XML doc could be laid out like <fire1>mou1</fire1><orbit>key9</orbit>
depending on how cConfig works, I can't remember at the moment. And then you could
just chop it up in LoadConfig or something.
* This input library doesn't currently support joystick functions, but the developer
said he was going to add it and even if it doesn't finish it in time, we could do
it ourselves.

-----------------------------------------------------------------------------------

// The following uses Drew Benton's "SDL input library" found at
// http://www.gamedev.net/community/forums/topic.asp?topic_id=328994

enum actions {
ACT_FIRE1,
ACT_ORBIT
//etc,etc
}

cInput::cInput() {
SDL_Event Event;
LoadConfig("keys.xml") //see note above
Input inputClass; //Drew Benton's SDL Input Library
//I'm sure there will be more to add here
}

void cInput::LoadConfig(string configFile) {
//see note above
}

int cInput::GetActionDevice(int action) {
if (flyMode == true) {
return flyModeDevice[action];
}
else {
return selectModeDevice[action];
}
}

int cInput::GetActionValue(int action) {
if (flyMode == true) {
return flyModeValue[action];
}
else {
return selectModeValue[action];
}
}

bool cInput::testAction (int thisAction) {
switch( GetActionDevice(thisAction) ) {
case 1:
if (inputClass.isKeyPressed( GetActionValue(thisAction) ) ) {
return true;
}
case 2:
if (inputClass.isButtonPressed( GetActionValue(thisAction) ) ) {
return true;
}
break;
case 3:
//no joystick support in inputClass yet, but its going to be added
break;
}
return false;
}

void cInput::resetKey (int thisAction) {
// works much the same way as testAction, but it uses setKeyUp() or setButtonUp()
// so the action happens only once.
}



//this function is called in Epiar's update cycle
void cInput::Update() {

//this chunk of code is from Drew Benton's demo included with the library
while ( SDL_PollEvent(&Event) )
{
if ( Event.type == SDL_QUIT ){
//do whatever we have to do to tell Epiar to quit
}

// Here we first call the Poll function with the current event
// inside our polling loop
InputClass.Poll(Event);
}

// Then we just have to call the update function to take the data
// from the Poll event and update the class
InputClass.Update();




//Now test each game action.
if (testAction(ACT_FIRE1)) {
player->fireWeapon(1);
}

if (testAction(ACT_ORBIT)) {
player->orbit(target);
resetKey(ACT_ORBIT); //for one time "toggle" type actions
}

if (testAction(ACT_SELECT)) {
//get the target by looking at whatever is at the current mouse location.
//get the mouse location using InputClass.GetMouseX() and InputClass.GetMouseY()
player->setTarget(something);
resetKey(ACT_SELECT);

}




[Edited by - TheMoebius on July 31, 2005 2:22:34 PM]

Share this post


Link to post
Share on other sites
DanEE    122
@Drew:
Is there still some place where we can download this library? I'm very interrested in it especially in its design.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this