Microsoft DirectX 8.1 (Visual Basic)

Preparing the Action Map

The action map is a DIACTIONFORMAT type containing information about application actions and their mapping to virtual controls or device objects. The type is passed back and forth between the application and Microsoft® DirectInput® to establish the final mapping. This section explains how to initialize the map.

1. Define Application Actions

The first step in implementing DirectInput action mapping is to determine what input-driven actions in your application need to be mapped to device objects. For actions that can be performed either by an axis or by a button, you must define separate actions for both input types. It is recommended that you define button actions for all important functions, in case the device does not have the appropriate axes.

The following sample enumeration of action values might be defined by a car-racing game. Axis actions begin with "eA" and button actions with "eB".

Enum eGameActions
    eA_STEER        'Steering
    eB_STEER_LEFT   'Steer left
    eB_STEER_RIGHT  'Steer right
    eA_ACCELERATE   'Change speed
    eB_ACCELERATE   'Speed up
    eB_DECELERATE   'Slow down
    eA_BRAKE        'Brake
    eB_BRAKE        'Brake
    eB_UPSHIFT      'Shift to higher gear
    eB_DOWNSHIFT    'Shift to lower gear
    eB_CYCLEVIEW    'Cycle to next view
    eB_COURSEVIEW   'Toggle course view
    eB_DRIVERVIEW   'View from driver's seat
    eB_BRAKEBIAS    'Brake bias
    eA_VOLUME       'Sound volume
    eB_MUTE         'Toggle sound
End Enum

Const NUM_MY_ACTIONS = 16

In the example, actions are defined as enumerated values. However, they could be other 32-bit data types. When you retrieve device data, you get whatever action value you have defined, and you can handle it in any way you like.

2. Define the Genre

The next step is to decide what genre your application belongs to. A genre defines a set of virtual controls. By selecting the proper genre, you can obtain the best possible fit of virtual controls to application actions. Manufacturers who choose to supply default mappings for their devices must support one or more of the genres defined by DirectInput. See Action Mapping Constants for a list of these genres.

For the game in the example, the obvious choice is the DIVIRTUAL_DRIVING_RACE genre, which contains the following virtual controls.

Priority 1 Controls

DIAXIS_DRIVINGR_STEER
DIAXIS_DRIVINGR_ACCELERATE
DIAXIS_DRIVINGR_BRAKE
DIBUTTON_DRIVINGR_SHIFTUP
DIBUTTON_DRIVINGR_SHIFTDOWN
DIBUTTON_DRIVINGR_VIEW
DIBUTTON_DRIVINGR_MENU

Priority 2 Controls

DIAXIS_DRIVINGR_ACCEL_AND_BRAKE
DIHATSWITCH_DRIVINGR_GLANCE
DIBUTTON_DRIVINGR_ACCELERATE_LINK
DIBUTTON_DRIVINGR_AIDS
DIBUTTON_DRIVINGR_BOOST
DIBUTTON_DRIVINGR_BRAKE
DIBUTTON_DRIVINGR_DASHBOARD
DIBUTTON_DRIVINGR_DEVICE
DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK
DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK
DIBUTTON_DRIVINGR_MAP
DIBUTTON_DRIVINGR_PAUSE
DIBUTTON_DRIVINGR_PIT
DIBUTTON_DRIVINGR_STEER_LEFT_LINK
DIBUTTON_DRIVINGR_STEER_RIGHT_LINK

There is no difference in functionality between Priority 1 and Priority 2 controls. Priority 1 controls are those most likely to be supported by device manufacturers in their default mappings. However, there is no guarantee that any virtual control will be supported by a device.

3. Assign Actions to Controls or Device Objects

The next step in creating the action map is to associate each application action with one or more of the virtual controls defined for the genre. You do this by declaring and initializing an array of DIACTION types. Each type in the array specifies the action value, the virtual control to associate with it, and a friendly name that describes the action. Leave other members as zero; they will be filled in later by DirectInput.

You can also use elements of the DIACTION array to map actions to particular keys or buttons on the keyboard or mouse or to channels on a Microsoft DirectPlay® voice device. By doing so, you can take advantage of the simplified input loop for all input, not just that from virtual controls. For example, suppose you map the application-defined action eB_UPSHIFT to both the DIBUTTON_DRIVINGR_SHIFTUP virtual control and to the Page Up key. When retrieving data, you get back eB_UPSHIFT whether the input came from a joystick button or the keyboard.

The following example begins the declaration of an action map for the car-racing game.

Dim rgActions(20) As DIACTION

' Genre-defined virtual axes
With rgActions(0)
  .lAppData = eA_STEER
  .lSemantic = DIAXIS_DRIVINGR_STEER
  .lFlags = 0
  .ActionName = "Steer"
End With
With rgActions(1)
  .lAppData = eA_ACCELERATE
  .lSemantic = DIAXIS_DRIVINGR_ACCELERATE
  .lFlags = 0
  .ActionName = "Accelerate"
End With
With rgActions(2)
  .lAppData = eA_BRAKE
  .lSemantic = DIAXIS_DRIVINGR_BRAKE
  .lFlags = 0
  .ActionName = "Brake"
End With
'and so on.

It may be more efficient, however, to use a Sub procedure to assign the values to the DIACTION array in the DIACTIONFORMAT type directly as in the following example.

Dim m_diaf As DIACTIONFORMAT
Dim m_NumberofSemantics As Long


Private Sub Form_Load()

m_NumberofSemantics = 0

AddAction eA_STEER, DIAXIS_DRIVINGR_STEER, 0, "Steer"
AddAction eA_ACCELERATE, DIAXIS_DRIVINGR_ACCELERATE, 0, "Accelerate"
AddAction eA_BRAKE, DIAXIS_DRIVINGR_BRAKE, 0, "Brake"

' Genre-defined virtual buttons
 
AddAction eB_UPSHIFT, DIBUTTON_DRIVINGR_SHIFTUP, 0, "Upshift"
AddAction eB_DOWNSHIFT, DIBUTTON_DRIVINGR_SHIFTDOWN, 0, "DownShift"
AddAction eB_CYCLEVIEW, DIBUTTON_DRIVINGR_VIEW, 0, "Change View"
 
'  Actions not defined in the genre that can be assigned to any
'  button or axis
 
AddAction eA_VOLUME, DIAXIS_ANY_1, 0, "Volume"
AddAction eB_MUTE, DIBUTTON_ANY, 0, "Toggle Sound"
 
'  Actions not defined in the genre that must be assigned to
'  particular keys
 
AddAction eB_DRIVERVIEW, DIKEYBOARD_1, 0, "Driver View"
AddAction eB_COURSEVIEW, DIKEYBOARD_C, 0, "Course View"
AddAction eB_BRAKEBIAS, DIKEYBOARD_B, 0, "Brake Bias"
 
'  Actions mapped to keys as well as to virtual controls
 
AddAction eB_UPSHIFT, DIKEYBOARD_PRIOR, 0, "Upshift"
AddAction eB_DOWNSHIFT, DIKEYBOARD_NEXT, 0, "Downshift"
AddAction eB_STEER_LEFT, DIKEYBOARD_LEFT, 0, "Steer Left"
AddAction eB_STEER_RIGHT, DIKEYBOARD_RIGHT, 0, "Steer Right"
AddAction eB_ACCELERATE, DIKEYBOARD_UP, 0, "Accelerate"
AddAction eB_DECELERATE, DIKEYBOARD_DOWN, 0, "Decelerate"
AddAction eB_BRAKE, DIKEYBOARD_END, 0, "Brake"
 
'  Actions mapped to buttons as well as to virtual controls and keys
 
AddAction eB_UPSHIFT, DIMOUSE_BUTTON0, 0, "Upshift"
AddAction eB_DOWNSHIFT, DIMOUSE_BUTTON1, 0, "Downshift"

End Sub

Private Sub AddAction(user As Long, semantic As Long,_
                             flags As Long, strName As String)
ReDim Preserve m_diaf.ActionArray(m_NumberofSemantics)

With m_diaf.ActionArray(m_NumberofSemantics)
    .lAppData = user
    .lSemantic = semantic
    .lFlags = flags
    .ActionName = strName
End With
m_NumberofSemantics = m_NumberofSemantics + 1
    
End Sub

In the example, some actions are mapped to actual keys by using Keyboard Mapping Constants. Similar mappings to the mouse buttons and axes can be made by using Mouse Mapping Constants.

The DIACTION array is contained within the DIACTIONFORMAT type that also contains information about the genre, the application, and the desired scaling of axis data. Use the same instance of this type throughout the action mapping process. Some members will not be used immediately, but you can fill in the entire type before the next step, Finding Matching Devices.