Step 2: Defining the Action Map

Next, each game action should be assigned to at least one virtual control or device object. These controls are defined as action-mapping constants and are defined by genre and subgenre. In this case, the best choice is the Space Combat subgenre of the flight-games genre. This subgenre makes the following constants available.

Priority 1 Controls
DIAXIS_SPACESIM_LATERAL, DIAXIS_SPACESIM_MOVE, DIAXIS_SPACESIM_THROTTLE, DIBUTTON_SPACESIM_FIRE, DIBUTTON_SPACESIM_MENU, DIBUTTON_SPACESIM_TARGET, DIBUTTON_SPACESIM_WEAPONS
Priority 2 Controls
DIAXIS_SPACESIM_CLIMB, DIAXIS_SPACESIM_ROTATE, DIBUTTON_SPACESIM_BACKWARD_LINK, DIBUTTON_SPACESIM_DEVICE, DIBUTTON_SPACESIM_DISPLAY, DIBUTTON_SPACESIM_FASTER_LINK, DIBUTTON_SPACESIM_FIRESECONDARY, DIBUTTON_SPACESIM_FORWARD_LINK, DIBUTTON_SPACESIM_GEAR, DIBUTTON_SPACESIM_GLANCE_DOWN_LINK, DIBUTTON_SPACESIM_GLANCE_LEFT_LINK, DIBUTTON_SPACESIM_GLANCE_RIGHT_LINK, DIBUTTON_SPACESIM_GLANCE_UP_LINK, DIBUTTON_SPACESIM_LEFT_LINK, DIBUTTON_SPACESIM_LOWER, DIBUTTON_SPACESIM_PAUSE, DIBUTTON_SPACESIM_RAISE, DIBUTTON_SPACESIM_RIGHT_LINK, DIBUTTON_SPACESIM_SLOWER_LINK, DIBUTTON_SPACESIM_TURN_LEFT_LINK, DIBUTTON_SPACESIM_TURN_RIGHT_LINK, DIBUTTON_SPACESIM_VIEW, DIHATSWITCH_SPACESIM_GLANCE

Priority 1 controls are those controls that, at the minimum, should be mapped to a device object if possible. Priority 2 controls are less critical to basic game operation and may be mapped as needed.

Game actions are assigned to action-mapping constant controls in an array of DIACTION structures. Each DIACTION structure contains at least one game action, its associated action-mapping constant, any necessary flags, and either a friendly name or ID string for the action. The remaining DIACTION members are not used at this point. The following code sample shows definition of the array of DIACTION structures.

#define NUMBER_OF_ACTIONS 18

DIACTION g_rgGameAction[NUMBER_OF_ACTIONS] =
{
    // Device input pre-defined by DirectInput, according to genre
    {INPUT_LEFTRIGHT_AXIS, DIAXIS_SPACESIM_LATERAL, 0, "Turn",},
    {INPUT_UPDOWN_AXIS, DIAXIS_SPACESIM_MOVE, 0, "Move",},
    {INPUT_FIREWEAPONS, DIBUTTON_SPACESIM_FIRE, 0, "Shoot",},
    {INPUT_ENABLESHIELD, DIBUTTON_SPACESIM_GEAR, 0, "Shield",},
    {INPUT_DISPLAYGAMEMENU, DIBUTTON_SPACESIM_DISPLAY, 0, "Display",},
    {INPUT_QUITGAME, DIBUTTON_SPACESIM_MENU, 0, "Quit Game",},

    // Keyboard input mappings
    {INPUT_TURNLEFT, DIKEYBOARD_LEFT, 0, "Turn left", },
    {INPUT_TURNRIGHT, DIKEYBOARD_RIGHT, 0, "Turn right", },
    {INPUT_FORWARDTHRUST, DIKEYBOARD_UP, 0, "Forward thrust", },
    {INPUT_REVERSETHRUST, DIKEYBOARD_DOWN, 0, "Reverse thrust", },
    {INPUT_FIREWEAPONS, DIKEYBOARD_F, 0, "Fire weapons", },
    {INPUT_ENABLESHIELD, DIKEYBOARD_S, 0, "Enable shields", },
    {INPUT_DISPLAYGAMEMENU, DIKEYBOARD_D, DIA_APPFIXED, 
    "Display game menu"), },
    {INPUT_QUITGAME, DIKEYBOARD_ESCAPE, DIA_APPFIXED, "Quit game", },

    // Mouse input mappings
    {INPUT_LEFTRIGHT_AXIS, DIMOUSE_XAXIS, 0, "Turn", },
    {INPUT_UPDOWN_AXIS, DIMOUSE_YAXIS, 0, "Move", },
    {INPUT_FIREWEAPONS, DIMOUSE_BUTTON0, 0, "Fire weapons", },
    {INPUT_ENABLESHIELD, DIMOUSE_BUTTON1, 0, "Enable shields", },
};

A DIACTIONFORMAT structure is then initialized to contain the DIACTION array g_rgGameAction defined above. The DIACTIONFORMAT structure also defines the genre, buffer size, axis scaling, and a friendly name for the action map. The g_AppGuid value is a globally unique identifier (GUID) defined in the application to identify the action map. For more information about creating GUIDs, see COM Object Overview.

DIACTIONFORMAT diaf;
diaf.dwSize        = sizeof(DIACTIONFORMAT);
diaf.dwActionSize  = sizeof(DIACTION);
diaf.dwDataSize    = NUMBER_OF_ACTIONS * sizeof(DWORD);
diaf.dwNumActions  = NUMBER_OF_ACTIONS;
diaf.guidActionMap = g_AppGuid;
diaf.dwGenre       = DIVIRTUAL_SPACESIM;
diaf.rgoAction     = g_rgGameAction;
diaf.dwBufferSize  = 16;
diaf.lAxisMin      = -100;
diaf.lAxisMax      = 100;
diaf.tszActionMap  = "DI Test";

This DIACTIONFORMAT structure is matched against enumerated devices to find the best match in Step 3: Mapping Actions to Devices.