Game Programming (User Input)
description
Transcript of Game Programming (User Input)
Game ProgrammingGame Programming(User Input)(User Input)2011. 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
If ( GetAsynKeyState(VK_LSHIFT) ) { // whatever}
Short GetAsyncKeyState(int keycode);
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
1. Create the DirectInput object2. Create the keyboard device3. Set the data format for reading it4. Set the cooperative level you will use with the OS5. 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 object2 parameter: pass the current DirectInput version number3 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 object5 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 object1 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 mouse2 parameter : the pointer to the newly created device3 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 level1 parameter : pass the window handle2 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
■ DirectInput Reading the keyboard
Query a specific key (pp. 128)
Releasing the keyboard
BYTE diks[256]; // DirectInput keyboard state bufferZeroMemory( 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();}
If ( g_pKeyboard ) g_pKeyboard->Unacquire();SAFE_RELEASE( g_pKeyboard );SAFE_RELEASE( g_pDI );
Bool return_pressed = ( buffer[DIK_RETURN] & 0x80 ) ! = 0);
The most significant bit is activatedIf the key is currently pressed
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;LPDIRECTINPUTDEVICE g_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 structureZeroMemory( &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■ 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
If ( g_pMouse ) g_pMouse->Unacquire();SAFE_RELEASE( g_pMouse );SAFE_RELEASE( g_pDI );
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
Typedef struct DIMOUSESTATE { LONG lX, lY, lZ; BYTE rgbButtons[4];} DIMOUSESTATE, *LPDIMOUSESTATE
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 1int 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 performancepos.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 yawpoint 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 joystickLPDIRECTINPUT8 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, // 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 joystick3 parameter: user-defined parameter to be passed to the callback4 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 joystickLPDIRECTINPUT8 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, // 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 joystickLPDIRECTINPUT8 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, // 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 joystickg_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 joystickhr = 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
■ 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)
enum GAME_ACTIONS { WALK, WALK_LEFT, WALK_RIGHT, JUMP, QUIT};
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], },};
Force Feedback■ Force Feedback
Force Feedback H/W simulates vibration by incorporating one or more motors
■ Programming force feedback devices (platform dependent)1. Create or describe the desired effect (Ex. Force Editor)
• How it affects the controller’s position, and strength, and so on2. The effect must be loaded to the input API3. 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