Human Computer Interface

Smooth input is a very important aspect of a good gaming experience. you want to have your system respond seamlessly just as you would expect. Today I will talk about input devices and how you might see them integrated into a gaming engine, I will mostly talk about traditional inputs( controllers, mouse, keyboard). although you should always keep an open mind towards new was of interacting with computers and how this can effect gameplay.Buttons vs Analog Axes Many Controller interfaces will include Buttons to press and Thumb sticks. the Buttons have only two states, Up and Down, but it is possible to add a function to detect if a button has been pressed for an extended period of time. Analog axes on the other hand take in a weighted value based on the degree to which a trigger is pressed or the two dimensional position of a joystick. this is useful for controlling things like character speed, without to much effort from the player.Most engines would define the input device as a struct where all digital buttons are stored in a single 16 bit unsigned integer.(word)typedef struct _INPUT_GAMEPAD{Word buttons;byte leftTrigger;byte rightTrigger;short leftThumbX;short leftThumbY;short rightThumbX;short rightThumbY;} INPUT_GAMEPAD'if a button state is down it is represented by a 0, if it is up it is represented with 1. this is how we can check the state of each trigger and use it to cause certain actions within the game. Also the thumb sticks are represented by 16 bit signed integers.(short) and triggers are 8 unsigned (bytes). This setup allows for proper physics calculations as character direction is dependent on Cartesian coordinates and triggers are typically more of a magnitude.button Up and Down eventsSince the events are stored in single integer you will need to comapare each bit to the others to find out what button is pressed. typically you can use the AND operator to compare say the A button state with the full set, and if it returns 1 you know it is being pressed. For more involved inputs we will want 2 different containers for buttonUp events and buttonDown.  in this case we can use the XOR operator to compare the previous frame with the current to return 1 for all buttons that have changed.ChordsChords specify a group of buttons being pressed at the same time to cause their own unique behavior. This is commonly used in figting games where the sheer number of moves don't amount to the buttons available.OGRE uses OIS as its main input system, a very powerful library that supports several input devices. One thing I noticed perusing the user forums  was that it does not directly recognize different cases. Since I didn't want to just map out the triggers to different keys which would have been way to confusing. I developed my own chord to know if the letter was capital or not.if(OGRE_CORE->mKeyboard->isKeyDown(OIS::KC_Q)){if(OGRE_CORE->mKeyboard->isKeyDown(OIS::KC_LSHIFT)){q+=dt;pinkyTipRotateNode->setOrientation(Quaternion(Radian(Degree(q)),Vector3::UNIT_Z));}else{q-=dt;pinkyTipRotateNode->setOrientation(Quaternion(Radian(Degree(q)),Vector3::UNIT_Z));}}I am just going to go on the record here and say this is probably a bad way to make chords. After further research I found that you should compare the states through a bitwise oprator, like how I explained earlier except instead of just checking for one key you check for 2.Rapid tapping and sequence detectionOften times we will want to limit the amount of actions a player can do in a given time frame. In competitive gaming, cool down times are a very important aspect to balancing and keeping the game "fair".this can be achieved by checking the time between button presses:if (input == Abutton){if(ValidGesture){performAction();}}where valid gesture would be defined by a checking the deltaTime from the last keypress and only return true if that deltaTime is greater than the cool down time.deltaTime= globalTime() - timeSinceLastKeypress;return (deltaTime< coolDown);Sequencing buttons is a little different.  A very clever technique I learned is to store the button IDs in an array the size of the sequence,egsuperCombo[4] = {up, A, A, B}you will also want to ensure that this sequence happens consecutively, so this time we will want to check that the deltaTime between button presses is less than a specified valuedeltaTime = globalTime() - timeSinceLastKeypress;if (ButtonDown(!superCombo[i])){i = 0;}else if( ButtonDown(superCombo[i]){executeAction();i++;}else if(timeSinceLastKeypress > maxTime){i =0;}of course on top of this you will want to add statements for when the combo is successful as well. this is just to act as an idea as to how this sort of functionality would work in code.Alot of new interesting technologies have added more exciting capabilities to interface devices directly affecting the way we play games. Nintendo has been greatly paving the way for interface devices with their Wii mote and the new wii u touchscreen pad. The occulus rift has also been a pivotal changing point in the way we view HID.This has created a standard for using technologies such as accelerometers and gyro sensors to add new and compelling game play. While alot of these discoveries may seem trivial, and many hadcore gamers turn away from them, they are still a very important step forward in interface technologies, and it is apparent that this type of technology is cutting edge to developers. what will be interesting is to see just how far they take it and whether any of these new concepts will die out as fads or stand the test of time like the controller.

Previous
Previous

Physics for Game Engines

Next
Next

Carmera Design and Architecture