360 likes | 505 Views
Game Programming (User Input). 2013. Spring. The Keyboard. The Keyboard Most widely available input device The main input device for PC-based games Also available for mobile phones, some consoles, and palm devices Disadvantages Not very well suited for games Impractical for small children.
E N D
Game Programming(User Input) 2013. Spring
The Keyboard • The Keyboard • Most widely available input device • The main input device for PC-based games • Also available for mobile phones, some consoles, and palm devices • Disadvantages • Not very well suited for games • Impractical for small children User Input : No broad standards are available
The Keyboard • Keyboard read methods • Synchronous routine • Wait until a key is pressed and then report it to the application • Not well suited for real gameplay • Ex) type information such as the character name in a RPG • Asynchronous routine • Return immediately after being called, and give the application information about which keys were pressed • Two different routines • A single-key asynchronous call • Test the state of individual keys • A whole keyboard check • Retrieve the whole keyboard state in a single call • Less overhead, more efficient
The Keyboard • Asynchronous routine • A single-key asynchronous call • Win32 API (table 5.1) • How to check whether the key is pressed • How to test for the key combination Short GetAsyncKeyState(int keycode); If ( GetAsynKeyState(VK_LSHIFT) ) { // whatever } If ( GetAsynKeyState(VK_LSHIFT) && GetAsynKeyState(VK_RETRUN) ) { // whatever } Each key test requires a system call, which can be troublesome for those systems checking a lot of different keys
The Keyboard • Asynchronous routine • A whole keyboard check • How to check whether the key is pressed • a simple array lookup Bool GetKeyboardState(PBYTE *lpKeyState); If ( keyState[VK_RSHIFT] ) { // right shift was pressed } This mode does not immediately check the keys when you perform the test Undesirable side effects might occur (the array will contain “old” key values)
The Keyboard • Keyboard with DirectInput • A single call can retrieve the state of the whole keyboard • Provide fast asynchronous access to key states • Encapsulates keyboards, joystick, mice and any other input • Setting up a keyboard DirectInput • Create the DirectInput object • Create the keyboard device • Set the data format for reading it • Set the cooperative level you will use with the OS • Read data as needed
The Keyboard • DirectInput • Declaration : 1. Create the DirectInput object LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pKeyboard; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL); hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard); hr = g_pKeyboard->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pKeyboard->Acquire(); DirectInput object ready for use : 1 parameter: send the instance handle to the application that is creating the DirectInput object 2 parameter: pass the current DirectInput version number 3 parameter: pass the unique interface identifier for the object we are requesting (can use other parameters to define ANSI or Unicode versions of the interface) 4 parameter: pass the pointer so we can receive the already initialized object 5 parameter: perform Component Object Model (COM) aggregation
The Keyboard • DirectInput • Declaration : 2. Create the keyboard device LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pKeyboard; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL); hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard); hr = g_pKeyboard->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pKeyboard->Acquire(); Request a device from the DirectInput object 1 parameter : Receive Global Unique Identifier (GUID) for the desired device GUIDs for the different devices (128-bit structures) GUID_SysKeyboard: default system keyboard GUID_SysMouse: default system mouse 2 parameter : the pointer to the newly created device 3 parameter : reserved for aggregation
The Keyboard • DirectInput • Declaration : 3. Set the data format for reading it LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pKeyboard; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL); hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard); hr = g_pKeyboard->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pKeyboard->Acquire(); Tell the keyboard how we want to exchange data (pp. 127) 1 parameter : c_dfDIKeyboard the full keyboard stored in an array of 256 bytes
The Keyboard • DirectInput • Declaration : 4. Set the cooperative level you will use with the OS LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pKeyboard; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL); hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard); hr = g_pKeyboard->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pKeyboard->Acquire(); Tell DirectInput about the cooperative level 1 parameter : pass the window handle 2 parameter : the OR of a series of flags that control the cooperative level
The Keyboard • DirectInput • Declaration : 5. Read data as needed LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pKeyboard; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL); hr = g_pKeyboard->SetDataFormat( &c_dfDIKeyboard); hr = g_pKeyboard->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pKeyboard->Acquire(); Acquire the keyboard Can begin querying its state
The Keyboard The most significant bit is activated If the key is currently pressed • DirectInput • Reading the keyboard • Query a specific key (pp. 128) • Releasing the keyboard BYTE diks[256]; // DirectInput keyboard state buffer ZeroMemory( diks, sizeof(diks) ); hr = g_pKeyboard->GetDeviceState( sizeof(diks), diks ); If ( FAILED(hr) ) { hr = g_pKeyboard->Acquire(); while ( hr == DIERR_INPUTLOST || hr == DIEER_OTHERAPPHASPRIO) hr = g_pKeyboard->Acquire(); } Bool return_pressed = ( buffer[DIK_RETURN] & 0x80 ) ! = 0); If ( g_pKeyboard ) g_pKeyboard->Unacquire(); SAFE_RELEASE( g_pKeyboard ); SAFE_RELEASE( g_pDI );
Mouse • The Mouse • Not only generate button or key press, but 2D positions as well • The operation of the mouse • Transmitting positional information • Sending button press and release message
Mouse • DirectInput • declaration LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICEg_pMouse; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL); hr = g_pMouse->SetDataFormat( &c_dfDIMouse); hr = g_pMouse->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); hr = g_pMouse->Acquire();
Mouse • DirectInput • Reading from the mouse DIMOUSESTATE dims; // DirectInput mouse state structure ZeroMemory( &dims, sizeof(dims) ); hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE), &dims ); If ( FAILED(hr) ) { hr = g_pMouse->Acquire(); while ( hr == DIERR_INPUTLOST || hr == DIEER_OTHERAPPHASPRIO || hr == DIEER_NOTACTIVATED) hr = g_pMouse->Acquire(); }
Mouse Typedef struct DIMOUSESTATE { LONG lX, lY, lZ; BYTE rgbButtons[4]; } DIMOUSESTATE, *LPDIMOUSESTATE • DirectInput • Access the mouse attributes • Button 0: left mouse button • Button 1: right mouse button • Button 2: middle button • Relative pointing device • Return the displacement from the last one • Release the mouse Int MouseX=dims.lX; Int MouseY=dims.lY; bool lbutton = ( dims.rgbButtons[0] & 0x80 ) ! = 0); Buttons are pressed if the high-order bit is set If ( g_pMouse ) g_pMouse->Unacquire(); SAFE_RELEASE( g_pMouse ); SAFE_RELEASE( g_pDI );
Mouselook • Mouselook • The classic mouselook used in many first person shooters • The keys to change our position • X and Z values • The mouse to reorient our viewpoint • A yaw and pitch angle (Ref] Camera) • Mapping • Mouse: Mouselook • Left arrow: Strafe left • Right arrow: Strafe right • Up arrow: Move forward • Down arrow: Move back
Mouselook • Implementation // strafe and fwd by -1, 0, or 1 int strafe = (buffer[DIK_RIGHT] & 0x80) != 0) – (buffer[DIK_LEFT] & 0x80) != 0) ; int fwd = (buffer[DIK_UP] & 0x80) != 0) – (buffer[DIK_DOWN] & 0x80) != 0) ; // elapsed : elapsed time factor ensure device-independent performance pos.x += fwd*FWDSPEED*elapsed*cos(yaw) + strafe*STRAFESPEED*elapsed*cos(yaw+3.1416/2); pos.z += fwd*FWDSPEED*elapsed*sin(yaw) + strafe*STRAFESPEED*elapsed*sin(yaw+3.1416/2); yaw += YAWSPEED*elapsed*dims.lX; pitch += PITCHSPEED*elapsed*dims.lY; // lookat: spherical mapping using the pitch and yaw point campos( pos.x, pos.y, pos.z ); point camlookat( pos.x+cos(yaw)*cos(pitch), pos.y+sin(pitch), pos.z+sin(yaw)*cos(pitch) );
Joysticks • Joystick • Introduced in the 1970s as a way to represent positional data • Controlling a joystick LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICE g_pJoystick; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->EnumDevice( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY); hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick); hr = g_pJoystick->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)hwnd, DIDFT_ALL);
Joysticks • Controlling a joystick LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICEg_pJoystick; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->EnumDevice( DI8DEVCLASS_GAMECTRL, // game pads and joystick EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY); hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick); hr = g_pJoystick->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)hwnd, DIDFT_ALL); Ask DirectInput to enumerate any joystick it is detecting: 1 parameter: tells DirectInput which kind of device we want to detect (keyboard DI8DEVCLASS_KEYBOARD, mouse DI8DEVCLASS_POINTER) 2 parameter: a callback that will get triggered once for each detected joystick 3 parameter: user-defined parameter to be passed to the callback 4 parameter: the enumeration flags (DIEDFL_ATTACHEDONLY only detect devices that are properly attached and installed DIEDFL_FORCEFEEDBACK restrict the enumeration to force feedback)
Joysticks • Controlling a joystick LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICEg_pJoystick; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->EnumDevice( DI8DEVCLASS_GAMECTRL, // game pads and joystick EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY); hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick); hr = g_pJoystick->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)hwnd, DIDFT_ALL); BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID* pContext ) { HRESULT hr= g_pDI->createdevice( pdidInstance->guidInstance, &g_pJoystick, NULL); if (FAILED(hr)) return DIENUM_CONTINUE; return DIENUM_STOP; }
Joysticks • Controlling a joystick LPDIRECTINPUT8 g_pDI=NULL; LPDIRECTINPUTDEVICEg_pJoystick; HRESULT hr; hr = DirectInput8Create( GetModuleHandle (NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**) &g_pDI, NULL ); hr = g_pDI->EnumDevice( DI8DEVCLASS_GAMECTRL, // game pads and joystick EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY); hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick); hr = g_pJoystick->SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)hwnd, DIDFT_ALL); Set the data format and cooperative level
Joysticks • Controlling a joystick g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)hwnd, DIDFT_ALL); Set the output range for the joystick (Ex: -1…1 , -100…100 ) 1 parameter: Need to a callback that request the objects associated with the joystick (Objects axes, buttons, POVs, and so on) BOOL CALLBACK EnumObjectsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID* pContext ) { HWND hDlg =(HWND)pContext; if (pdidoi->dwType & DIDFT_AXIS) { DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize= sizeof(DIPROHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = pdidoi->dwType; diprg.diph.lMin = -100; diprg.diph.lMax = 100; if (FAILED(g_pJoystick->SetProperty(DIPROP_RANGE, &diprg.diph))) return DIENUM_STOP; } }
Joysticks • Reading from the joystick hr = g_pMouse->Poll(); If ( FAILED(hr) ) { hr = g_pJoystick->Acquire(); while ( hr == DIERR_INPUTLOST || hr == DIEER_OTHERAPPHASPRIO) hr = g_pJoystick->Acquire(); return S_OK; } DIJOYSTATE js; hr = g_pJoystick->GetDeviceState ( sizeof (DIJOYSTATE), &js)); typedef struct DIJOYSTATE { LONG lX, lY, lZ; LONG lRx, lRy, lRz; LONG rglSlider[2]; DWORD rgdwPOV[4]; BYTE rgbButtons[32]; } DIJOYSTATE, *LPDIJOYSTATE
Joysticks POV (point of view) switch
Joysticks • Response Curve • How analog joysticks map the controller position to a continuous range of values • Left, Still, Right ?? Response Curve without(left) and with(right) dead zone
Joysticks • Analog controller • Return a value in a continuous range • Need a response curve Types of Response Curve
Hardware Abstraction • Platforms that support a variety of input controllers • Ex) Standard controller, aircraft-style-joystick, snowboards, dance pads, fishing rod • Coding for such a platform • Choose to use only one of the existing controllers • Ex) strategy games (with a PC mouse) • Let the user choose the input method • Ex) Action games • Hardware Abstraction • Coding the game with a “virtual” controller • Controllers that conform to that abstract profile • via inheritance
Hardware Abstraction • Action mapping • Allows your device to return not specific state values but game-oriented values • Assign device events to game events • Device independence • Ex) “advance left” joystick(a movement on the X-axis) DIACTION g_adiaActionMap[ ] = { // Joystick input mappings { WALK, DIAXIS_FIGHTINGH_LATERAL, 0, ACTION_NAMES [WALK], }, { JUMP, DIBUTTON_FIGHTINGH_JUMP, 0, ACTION_NAMES [JUMP], }, // Keyboard input mappings { WALK_LEFT, DIKEYBOARD_LEFT, 0, ACTION_NAMES [WALK_LEFT], }, { WALK_RIGHT, DIKEYBOARD_RIGHT, 0, ACTION_NAMES [WALK_RIGHT], }, { JUMP, DIKEYBOARD_J, 0, ACTION_NAMES [JUMP], }, { QUIT, DIKEYBOARD_Q, DIA_APPFIXED, ACTION_NAMES [QUIT], }, // Mouse input mappings { WALK, DIMOUSE_XAXIS, 0, ACTION_NAMES [WALK], }, { JUMP, DIMOUSE_BUTTON0, 0, ACTION_NAMES [JUMP], }, }; enum GAME_ACTIONS { WALK, WALK_LEFT, WALK_RIGHT, JUMP, QUIT };
Force Feedback • Force Feedback • Force Feedback H/W simulates vibration by incorporating one or more motors • Programming force feedback devices (platform dependent) • Create or describe the desired effect (Ex. Force Editor) • How it affects the controller’s position, and strength, and so on • The effect must be loaded to the input API • Reproduce the effect at runtime MS’s Force Editor
Types of game controllers • Game Pad (= joypad) • the most common kind of game controller • Gamepads generally feature a set of action buttons handled with the right thumb and a direction controller(D-pad) handled with the left • shoulder buttons placed along the edges of the pad, centrally placed start, select, and mode buttons, and an internal motor to provide force feedback.
Types of game controllers • Paddle • A paddle is a controller that features a round wheel and one or more fire buttons • The wheel is typically used to control movement of the player or of an object along one axis of the video screen • Trackball • A trackball is basically an upside-down mouse that is manipulated with the palm of one's hand
Types of game controllers • Arcade style Joystick • It features a shaft that has a ball or drop-shaped handle, and one or more buttons for in game actions • Steering wheel • The steering wheel, essentially a larger version of a paddle, is used for racing simulators • Pedals • Pedals may be used for driving simulations or flight simulations
Types of game controllers • Touch screen • A touch screen is an input device that allows the user to interact with the computer by touching the display screen • Motion sensing • It uses accelerometers to detect its approximate orientation and acceleration and an image sensor[1] so it can be used as a pointing device • Microsoft has also released the Kinect, similar to Sony's Eyetoy, both of which use cameras to detect the player's motions and translate them into inputs for the game.
Types of game controllers • Light gun • A light gun is a peripheral used to "shoot" targets on a screen • Dance pad • a flat electronic game controller used for input in dance games • Balance Board • contains multiple pressure sensors that are used to measure the user's center of balance
Types of game controllers • Others • Rhythm games controller • guitars, drums, turntablism or maracas • Fishing rod • Microphone • Mind-controlled headset