04-12-2023, 03:29 PM
(This post was last modified: 05-18-2023, 03:08 AM by TerryRitchie.)
------------------------------------------------------
05/17/23 - UPDATE
Version 1.10 is now available (code below updated as well as attached ZIP file)
NOTE: This library will now require QB64PE version 3.7.0 and above.
This version now adds the following capabilities:
- Save and load user defined buttons ( __LOAD_BUTTONS, __SAVE_BUTTONS )
- The ability to detect new controllers plugged and existing controllers unplugged/plugged back in ( __NEW_CONTROLLER, __CONNECTED )
- Remove all controller associated user defined buttons ( __REMOVE_CONTROLLER )
- Prior versions automatically created buttons based on integer variables. A change was needed to facilitate the loading of saved button configurations.
__MAKE_BUTTON is now required to initialize user defined buttons (see documentation in CONTROLLER.BI for more info).
------------------------------------------------------
I wrote a controller library for use with the keyboard, mouse, and joysticks / game pads.
The first code is CONTROLLER.BI to be placed at the top of your code. It also contains the library documentation.
The second code is CONTROLLER.BM to be placed at the bottom of your code.
The next three pieces of code are examples showing the use of the library. A ZIP file is also attached that contains all the code as well. A fourth demo named "Configure_Buttons.BAS" is also included that is a mini-game that highlights all the features of the library.
Give it a whirl and let me know if you find any bugs or changes that I should make to the library. I have not incorporated WHEEL routines yet. Having a bit of an issue getting WHEEL functions to work properly.
05/17/23 - UPDATE
Version 1.10 is now available (code below updated as well as attached ZIP file)
NOTE: This library will now require QB64PE version 3.7.0 and above.
This version now adds the following capabilities:
- Save and load user defined buttons ( __LOAD_BUTTONS, __SAVE_BUTTONS )
- The ability to detect new controllers plugged and existing controllers unplugged/plugged back in ( __NEW_CONTROLLER, __CONNECTED )
- Remove all controller associated user defined buttons ( __REMOVE_CONTROLLER )
- Prior versions automatically created buttons based on integer variables. A change was needed to facilitate the loading of saved button configurations.
__MAKE_BUTTON is now required to initialize user defined buttons (see documentation in CONTROLLER.BI for more info).
------------------------------------------------------
I wrote a controller library for use with the keyboard, mouse, and joysticks / game pads.
The first code is CONTROLLER.BI to be placed at the top of your code. It also contains the library documentation.
The second code is CONTROLLER.BM to be placed at the bottom of your code.
The next three pieces of code are examples showing the use of the library. A ZIP file is also attached that contains all the code as well. A fourth demo named "Configure_Buttons.BAS" is also included that is a mini-game that highlights all the features of the library.
Give it a whirl and let me know if you find any bugs or changes that I should make to the library. I have not incorporated WHEEL routines yet. Having a bit of an issue getting WHEEL functions to work properly.
Code: (Select All)
'----------------------------
' Controller Library V1.10
' Terry Ritchie
' May 17th, 2023
' Written using QB64PE v3.7.0
'----------------------------
' CONTROLLER.BI
'----------------------------
'
' TODO: Add WHEEL routines
' Create PDF instructions
'
'----------------------------
' 04/10/23 V1.0 - Initial Release
' 04/26/23 V1.01 - Corrected slot reassigning issues
' 05/17/23 V1.10 - Added __MAKE_BUTTON, __CONNECTED, __SAVE_BUTTONS, __LOAD_BUTTONS, __NEW_CONTROLLER, __REMOVE_CONTROLLER
' - The library now has the ability to save and load controller user defined button configurations
' - You can now detect when a controller has been plugged in or unplugged
' - A controller's user defined button assignments can be removed when the controller has been unplugged
'----------------------------
' +---------------------------------------+
' | |
' | HOW QB64 HANDLES CONTROLLERS |
' | |
' +---------------------------------------+
'
' QB64's controller commands work by identifying the connected controllers at program start up using _DEVICES. This list of identified controllers can
' only be added to during program execution. If a controller is unplugged the controller's id number is not removed from the list. Instead, the
' controller will be listed as [DISCONNECTED] through _DEVICE$. When the controller is plugged back in the [DISCONNECTED] will be removed from the
' controller's identifying string returned by _DEVICE$.
'
' This library will support up to six controllers (see the list below in "INITIALIZING THE LIBRARY") connected at one time. The behavior above will only
' become an issue if your user, for whatever reason, has plugged in, and then unplugged, so many controllers that the device list contains all
' [DISCONNECTED] controllers and a new controller plugged in occupies id #7. That controller will not be detected, only the previous controllers the
' user plugged in. This scenario is highly unlikely but, users being users, it may happen. You can test for this condition by checking if _DEVICES is
' ever greater than 6.
' +---------------------------------------+
' | |
' | INITIALIZING THE LIBRARY |
' | |
' +---------------------------------------+
'
' The first subroutine that MUST be called is __INITIALIZE_CONTROLLERS. This subroutine initializes all the associated controller variables and
' identifies all connected controllers. Up to 6 total controllers can be detected and used:
'
' - 1 keyboard, 1 mouse, and 4 joysticks/game pads
' - 1 leyboard, no mouse, and 5 joysticks/game pads
' - no keyboard, 1 mouse, and 5 joysticks/game pads
' - no keyboard, no mouse, and 6 joysticks/game pads
'
' Once the connected controllers have been identified the following shared integers will be set with controller ID numbers:
'
' __KEYBOARDCID Always a value of 1 when a keyboard is detected
' __MOUSECID Always a value of 2 if a keyboard is also present, 1 if no keyboard detected
' __JOYPAD1CID The first joystick/game pad detected. Always a value of 3 if a keyboard and mouse present, 1 or 2 otherwise
' __JOYPAD2CID The second joystick/game pad detected. Always a value of 4 if a keyboard and mouse present, 2 or 3 otherwise
' __JOYPAD3CID The third joystick/game pad detected. Always a value of 5 if a keyboard and mouse present, 3 or 4 otherwise
' __JOYPAD4CID The fourth joystick/game pad detected. Always a value of 6 if a keyboard and mouse present, 4 or 5 otherwise
' __JOYPAD5CID The fifth joystick/game pad detected. ALWAYS A VALUE OF 5. Will only be detected if a keyboard or mouse is NOT present
' __JOYPAD6CID The sixth joystick/game pad detected. ALWAYS A VALUE OF 6. Will only be detected if a keyboard and mouse are NOT present
'
' NOTE: If a certain controller is not found, for instance a mouse, then the corresponding variable will contain 0 (__MOUSECID = 0)
'
' These variables are now to be used to indentify the controller you wish to interact with. If a variable contains a value other than 0 the controller
' exists and will continue to exist until program termination.
' +---------------------------------------+
' | |
' | REDETECING CONTROLLERS |
' | |
' +---------------------------------------+
'
' If at any time you wish to rescan for currently connected controllers you can use this subroutine:
'
' __IDENTIFY_CONTROLLERS
'
' However, you'll more than likely never need to use this subroutine. The library is designed to automatically use __IDENTIFY_CONTROLLERS when a
' change in controller status occurs, such as a new controller plugged in, an existing controller unplugged, or an existing controller plugged back in.
' __INITIALIZE_CONTROLLERS automatically calls this subroutine as well.
' +---------------------------------------+
' | |
' | GET EXISTING CONTROLLERS |
' | |
' +---------------------------------------+
'
' The following functions can be used to determine the number and type of controllers found:
'
' __KEYBOARD_EXISTS - determine if a keyboard controller was found, -1 (TRUE) or 0 (FALSE)
' __MOUSE_EXISTS - determine if a mouse controller was found, -1 (TRUE) or 0 (FALSE)
' __JOYPAD_EXISTS(Number) - determine if a joystick/game pad was found
' Number = the desired joystick/game pad to query (1 to 6)
' If the numbered game pad was found __JOYPAD_EXISTS returns the TOTAL NUMBER of joysticks/game pads found.
'
' Example:
'
' IF __KEYBOARD_EXISTS THEN PRINT "Found!" ' was keyboard controller found?
' IF __MOUSE_EXISTS THEN PRINT "Found!" ' was mouse controller found?
' NumberOfJoypads = __JOYPAD_EXISTS(__JOYPAD1CID) ' query to determine if at least one joystick/game pad found
' IF NumberOfJoypads THEN ' at least 1 joystick found?
' PRINT "Joystick 1 found!" ' yes, display result
' PRINT "Total number of joysticks/game pads:"; NumberOfJoypads
' END IF
' +---------------------------------------+
' | |
' | GET CONTROLLER PROPERTIES |
' | |
' +---------------------------------------+
'
' The following functions can be used to query each controller for information:
'
' __CONTROLLER_NAME$(cid) - the descriptive name of the controller
' __BUTTON_TOTAL(cid) - the number of buttons a controller has
' __AXIS_TOTAL(cid) - the number of axes a controller has
'
' Example:
'
' IF __JOYPAD1CID THEN ' or "IF __JOYPAD_EXISTS(1) THEN" would work as well
' PRINT "Joystick 1 name : "; __CONTROLLER_NAME$(__JOYPAD1CID)
' PRINT "Buttons available:"; __BUTTON_TOTAL(__JOYPAD1CID)
' PRINT "Axes available :"; __AXIS_TOTAL(__JOYPAD1CID)
' END IF
' +---------------------------------------+
' | |
' | QUERY CONTROLLER DIRECTLY |
' | |
' +---------------------------------------+
'
' The following function can be used to determine if a controller is plugged in or unplugged:
'
' __CONNECTED(cid)
'
' The function will return a value of -1 (TRUE) if the controller is plugged in and 0 (FALSE) if the controller in unplugged.
'
' Example:
'
' IF __JOYPAD2CID THEN ' was joystick 2 detected at program startup?
' IF __CONNECTED(__JOYPAD2CID) THEN ' yes, is joystick 2 currently connected?
' PRINT "Joystick 2 found and currently connected." ' yes, inform user
' ELSE ' no, joystick 2 has been unplugged
' PRINT "Joystick 2 is currently unplugged." ' inform user
' END IF
' END IF
'
' The following functions can be used to query buttons and axes directly from a controller:
'
' __CONTROLLER_BUTTON(cid, Button)
' __CONTROLLER_AXIS(cid, Axis)
'
' Example:
'
' IF __CONTROLLER_BUTTON(__JOYPAD1CID, 1) THEN ' is joystick button one down?
' PRINT "Joystick button #1 pressed!" ' yes, report findings
' END IF
' IF __CONROLLER_BUTTON(__KEYBOARDCID, CLKEY_UP) THEN ' is keyboard UP ARROW key down?
' PRINT "Keyboard UP ARROW key pressed!" ' yes, report findings
' END IF
' VerticalAxis = __CONTROLLER_AXIS(__JOYPAD1CID, 1) ' get current vertical axis of joystick/game pad 1
' +---------------------------------------+
' | |
' | RETRIEVING CONTROLLER EVENTS |
' | |
' +---------------------------------------+
'
' The __NEW_CONTROLLER function is used to identify when a new controller has been plugged in, and existing controller has been unplugged, or an
' existing controller has been plugged back in:
'
' Controller = __NEW_CONTROLLER(Event)
'
' Event will contain the controller event that was detected (if any):
'
' 0 - no events occurred
' 1 - an existing controller was unplugged (the constant __UNPLUGGED can be used to check for this event)
' 2 - an existing controller was plugged back in (the constant __PLUGGEDIN can be used to check for this event)
' 3 - a new controller has been plugged in (the constant __NEWCONTROLLER can be used to check for this event)
'
' The function will return the following values:
'
' - a value of 0 (FALSE) if nothing has changed
' - the value will contain the new controller id when a new controller is plugged in (Event = 3 )
' - the value will contain the controller id of a controller that was unplugged or plugged back in (Event = 1 or 2)
'
' Example:
'
' Controller = __NEW_CONTROLLER(Event) ' check for a controller event
' IF Controller THEN ' has a controller event ocurred?
' SELECT CASE Event ' yes, what happened?
' CASE __NEW_CONTROLLER ' a new controller was plugged in
' PRINT "A new controller with the id of"; Controller; "has been plugged in."
' CASE __PLUGGEDIN ' an existing controller was plugged back in
' PRINT "Controller id"; Controller; "has been plugged back in."
' CASE __UNPLUGGED ' an existing controller was unplugged
' PRINT "Controller id"; Controller; "has been unplugged."
' END SELECT
' END IF
'
' During game play there is no need to constantly check for controller events. Inside the main game loop during game play a check once per second
' will be more than enough. See the example program named "Configure_buttons.BAS" for a demonstration of this in action.
' +---------------------------------------+
' | |
' | CREATING USER DEFINED BUTTONS |
' | |
' +---------------------------------------+
'
' A user defined button can have up to 4 buttons or axes from various controllers associated with it. First, create an integer handle for each user
' defined button:
'
' DIM UP_Button AS INTEGER ' user defined button handles with up to four associated controller buttons and/or axes
' DIM DOWN_Button AS INTEGER
' DIM LEFT_Button AS INTEGER
' DIM RIGHT_Button AS INTEGER
'
' Next, the variables must be identified as user defined buttons using the __MAKE_BUTTON subroutine:
'
' __MAKE_BUTTON UP_Button ' __MAKE_BUTTON statement added with version 1.10
' __MAKE_BUTTON DOWN_Button ' __MAKE_BUTTON must be used with versions 1.10 and above
' __MAKE_BUTTOn LEFT_Button
' __MAKE_BUTTON RIGHT_Button
'
' The following subroutines allow for assigning a controller button and/or axes directly to a user defined button:
'
' __ASSIGN_BUTTON(Handle, cid, Button)
' __ASSIGN_AXIS(Handle, cid, Axis)
'
' Example:
'
' __ASSIGN_BUTTON UP_Button, __KEYBOARDCID, CLKEY_UP ' keyboard UP ARROW key assigned to UP_Button [SLOT1]
' __ASSIGN_BUTTON UP_Button, __KEYBOARDCID, CLKEY_W ' Keyboard W key also assigned to UP_Button [SLOT2]
' __ASSIGN_AXIS UP_Button, __JOYPAD1CID, -2 ' joystick vertical axis UP (-) also assigned to UP_Button [SLOT3]
' __ASSIGN_BUTTON DOWN_Button, __KEYBOARDCID, CLKEY_DOWN ' keyboard DOWN ARROW key assigned to DOWN_Button [SLOT1]
' __ASSIGN_BUTTON DOWN_Button, __KEYBOARDCID, CLKEY_S ' keyboard S key also assigned to DOWN_Button [SLOT2]
' __ASSIGN_AXIS DOWN_Button, __JOYPAD1CID, 2 ' joystick vertical axis DOWN (+) also assigned to DOWN_Button [SLOT3]
' __ASSIGN_BUTTON LEFT_Button, __KEYBOARDCID, CLKEY_LEFT ' keyboard LEFT ARROW key assigned to LEFT_Button [SLOT1]
' __ASSIGN_BUTTON LEFT_Button, __KEYBOARDCID, CLKEY_A ' keyboard A key also assigned to LEFT_Button [SLOT2]
' __ASSIGN_AXIS LEFT_Button, __JOYPAD1CID, -1 ' joystick horizontal axis LEFT (-) also assigned to LEFT_Button [SLOT3]
' __ASSIGN_BUTTON RIGHT_Button, __KEYBOARDCID, CLKEY_RIGHT ' keyboard RIGHT ARROW key assigned to RIGHT_Button [SLOT1]
' __ASSIGN_BUTTON RIGHT_Button, __KEYBOARDCID, CLKEY_D ' keyboard D key also assigned to RIGHT_Button [SLOT2]
' __ASSIGN_AXIS RIGHT_Button, __JOYPAD1CID, 1 ' joystick horizontal axis RIGHT (+) also asigned to RIGHT_Button [SLOT3]
'
' The above example now gives the player the option of using the keyboard ARROW keys, WASD keys, or the joystick to move in all four directions.
' Each of the above user defined buttons still have one slot remaining [SLOT4] and it could be populated with another joystick axis or perhaps
' the keyboard NUMBER PAD arrow keys if you wish.
'
' Joystick and game pad axis directions are defined with positive and negative values. A negative axis value either means UP or LEFT and a positive
' axis value either means DOWN or RIGHT depending on the axis being assigned. Axis deflections are detected when the axis is 50% or greater in
' deflection in a given direction. Top hats and D-Pads typically return a vale of -1 (-100%) or 1 (100%) while analog joystick inputs will change
' from -1 to 1 with a range of values in between. Analog joystick axes will register as a button press when they are deflected -.5 (-50%) to
' .5 (+50%) in either direction. (This .5 value can be changed using __SET_AXIS_THRESHOLD to suit your needs)
' +---------------------------------------+
' | |
' | SETTING AXIS THRESHOLD SENSITIVITY |
' | |
' +---------------------------------------+
'
' When using an axis as a button a certain axis deflection must be reached before the axis is considered "pressed". By default a joystick or game pad
' axis must be deflected at least 50% to reach this threshold. The following function can be used to change the threshold sensitivity amount:
'
' __SET_AXIS_THRESHOLD(Value)
'
' Example:
'
' __SET_AXIS_THRESHOLD .25 ' set axis button sensitivity to 25% deflection.
'
' Value can be any number from .01 (1%) to .99 (99%).
' +---------------------------------------+
' | |
' | DETECTING A USER DEFINED BUTTON PRESS |
' | |
' +---------------------------------------+
'
' The following function can be used to test if a user defined button is being pressed:
'
' __BUTTON_DOWN(Handle)
'
' Example:
'
' IF __BUTTON_DOWN(UP_Button) THEN
' PRINT "Either the keyboard UP ARROW or W key was pressed or joystick 1 was pushed or pressed UP."
' END IF
' +---------------------------------------+
' | |
' | AUTO-ASSIGNING USER DEFINED BUTTONS |
' | |
' +---------------------------------------+
'
' Because of the wide variety of joytick and game pad controllers a user may connect it may be best to have the user define the keys, buttons, and
' axes they wish to use. The following subroutine can be used to have the user auto-assign user defined button assignments:
'
' __AUTOASSIGN_BUTTON(Handle)
'
' Example:
'
' __AUTOASSIGN_BUTTON UP_Button ' [SLOT1] wait for a button press or axis deflection
' __AUTOASSIGN_BUTTON UP_Button ' [SLOT2] wait for a button press or axis deflection
'
' __AUTOASSIGN_BUTTON will wait for a controller button press or axis deflection and then store that information into an available slot. Again,
' this can be done up to four times to fill the four available slots.
'
' NOTE: The mouse controller axes are ignored while __AUTOASSIGN_BUTTON waits for a controller button or axis. If you wish to assign mouse movements as
' axes to a user defined button you'll need to do it manually with __ASSIGN_AXIS.
' +---------------------------------------+
' | |
' | REMOVING BUTTON ASSIGNMENTS |
' | |
' +---------------------------------------+
'
' The following subroutine can be used to clear button/axis assignments (slots) from a user defined button:
'
' __REMOVE_BUTTON(Handle, Slot)
'
' Example:
'
' __REMOVE_BUTTON UP_Button, 3 ' remove the assigned button/axis from slot 3
' __REMOVE_BUTTON DOWN_Button, 0 ' remove the assigned buttons/axes from all slots
'
' Slot can range from 1 to 4, or 0 if you wish to remove all user assigned buttons/axes.
' +---------------------------------------+
' | |
' | REMOVING A CONTROLLER'S BUTTONS |
' | |
' +---------------------------------------+
'
' The subroutine __REMOVE_CONTROLLER will remove all user assigned buttons associated with a controller. This is most useful when a controller has
' been detected as unplugged by __NEW_CONTROLLER and the associated assigned buttons need to be removed as well.
'
' __REMOVE_CONTROLLER cid
'
' Example:
'
' Controller = __NEW_CONTROLLER(Event) ' check for a controller event
' IF Controller THEN ' has a controller event ocurred?
' SELECT CASE Event ' yes, what happened?
' CASE __NEW_CONTROLLER ' a new controller was plugged in
' PRINT "A new controller with the id of"; Controller; "has been plugged in."
' CASE __PLUGGEDIN ' an existing controller was plugged back in
' PRINT "Controller id"; Controller; "has been plugged back in."
' __LOAD_BUTTONS ' load user defined buttons associated with controller (if they exist)
' CASE __UNPLUGGED ' an existing controller was unplugged
' PRINT "Controller id"; Controller; "has been unplugged."
' __REMOVE_CONTROLLER Controller ' remove controller's associated user defined buttons
' END SELECT
' END IF
' +---------------------------------------+
' | |
' | ENABLING/DISABLING BUTTON REASSIGNMENT|
' | |
' +---------------------------------------+
'
' If an attempt is made to assign an axis or button that was previously assigned to a user defined button, the original assignment will be erased and
' replaced by the new assignment by default. This behavior can be changed using the following subroutines:
'
' __BUTTON_REASSIGN_ALLOWED
' __BUTTON_REASSIGN_NOT_ALLOWED
'
' Example:
'
' __BUTTON_REASSIGN_ALLOWED ' allow previously assigned buttons/axes to be moved into a different user assigned button *DEFAULT*
' __BUTTON_REASSIGN_NOT_ALLOWED ' ignore requests to reassign buttons
' +---------------------------------------+
' | |
' | GETTING A BUTTON'S NAME |
' | |
' +---------------------------------------+
'
' When a user defined button is created a descriptive name is also generated and stored. You can use the following function to get a user defined button's
' name:
'
' __BUTTON_NAME$(Handle, Slot)
'
' Example:
'
' ButtonName$ = __BUTTON_NAME$(UP_Button, 1)
'
' Slot values range from 1 to 4.
' +---------------------------------------+
' | |
' | LOADING/SAVING USER DEFINED BUTTONS |
' | |
' +---------------------------------------+
'
' It's now possible to save and load user defined buttons associated to controller inputs. Use the __SAVE_BUTTONS subroutine to save the current
' set of user defined buttons and __LOAD_BUTTONS to load any user defined buttons that may be associated with a controller.
'
' __SAVE_BUTTONS ' save all currently configured user define buttons to configuration files
' __LOAD_BUTTONS ' load buttons that are associated with the currently connected controllers
'
' When __SAVED_BUTTONS is used a configration file for each attached controller is created. The name of the controller and the controller's id number
' ised used to create the file. For instance, if a system currently has a keyboard, mouse, Joystick, and game pad. The name of the joystick is
' "Saitek ST290 Pro" and the name of the game pad is "USB Game Pad". The joystick is using id#3 and the game pad is using id#4. The four configration
' files that will be created are:
'
' - "Keyboard.ID1"
' - "Mouse.ID2"
' - "Saitek ST290 Pro.ID3"
' - "USB Game Pad.ID4"
'
' All user assigned buttons will be saved in their assigned controller configuration file. It's possible to have multiple configration files for any
' given controller based on the id number it is using. For example, let's say the next time the program is started only the USB Game Pad is connected.
' It will be identified as using id number 3. Later on the user plugs in the Saitek ST290 Pro which will now be have an id of 4. When __SAVE_BUTTONS
' is used the four configration files will be as follows:
'
' - "Keyboard.ID1"
' - "Mouse.ID2"
' - "USB Game Pad.ID3"
' - "Saitek ST290 Pro.ID4"
'
' Therefore, depending on which id number a controller currently has will depend on which configuration file is used to load saved user defined
' buttons. This allows controllers to be set up with player 1-6 configurations with each player having a different preferred configuration.
'
' Also, controllers that have no user assigned buttons will still create a configuration file of zero bytes in size. This is normal.
'
' __LOAD_BUTTONS will look for configuration files associated with all currently connected controllers based on their id numbers. If a configration
' exists the user defined buttons wil be loaded.
' +---------------------------------------+
' | |
' | REMAPPING JOYSTICK/GAME PAD AXES |
' | |
' +---------------------------------------+
'
' As stated before, joystick and game pad axis are always returned as values between -1 and 1. The following function can be used to remap this range
' to a different value range:
'
' __MAP_AXIS(AxisValue, Lower, Upper)
'
' Example:
'
' J1Xaxis = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD1CID, 1), -128, 128) ' remap joystick 1 horizontal axis values from -128 to 128 (0 being center)
' J1Yaxis = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD1CID, 2), -128, 128) ' remap joystick 1 vertical axis values from -128 to 128 (0 being center)
' J2Xaxis = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD2CID, 1), 0, 255) ' remap joystick 2 horizontal axis values from 0 to 255 (127 being center)
' J2Yaxis = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD2CID, 2), 0, 255) ' remap joystick 2 vertical axis values from 0 to 255 (127 being center)
'
' The Lower and Upper range values can be any values you wish as long as the Lower value is less than the Upper value.
'
' +---------------------------------------+
' | |
' | LIBRARY CODE BEGINS HERE |
' | |
' +---------------------------------------+
'OPTION _EXPLICIT
' __________________________________________________________________________________________________________________________________________________
'/ KEYBOARD KEY _BUTTON CONSTANTS \
CONST CLKEY_ESC = 2 ' |
CONST CLKEY_F1 = 60 ' FUNCTION KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_F2 = 61 ' _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ |
CONST CLKEY_F3 = 62 ' ||ESC|| ||F1 |||F2 |||F3 |||F4 || ||F5 |||F6 |||F7 |||F8 || ||F9 |||N/A|||F11|||F12|| |
CONST CLKEY_F4 = 63 ' ||___|| ||___|||___|||___|||___|| ||___|||___|||___|||___|| ||___|||___|||___|||___|| |
CONST CLKEY_F5 = 64 ' |/___\| |/___\|/___\|/___\|/___\| |/___\|/___\|/___\|/___\| |/___\|/___\|/___\|/___\| |
CONST CLKEY_F6 = 65 ' |
CONST CLKEY_F7 = 66 ' NOTE: F10 does not register as a _BUTTON. I know, strange but true. |
CONST CLKEY_F8 = 67 ' These _BUTTON contants were provided by gx.bi in dbox's Game Engine: https://github.com/boxgaming/gx |
CONST CLKEY_F9 = 68 ' |
CONST CLKEY_F11 = 88 ' |
CONST CLKEY_F12 = 89 ' |
CONST CLKEY_BACKQUOTE = 42 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_1 = 3 ' FIRST KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_2 = 4 ' |
CONST CLKEY_3 = 5 ' _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _________ |
CONST CLKEY_4 = 6 ' ||`~ |||1! |||2@ |||3# |||4$ |||5% |||6^ |||7& |||8* |||9( |||0) |||-_ |||=+ |||BACKSP || |
CONST CLKEY_5 = 7 ' ||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||_______|| |
CONST CLKEY_6 = 8 ' |/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/_______\| |
CONST CLKEY_7 = 9 ' |
CONST CLKEY_8 = 10 ' |
CONST CLKEY_9 = 11 ' |
CONST CLKEY_0 = 12 ' |
CONST CLKEY_MINUS = 13 ' |
CONST CLKEY_EQUALS = 14 ' |
CONST CLKEY_BACKSPACE = 15 ' |
CONST CLKEY_TAB = 16 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_Q = 17 ' SECOND KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_W = 18 ' |
CONST CLKEY_E = 19 ' _______ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _______ |
CONST CLKEY_R = 20 ' ||TAB |||Q |||W |||E |||R |||T |||Y |||U |||I |||O |||P |||[{ |||]} |||\| || |
CONST CLKEY_T = 21 ' ||_____|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||_____|| |
CONST CLKEY_Y = 22 ' |/_____\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/_____\| |
CONST CLKEY_U = 23 ' |
CONST CLKEY_I = 24 ' |
CONST CLKEY_O = 25 ' |
CONST CLKEY_P = 26 ' |
CONST CLKEY_LBRACKET = 27 ' |
CONST CLKEY_RBRACKET = 28 ' |
CONST CLKEY_BACKSLASH = 44 ' |
CONST CLKEY_CAPSLOCK = 59 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_A = 31 ' THIRD KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_S = 32 ' |
CONST CLKEY_D = 33 ' ________ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ ____________ |
CONST CLKEY_F = 34 ' ||CAPS |||A |||S |||D |||F |||G |||H |||J |||K |||L |||;: |||'" |||ENTER || |
CONST CLKEY_G = 35 ' ||______|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||__________|| |
CONST CLKEY_H = 36 ' |/______\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/__________\| |
CONST CLKEY_J = 37 ' |
CONST CLKEY_K = 38 ' |
CONST CLKEY_L = 39 ' |
CONST CLKEY_SEMICOLON = 40 ' |
CONST CLKEY_QUOTE = 41 ' |
CONST CLKEY_ENTER = 29 ' |
CONST CLKEY_LSHIFT = 43 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_Z = 45 ' FOURTH KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_X = 46 ' |
CONST CLKEY_C = 47 ' _____________ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____________ |
CONST CLKEY_V = 48 ' ||LEFT SHIFT |||Z |||X |||C |||V |||B |||N |||M |||,< |||.> |||/? |||RIGHT SHIFT|| |
CONST CLKEY_B = 49 ' ||___________|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___________|| |
CONST CLKEY_N = 50 ' |/___________\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___________\| |
CONST CLKEY_M = 51 ' |
CONST CLKEY_COMMA = 52 ' |
CONST CLKEY_PERIOD = 53 ' |
CONST CLKEY_SLASH = 54 ' |
CONST CLKEY_RSHIFT = 55 ' |
CONST CLKEY_LCTRL = 30 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_LWIN = 348 ' FIFTH KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_SPACEBAR = 58 ' |
CONST CLKEY_RWIN = 349 ' ______ ______ ______ _____________________________________________ ______ ______ ______ |
CONST CLKEY_RCTRL = 286 ' ||LCTL|||LWIN|||MENU|||SPACEBAR |||N/A |||RWIN|||RCTL|| |
CONST CLKEY_MENU = 350 ' ||____|||____|||____|||___________________________________________|||____|||____|||____|| |
' |/____\|/____\|/____\|/___________________________________________\|/____\|/____\|/____\| |
' |
CONST CLKEY_NUMLOCK = 326 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_NUMPAD_DIVIDE = 310 ' NUMBER PAD _BUTTON CONSTANTS |
CONST CLKEY_NUMPAD_MULTIPLY = 56 ' |
CONST CLKEY_NUMPAD_MINUS = 75 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_7 = 72 ' ||NUM|||/ |||* |||- || |
CONST CLKEY_NUMPAD_8 = 73 ' ||___|||___|||___|||___|| |
CONST CLKEY_NUMPAD_9 = 74 ' |/___\|/___\|/___\|/___\| |
CONST CLKEY_NUMPAD_PLUS = 79 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_4 = 76 ' ||7 |||8 |||9 |||+ || |
CONST CLKEY_NUMPAD_5 = 77 ' ||___|||___|||___||| || |
CONST CLKEY_NUMPAD_6 = 78 ' |/___\|/___\|/___\|| || |
CONST CLKEY_NUMPAD_1 = 80 ' _____ _____ _____|| || |
CONST CLKEY_NUMPAD_2 = 81 ' ||4 |||5 |||6 ||| || |
CONST CLKEY_NUMPAD_3 = 82 ' ||___|||___|||___|||___|| |
CONST CLKEY_NUMPAD_ENTER = 285 ' |/___\|/___\|/___\|/___\| |
CONST CLKEY_NUMPAD_0 = 83 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_PERIOD = 84 ' ||1 |||2 |||3 |||E || |
' ||___|||___|||___|||N || |
' |/___\|/___\|/___\||T || |
' ___________ _____||E || |
' ||0 |||. |||R || |
' ||_________|||___|||___|| |
' |/_________\|/___\|/___\| |
' |
CONST CLKEY_UP = 329 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_LEFT = 332 ' ARROW KEY _BUTTON CONSTANTS |
CONST CLKEY_DOWN = 337 ' |
CONST CLKEY_RIGHT = 334 ' _____ |
' || || |
' ||___|| |
' |/___\| |
' _____ _____ _____ |
' || ||| ||| || |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' |
CONST CLKEY_SCRLK = 71 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_PAUSE = 70 ' POSITION KEY _BUTTON CONSTANTS |
CONST CLKEY_INSERT = 339 ' |
CONST CLKEY_HOME = 328 ' _____ _____ _____ |
CONST CLKEY_PAGEUP = 330 ' ||N/A|||SCR|||PAU|| |
CONST CLKEY_DELETE = 340 ' ||___|||___|||___|| NOTE: Pause not working on my system? |
CONST CLKEY_END = 336 ' |/___\|/___\|/___\| |
CONST CLKEY_PAGEDOWN = 338 ' _____ _____ _____| |
' ||INS|||HOM|||PUP|| |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' _____ _____ _____ |
' ||DEL|||END|||PDN|| |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' |
'\__________________________________________________________________________________________________________________________________________________/
'/ __NEW_CONTROLLER CONSTANTS \
CONST __UNPLUGGED = 1 ' existing controller unplugged - use with __NEW_CONTROLLER |
CONST __PLUGGEDIN = 2 ' existing controller plugged back in - use with __NEW_CONTROLLER |
CONST __NEWCONTROLLER = 3 ' a new controller has been plugged in - use with __NEW_CONTROLLER |
'\__________________________________________________________________________________________________________________________________________________/
'/ TYPE__SLOT \
TYPE TYPE__SLOT ' USER DEFINED BUTTON SLOT PROPERTIES |
Cname AS STRING * 25 ' controller name |
cid AS INTEGER ' controller id number (_DEVICES) |
Button AS INTEGER ' button number (0 if using axis) |
Axis AS INTEGER ' axis number (0 if using button) (- value for UP/LEFT or + value for DOWN/RIGHT) |
Name AS STRING * 15 ' button/axis name |
END TYPE ' |
'\__________________________________________________________________________________________________________________________________________________/
'/ TYPE__BUTTON \
TYPE TYPE__BUTTON ' USER DEFINED BUTTON PROPERTIES |
Slot0 AS TYPE__SLOT ' blank slot to clear others |
Slot1 AS TYPE__SLOT ' user defined button slot 1 |
Slot2 AS TYPE__SLOT ' user defined button slot 2 |
Slot3 AS TYPE__SLOT ' user defined button slot 3 |
Slot4 AS TYPE__SLOT ' user defined button slot 4 |
END TYPE ' |
'\__________________________________________________________________________________________________________________________________________________/
'/ TYPE__CONTROLLER \
TYPE TYPE__CONTROLLER ' DETECTED CONTROLLER PROPERTIES |
Found AS INTEGER ' controller found (t/f) |
Connected AS INTEGER ' controller connected (t/f) |
Name AS STRING * 25 ' description of controller |
Buttons AS INTEGER ' number of buttons controller has ( _LASTBUTTON(Controller) ) |
Axis AS INTEGER ' number of axis controller has ( _LASTAXIS(Controller) ) |
Wheels AS INTEGER ' number of wheels controller has ( _LASTWHEEL(Controller) ) ** NOT IMPLEMENTED YET * |
END TYPE ' |
'\__________________________________________________________________________________________________________________________________________________/
'/ TYPE__SETTINGS \
TYPE TYPE__SETTINGS ' LIBRARY SETTINGS |
Reassign AS INTEGER ' reassign (-1) or ignore (0) already used user defined buttons |
Threshold AS SINGLE ' axis sensitivity when used as a user defined button (.01 to .99) |
FoundDevices AS INTEGER ' number of controllers found when program first started |
END TYPE ' |
'\__________________________________________________________________________________________________________________________________________________/
'/ VARIABLE ASSIGNMENTS \
REDIM CL_BUTTON(1) AS TYPE__BUTTON ' user assigned button array |
DIM CL_CONTROLLER(6) AS TYPE__CONTROLLER ' controller array (index number equals _DEVICES id number) |
DIM CL_KEYNAME(350) AS STRING ' keyboard _BUTTON key names |
DIM CL_SETTINGS AS TYPE__SETTINGS ' library settings |
DIM SHARED __CURRENT_ROUTINE AS STRING ' __ERROR use |
DIM SHARED __PREVIOUS_ROUTINE AS STRING ' __ERROR use |
DIM SHARED __KEYBOARDCID AS INTEGER ' these will contain the device ids (_DEVICES) |
DIM SHARED __MOUSECID AS INTEGER ' |
DIM SHARED __JOYPAD1CID AS INTEGER ' |
DIM SHARED __JOYPAD2CID AS INTEGER ' |
DIM SHARED __JOYPAD3CID AS INTEGER ' |
DIM SHARED __JOYPAD4CID AS INTEGER ' |
DIM SHARED __JOYPAD5CID AS INTEGER ' |
DIM SHARED __JOYPAD6CID AS INTEGER ' |
'\__________________________________________________________________________________________________________________________________________________/
Code: (Select All)
'----------------------------
' Controller Library V1.10
' Terry Ritchie
' May 17th, 2023
' Written using QB64PE v3.7.0
'----------------------------
' CONTROLLER.BM
'----------------------------
'
' TODO: Add WHEEL routines
' Create PDF instructions
'
'----------------------------
' 04/10/23 V1.0 - Initial Release
' 04/26/23 V1.01 - Corrected slot reassigning issues
' 05/17/23 V1.10 - Added __MAKE_BUTTON, __CONNECTED, __SAVE_BUTTONS, __LOAD_BUTTONS, __NEW_CONTROLLER, __REMOVE_CONTROLLER
' - The library now has the ability to save and load controller user defined button configurations
' - You can now detect when a controller has been plugged in or unplugged
' - A controller's user defined button assignments can be removed when the controller has been unplugged
'----------------------------
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __REMOVE_CONTROLLER (cid AS INTEGER) ' __REMOVE_CONTROLLER |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Removes all user defined buttons associated with a controller. |
'| |
'| __REMOVE_CONTROLLER __JOYPAD3CID |
'| |
'| cid - the controller id |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
DIM b AS INTEGER ' button counter
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__REMOVE_CONTROLLER"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-----------------------------------------------------------------------------+
'| Cycle through each assigned button slot. If a button assignment matches the |
'| controller name and controller id then remove the button from the array. |
'+-----------------------------------------------------------------------------+
b = 0 ' reset button counter
DO ' begin button search
b = b + 1 ' increment button counter
IF CL_BUTTON(b).Slot1.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot1.cid = cid THEN ' does controller name and id match in slot 1?
__REMOVE_BUTTON b, 1 ' yes, remove the button assignment in slot 1
END IF
IF CL_BUTTON(b).Slot2.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot2.cid = cid THEN ' does controller name and id match in slot 2?
__REMOVE_BUTTON b, 2
END IF
IF CL_BUTTON(b).Slot3.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot3.cid = cid THEN ' does controller name and id match in slot 3?
__REMOVE_BUTTON b, 3
END IF
IF CL_BUTTON(b).Slot4.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot4.cid = cid THEN ' does controller name and id match in slot 4?
__REMOVE_BUTTON b, 4
END IF
LOOP UNTIL b = UBOUND(CL_BUTTON) ' leave when all buttons checked
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __NEW_CONTROLLER (Action AS INTEGER) ' __NEW_CONTROLLER |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Checks for the addition of a new controller, a controller that has been unplugged, or a controller plugged back in. |
'| |
'| Controller = __NEW_CONTROLLER(Action) |
'| |
'| Action - the returned action that occurred |
'| 0 - nothing changed |
'| 1 - a controller was unplugged (the constant __UNPLUGGED has been created to check for this) |
'| 2 - a controller was plugged back in (the constant __PLUGGEDIN has been created to check for this) |
'| 3 - a new controller has been plugged in (the constant __NEWCONTROLLER has been created to check for this) |
'| |
'| The function will return the following values: |
'| |
'| - the value will contain the new controller id when a new controller is plugged in (Action = 3 ) |
'| - the value will contain the controller id of a controller that was unplugged or plugged back in (Action = 1 or 2) |
'| - a value of 0 (FALSE) if nothing has changed |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
DIM Rescan AS INTEGER ' -1 (TRUE) if controllers need to be rescanned
DIM Devices AS INTEGER ' number of devices currently found
DIM d AS INTEGER ' device counter
__NEW_CONTROLLER = 0 ' assume no new or previous controller plugged in
Action = 0 ' assume no changes
d = 0 ' reset device counter
Rescan = 0 ' reset rescan flag
Devices = _DEVICES ' get number of devices found
IF Devices <> CL_SETTINGS.FoundDevices THEN ' has a new controller been plugged in?
Rescan = -1 ' yes, controllers will need to be rescanned
Action = __NEWCONTROLLER ' remember that a new controller was plugged in
ELSE ' no, check for previous plugged/unplugged controllers
DO ' begin controller search
d = d + 1 ' increment device counter
IF __CONNECTED(d) <> CL_CONTROLLER(d).Connected THEN ' has controller connection status changed?
Rescan = d ' yes, remember which controller has changed and needs rescanned
IF CL_CONTROLLER(d).Connected THEN ' was the controller connected?
Action = __UNPLUGGED ' yes, remember that it was just unplugged
ELSE ' no, the controller was disconnected
Action = __PLUGGEDIN ' remember that it was just plugged back in
END IF
EXIT DO ' no need to check any more controllers
END IF
LOOP UNTIL d = Devices ' leave when all controllers checked
END IF
IF Rescan THEN ' need to scan for new/unplugged/plugged in controllers?
__IDENTIFY_CONTROLLERS ' yes, identify connected controllers
IF Rescan = -1 THEN ' was a new controller found?
__NEW_CONTROLLER = CL_SETTINGS.FoundDevices ' yes, return the new controller id number
ELSE ' no, a controller was unplugged/plugged back in
__NEW_CONTROLLER = Rescan ' return the controller that was unplugged/plugged back in
END IF
END IF
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __MAKE_BUTTON (Handle AS INTEGER) ' __MAKE_BUTTON |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Assigns a value to a user generated integer button variable. |
'| |
'| DIM UPButton AS INTEGER |
'| __MAKE_BUTTON UPButton ' define the integer variable UPButton as a user defined button |
'| |
'| Handle - the name of the variable the user wishes to use as a button reference. |
'| The variable's value will change to indicate the new handle value pointing to the button array index. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__MAKE_BUTTON"
IF Handle THEN __ERROR "This button has already been created"
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+----------------------------------------------+
'| Create a new entry for the button assignment |
'+----------------------------------------------+
Handle = UBOUND(CL_BUTTON) + 1 ' set handle to new size of button array
REDIM _PRESERVE CL_BUTTON(Handle) AS TYPE__BUTTON ' increase size of button array to match new handle
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __SAVE_BUTTONS () ' __SAVE_BUTTONS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Saves all assigned buttons for all currently discovered and connected controllers. |
'| |
'| __SAVE_BUTTONS |
'| |
'| The config files created for the controllers will be in the form: [Controller Name].ID[Device ID#] |
'| For example, a joystick with the name Saitek ST290 Pro found as device number 4 will have the following config file: "Saitek ST290 Pro.ID4" |
'| |
'| It's possible for a controller to have multiple config files based on the device id number. |
'| - "Saitek ST290 Pro.ID3" |
'| - "Saitek ST290 Pro.ID4" |
'| - "Saitek ST290 Pro.ID5" |
'| - etc.. |
'| |
'| This allows for multiple configurations based on which player is using which joystick/game pad in any order. |
'| |
'| Controllers with no assigned buttons will create config files that are zero bytes in length. This is normal. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
DIM Fname AS STRING ' controller config file name
DIM b AS INTEGER ' button counter
DIM cid AS INTEGER ' controller id counter
DIM FF AS LONG ' next available free file handle
cid = 0 ' reset controller id counter
DO ' begin controller search loop
cid = cid + 1 ' increment controller id counter
IF CL_CONTROLLER(cid).Found THEN ' was this controller found initially?
IF __CONNECTED(cid) THEN ' yes, is this controller still connected?
'+---------------------------------------------------+
'| This controller is in use and currently connected |
'| Create and open a config file for this controller |
'+---------------------------------------------------+
Fname = _TRIM$(CL_CONTROLLER(cid).Name) + ".ID" + _TRIM$(STR$(cid)) ' yes, build the name of controller's config file
FF = FREEFILE ' get a free file handle
OPEN Fname FOR OUTPUT AS #FF ' open the config file for writing
b = 0 ' reset button counter
'+-----------------------------------------------------------------------------+
'| Cycle through each assigned button slot. If a button assignment matches the |
'| controller name and controller id save the variable assignment value, the |
'| button value (0 if axis is used), and the axis value (0 if button is used). |
'+-----------------------------------------------------------------------------+
DO ' begin assignment search and write loop
b = b + 1 ' increment button counter
IF CL_BUTTON(b).Slot1.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot1.cid = cid THEN ' does controller name and id match in slot 1?
WRITE #FF, b, CL_BUTTON(b).Slot1.Button, CL_BUTTON(b).Slot1.Axis ' yes, write assignment to file
END IF
IF CL_BUTTON(b).Slot2.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot2.cid = cid THEN ' does controller name and id match in slot 2?
WRITE #FF, b, CL_BUTTON(b).Slot2.Button, CL_BUTTON(b).Slot2.Axis ' yes, write assignment to file
END IF
IF CL_BUTTON(b).Slot3.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot3.cid = cid THEN ' does controller name and id match in slot 3?
WRITE #FF, b, CL_BUTTON(b).Slot3.Button, CL_BUTTON(b).Slot3.Axis ' yes, write assignment to file
END IF
IF CL_BUTTON(b).Slot4.Cname = CL_CONTROLLER(cid).Name AND CL_BUTTON(b).Slot4.cid = cid THEN ' does controller name and id match in slot 4?
WRITE #FF, b, CL_BUTTON(b).Slot4.Button, CL_BUTTON(b).Slot4.Axis ' yes, write assignment to file
END IF
LOOP UNTIL b = UBOUND(CL_BUTTON) ' leave when all button assignments checked
CLOSE #FF ' close the file
END IF
END IF
LOOP UNTIL cid = 6 ' leave when all controllers checked
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __LOAD_BUTTONS () ' __LOAD_BUTTONS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Loads assigned buttons for controllers from configuration files if they exist. |
'| |
'| __LOAD_BUTTONS |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
DIM Fname AS STRING ' controller config file name
DIM cid AS INTEGER ' controller id counter
DIM Handle AS INTEGER ' user defined button handle
DIM Button AS INTEGER ' button to assign (0 if axis)
DIM Axis AS INTEGER ' axis to assign (0 if button)
DIM FF AS LONG ' next available free file handle
cid = 0 ' reset controller id counter
DO ' begin controller search loop
cid = cid + 1 ' increment controller id counter
IF CL_CONTROLLER(cid).Found THEN ' was this controller found initially?
IF __CONNECTED(cid) THEN ' yes, is this controller still connected?
'+-----------------------------------------------------------------+
'| This controller was initially found and is currently connected. |
'| Create a config file name to check for. |
'+-----------------------------------------------------------------+
Fname = _TRIM$(CL_CONTROLLER(cid).Name) + ".ID" + _TRIM$(STR$(cid)) ' yes, build the name of the controller's config file
IF _FILEEXISTS(Fname) THEN ' does a config file for this controller exist?
'+-------------------------------------------+
'| A config file exists for this controller |
'| Open the file and assign the buttons/axes |
'+-------------------------------------------+
FF = FREEFILE ' yes, get a free file handle
OPEN Fname FOR INPUT AS #FF ' open the config file for reading
WHILE NOT EOF(1) ' has the end of the file been reached?
'+---------------------------------------------------------------+
'| Config files that are zero bytes in length are simply ignored |
'+---------------------------------------------------------------+
INPUT #FF, Handle, Button, Axis ' no, get the button handle, button, and axis settings
IF Button THEN ' has a button been assigned?
__ASSIGN_BUTTON Handle, cid, Button ' yes, assign the button
ELSE ' no, an axis is assigned
__ASSIGN_AXIS Handle, cid, Axis ' assign the axis as a button
END IF
WEND ' loop back and load next button assignment (if any)
CLOSE #FF ' close the config file
END IF
END IF
END IF
LOOP UNTIL cid = 6 ' leave when all controllers searched
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __CONNECTED (cid AS INTEGER) ' __CONNECTED |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns 0 (FALSE) if a controller is disconnected, -1 (TRUE) otherwise |
'| |
'| Status = __CONNECTED(__JOYPAD1CID) |
'| |
'| cid - the id of the controller |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__CONNECTED"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-------------------------+
'| Return connection state |
'+-------------------------+
WHILE _DEVICEINPUT(cid): WEND ' get latest controller values
IF INSTR(_DEVICE$(cid), "[DISCONNECTED]") THEN ' is controller disconnected?
__CONNECTED = 0 ' yes, return that controller is disconnected
ELSE ' no
__CONNECTED = -1 ' return that controller is connected
END IF
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __BUTTON_NAME$ (Handle AS INTEGER, Slot AS INTEGER) ' __BUTTON_NAME$ |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Retrieves the name of a user defined button. |
'| |
'| Description = __BUTTON_NAME$(Up_Button, 1) ' get name of button in slot 1 |
'| |
'| Handle - the handle of the user defined button |
'| Slot - the slot number (1 to 4) |
'| passing the value of 0 will clear all slot assignments and remove the user defined button completely. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__BUTTON_NAME$"
IF Handle < 1 OR Handle > UBOUND(CL_BUTTON) THEN __ERROR "The specified button does not exist."
IF Slot < 0 OR Slot > 4 THEN __ERROR "The requested slot assignment does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-----------------+
'| Get button name |
'+-----------------+
SELECT CASE Slot
CASE 1: __BUTTON_NAME$ = CL_BUTTON(Handle).Slot1.Name
CASE 2: __BUTTON_NAME$ = CL_BUTTON(Handle).Slot2.Name
CASE 3: __BUTTON_NAME$ = CL_BUTTON(Handle).Slot3.Name
CASE 4: __BUTTON_NAME$ = CL_BUTTON(Handle).Slot4.Name
END SELECT
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __SET_AXIS_THRESHOLD (Value AS SINGLE) ' __SET_AXIS_THRESHOLD |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Sets the value at which an axis set up as a user defined button is seen as being pressed. |
'| |
'| __SET_AXIS_THRESHOLD .25 ' button activated when axis is deflected 25% either UP/DOWN or LEFT/RIGHT |
'| |
'| Value - .01 (1%) to .99 (99%) of axis deflection |
'| |
'| NOTE: The default value set up by __INITIALIZE_CONTROLLERS is .5 (50%) |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__SET_AXIS_THRESHOLD"
IF Value <= 0 OR Value >= 1 THEN __ERROR "Threshold value must be between 0 and 1."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+---------------------+
'| Set threshold value |
'+---------------------+
CL_SETTINGS.Threshold = Value ' set value of user defined button axis sensitivity
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __BUTTON_REASSIGN_ALLOWED () ' __BUTTON_REASSIGN_ALLOWED |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Enables user defined button reassigning. |
'| |
'| __BUTTON_REASSIGN_ALLOWED |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
'+---------------------------+
'| Enable button reassigning |
'+---------------------------+
CL_SETTINGS.Reassign = -1 ' enable button reassigning (TRUE)
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __BUTTON_REASSIGN_NOT_ALLOWED () ' __BUTTON_REASSIGN_NOT_ALLOWED |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Disables user defined button reassigning. |
'| |
'| __BUTTON_REASSIGN_NOT_ALLOWED |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
'+----------------------------+
'| Disable button reassigning |
'+----------------------------+
CL_SETTINGS.Reassign = 0 ' disable button reassigning (FALSE)
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __REMOVE_BUTTON (Handle AS INTEGER, Slot AS INTEGER) ' __REMOVE_BUTTON |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Removes an assigned button or axis from a user defined button. Optionally the entire user defined button can be removed by supplying the |
'| value of 0 for slot. |
'| |
'| __REMOVE_BUTTON UP_Button, 3 ' remove the button/axis assigned in the third slot |
'| |
'| Handle - the handle of the user defined button |
'| Slot - the assigned slot to clear (0 to 4) |
'| passing the value of 0 will clear all slot assignments and remove the user defined button completely. |
'| |
'| When a defined button is removed from a slot the assignments in slots above are shifted down. For example, if the assignment in slot 1 is |
'| removed then the assignment in 2 is shifted to 1, 3 is shifted to 2, 4 is shifted to 3, and 4 is cleared. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__REMOVE_BUTTON"
IF Handle < 1 OR Handle > UBOUND(CL_BUTTON) THEN __ERROR "The specified button does not exist."
IF Slot < 0 OR Slot > 4 THEN __ERROR "The requested slot assignment does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+----------------------+
'| Remove assignment(s) |
'+----------------------+
SELECT CASE Slot ' which slot?
CASE 0 ' [ALL SLOTS]
CL_BUTTON(Handle).Slot1 = CL_BUTTON(Handle).Slot0 ' clear slot 1
CL_BUTTON(Handle).Slot2 = CL_BUTTON(Handle).Slot0 ' clear slot 2
CL_BUTTON(Handle).Slot3 = CL_BUTTON(Handle).Slot0 ' clear slot 3
CL_BUTTON(Handle).Slot4 = CL_BUTTON(Handle).Slot0 ' clear slot 4
CASE 1 ' [SLOT1]
CL_BUTTON(Handle).Slot1 = CL_BUTTON(Handle).Slot2 ' move slot 2 up to slot 1
CL_BUTTON(Handle).Slot2 = CL_BUTTON(Handle).Slot3 ' move slot 3 up to slot 2
CL_BUTTON(Handle).Slot3 = CL_BUTTON(Handle).Slot4 ' move slot 4 up to slot 3
CL_BUTTON(Handle).Slot4 = CL_BUTTON(Handle).Slot0 ' clear slot 4
CASE 2 ' [SLOT2]
CL_BUTTON(Handle).Slot2 = CL_BUTTON(Handle).Slot3 ' move slot 3 up to slot 2
CL_BUTTON(Handle).Slot3 = CL_BUTTON(Handle).Slot4 ' move slot 4 up to slot 3
CL_BUTTON(Handle).Slot4 = CL_BUTTON(Handle).Slot0 ' clear slot 4
CASE 3 ' [SLOT3]
CL_BUTTON(Handle).Slot3 = CL_BUTTON(Handle).Slot4 ' move slot 4 up to slot 3
CL_BUTTON(Handle).Slot4 = CL_BUTTON(Handle).Slot0 ' clear slot 4
CASE 4 ' [SLOT4]
CL_BUTTON(Handle).Slot4 = CL_BUTTON(Handle).Slot0 ' clear slot 4
END SELECT
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __JOYPAD_EXISTS (Number AS INTEGER) ' __JOYPAD_EXISTS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the total number of joysticks/game pads that exist (TREU) if the selected joystick/game pad exists, 0 (FALSE) otherwise. |
'| |
'| JoyPads = __JOYPAD_EXISTS(1) ' get total number of joysticks/game pads (if any) |
'| IF JoyPads THEN ' was the selected joypad found? |
'| PRINT "Joystick 1 of"; STR$(JoyPads); " found!" ' yes, report findings |
'| Print "Joystick name : ";__CONTROLLER_NAME$(__JOYPAD1CID) |
'| PRINT "Number of buttons:"; __BUTTON_TOTAL(__JOYPAD1CID) |
'| PRINT "Number of axes :"; __AXIS_TOTAL(__JOYPAD1CID) |
'| END IF |
'| |
'| number - the joystick/game pad to query |
'\_______________________________________________________________________________________________________________________________________________/
DIM Found AS INTEGER ' joypad found (t/f)
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__JOYPAD_EXISTS"
IF Number < 1 OR Number > 6 THEN __ERROR "The requested joystick/game pad does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+---------------------------------------+
'| Report existance of joystick/game pad |
'+---------------------------------------+
Found = 0 ' assume no joystick/game pad found
__JOYPAD_EXISTS = 0 ' assume there are no joypads
SELECT CASE Number ' which joypad are we looking for?
CASE 1 ' joypad 1
IF __JOYPAD1CID THEN Found = -1 ' record found if present
CASE 2 ' etc..
IF __JOYPAD2CID THEN Found = -1
CASE 3
IF __JOYPAD3CID THEN Found = -1
CASE 4
IF __JOYPAD4CID THEN Found = -1
CASE 5
IF __JOYPAD5CID THEN Found = -1
CASE 6
IF __JOYPAD6CID THEN Found = -1
END SELECT
IF Found THEN ' was a joypad found?
IF __JOYPAD6CID THEN ' yes, are there 6 joypads?
__JOYPAD_EXISTS = 6 ' yes, return that 6 exist
ELSEIF __JOYPAD5CID THEN ' no, are there 5 joypads?
__JOYPAD_EXISTS = 5 ' yes, return that 5 exist
ELSEIF __JOYPAD4CID THEN ' etc..
__JOYPAD_EXISTS = 4
ELSEIF __JOYPAD3CID THEN
__JOYPAD_EXISTS = 3
ELSEIF __JOYPAD2CID THEN
__JOYPAD_EXISTS = 2
ELSEIF __JOYPAD1CID THEN
__JOYPAD_EXISTS = 1
END IF
END IF
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __MOUSE_EXISTS () ' __MOUSE_EXISTS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns -1 (TRUE) if the mouse controller exists, 0 (FALSE) otherwise. |
'| |
'| IF __MOUSE_EXISTS THEN PRINT "Mouse found!" |
'| |
'| NOTE: It's highly unlikely that a mouse will not exist but for those instances where someone may have created a stand alone computer for |
'| playing QB64 games without a mouse (and/or a keyboard) but just joysticks attached this function is available. |
'\_______________________________________________________________________________________________________________________________________________/
__MOUSE_EXISTS = 0 ' assume no mouse
IF __MOUSECID THEN __MOUSE_EXISTS = -1 ' report that mouse found
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __KEYBOARD_EXISTS () ' __KEYBOARD_EXISTS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns -1 (TRUE) if the keyboard controller exists, 0 (FALSE) otherwise. |
'| |
'| IF __KEYBOARD_EXISTS THEN PRINT "Keyboard found!" |
'| |
'| NOTE: It's highly unlikely that a keyboard will not exist but for those instances where someone may have created a stand alone computer for |
'| playing QB64 games without a keyboard (and/or a mouse) but just joysticks attached this function is available. |
'\_______________________________________________________________________________________________________________________________________________/
__KEYBOARD_EXISTS = 0 ' assume no keyboard
IF __KEYBOARDCID THEN __KEYBOARD_EXISTS = -1 ' report that keyboard was found
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __MAP_AXIS (AxisValue AS SINGLE, Lower AS INTEGER, Upper AS INTEGER) ' __MAP_AXIS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Maps a joypad or mouse axis value from -1 to 1 to another defined range. |
'| |
'| Xaxis = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD1CID, 1), 0, 255) ' map -1 to 1 as 0 to 255 |
'| |
'| AxisValue - current axis value (must be -1 to 1) |
'| Lower - the new lower value range |
'| Upper - the new upper value range |
'| |
'| NOTE: This function will only work correctly when AxisValue is between -1 and 1. |
'\_______________________________________________________________________________________________________________________________________________/
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__MAP_AXIS"
IF AxisValue < -1 OR AxisValue > 1 THEN __ERROR "Axis value must be between -1 and 1."
IF Lower >= Upper THEN __ERROR "The lower value must be less than the upper value."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-----------------------------------+
'| Convert input to new output range |
'+-----------------------------------+
__MAP_AXIS = INT(Lower + (AxisValue + 1) * (Lower - Upper) / -2) ' convert input to adjusted output
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __AXIS_TOTAL (cid AS INTEGER) ' __AXIS_TOTAL |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the number of axes a controller has. |
'| |
'| Total = __AXIS_TOTAL(__JOYPAD1CID) |
'| |
'| cid - the controller id |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__AXIS_TOTAL"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF CL_CONTROLLER(cid).Axis = 0 THEN __ERROR "The specified controller has no axes."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+----------------------------------+
'| Return number of controller axis |
'+----------------------------------+
__AXIS_TOTAL = CL_CONTROLLER(cid).Axis ' return number of axes
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __BUTTON_TOTAL (cid AS INTEGER) ' __BUTTON_TOTAL |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the number of buttons a controller has. |
'| |
'| Total = __BUTTON_TOTAL(__JOYPAD1CID) |
'| |
'| cid - the controller id |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__BUTTON_TOTAL"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF CL_CONTROLLER(cid).Buttons = 0 THEN __ERROR "The specified controller has no buttons."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-------------------------------------+
'| Return number of controller buttons |
'+-------------------------------------+
__BUTTON_TOTAL = CL_CONTROLLER(cid).Buttons ' return number of buttons
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __CONTROLLER_BUTTON (cid AS INTEGER, Button AS INTEGER) ' __CONTROLLER_BUTTON |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the state of a controller's button. |
'| |
'| Button = __CONTROLLER_BUTTON(__KEYBOARDCID, 329) ' keyboard UP arrow key |
'| |
'| cid - the controller id |
'| Button - the controller's button (or keyboard key) |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__CONTROLLER_BUTTON"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF CL_CONTROLLER(cid).Buttons = 0 THEN __ERROR "The specified controller has no buttons."
IF Button < 1 OR Button > CL_CONTROLLER(cid).Buttons THEN __ERROR "The specified controller does not have this button."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-----------------------------+
'| Return current button state |
'+-----------------------------+
IF __CONNECTED(cid) THEN ' is controller connected?
WHILE _DEVICEINPUT(cid): WEND ' yes, get latest controller values
__CONTROLLER_BUTTON = _BUTTON(Button) ' return controller button state
END IF
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __CONTROLLER_AXIS (cid AS INTEGER, Axis AS INTEGER) ' __CONTROLLER_AXIS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the value of a controller's axis. (-1 to 1) |
'| |
'| Xaxis = __CONTROLLER_AXIS(__JOYPAD1CID, 1) ' x axis of joypad 1 |
'| |
'| cid - the controller id |
'| Axis - the controller's axis number |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__CONTROLLER_AXIS"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF CL_CONTROLLER(cid).Axis = 0 THEN __ERROR "The specified controller has no axes."
IF Axis < 1 OR Axis > CL_CONTROLLER(cid).Axis THEN __ERROR "The specified controller does not have this axis."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+---------------------------+
'| Return current axis value |
'+---------------------------+
IF __CONNECTED(cid) THEN ' is controller connected?
WHILE _DEVICEINPUT(cid): WEND ' yes, get latest controller values
__CONTROLLER_AXIS = _AXIS(Axis) ' return controller axis value
END IF
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __CONTROLLER_NAME$ (cid AS INTEGER) ' __CONTROLLER_NAME$ |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns the descriptive name of the controller. |
'| |
'| PRINT __CONTROLLER_NAME$(__JOYPAD1CID) |
'| |
'| cid - the id of the controller |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__CONTROLLER_NAME$"
IF cid < 1 OR cid > 6 THEN __ERROR "Invalid controller id."
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist"
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+---------------------------+
'| Return name of controller |
'+---------------------------+
__CONTROLLER_NAME$ = CL_CONTROLLER(cid).Name ' return the name of the controller
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION __BUTTON_DOWN (Handle AS INTEGER) ' __BUTTON_DOWN |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns -1 (TRUE) if a button is pressed, 0 (FALSE) otherwise. |
'| |
'| State = __BUTTON_DOWN(UPButton) |
'| |
'| Handle - the handle of the button to check |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
DIM Slot AS INTEGER ' button/axis slot counter
DIM cid AS INTEGER ' controller id
DIM Button AS INTEGER ' controller button
DIM Axis AS INTEGER ' controller axis
DIM AxisValue AS SINGLE ' controller current axis value
DIM Down AS INTEGER ' button is down (t/f)
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__BUTTON_DOWN"
IF Handle < 1 OR Handle > UBOUND(CL_BUTTON) THEN __ERROR "The specified button does not exist."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-------------------------+
'| Report status of button |
'+-------------------------+
Down = 0 ' assume no button/axis pressed
Slot = 0 ' reset slot counter
DO ' begin button/axis down search
Slot = Slot + 1 ' increment slot counter
'+----------------------------------------------------------+
'| Get the controller's id, button, and axis from each slot |
'+----------------------------------------------------------+
SELECT CASE Slot ' which button/axis slot?
CASE 1 ' slot 1
cid = CL_BUTTON(Handle).Slot1.cid ' get controller's id from slot 1
Button = CL_BUTTON(Handle).Slot1.Button ' get controller's button from slot 1
Axis = CL_BUTTON(Handle).Slot1.Axis ' get controller's axis from slot 1
CASE 2 ' slot 2
cid = CL_BUTTON(Handle).Slot2.cid
Button = CL_BUTTON(Handle).Slot2.Button
Axis = CL_BUTTON(Handle).Slot2.Axis
CASE 3 ' slot 3
cid = CL_BUTTON(Handle).Slot3.cid
Button = CL_BUTTON(Handle).Slot3.Button
Axis = CL_BUTTON(Handle).Slot3.Axis
CASE 4 ' slot 4
cid = CL_BUTTON(Handle).Slot4.cid
Button = CL_BUTTON(Handle).Slot4.Button
Axis = CL_BUTTON(Handle).Slot4.Axis
END SELECT
IF cid THEN ' is there a controller id?
'+---------------------------------------+
'| A controller id was found in the slot |
'+---------------------------------------+
WHILE _DEVICEINPUT(cid): WEND ' yes, get controller's latest values
IF Button THEN ' does a controller button need checked?
'+--------------------------------------------+
'| This slot contained a button to be checked |
'+--------------------------------------------+
IF _BUTTON(Button) THEN Down = -1 ' yes, get state of controller button
ELSEIF Axis THEN ' no, does a controller axis need checked?
'+-------------------------------------------+
'| This slot contained an axis to be checked |
'+-------------------------------------------+
AxisValue = _AXIS(ABS(Axis)) ' yes, get the current controller axis value
IF ABS(AxisValue) >= CL_SETTINGS.Threshold THEN ' is axis deflected at least to sensitivity setting?
IF SGN(AxisValue) = SGN(Axis) THEN Down = -1 ' yes, get state of axis
END IF
END IF
END IF
LOOP UNTIL (Slot = 4) OR Down ' leave when all four slots checked or a button is down
__BUTTON_DOWN = Down ' return state of button
END FUNCTION
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __AUTOASSIGN_BUTTON (Handle AS INTEGER) ' __AUTOASSIGN_BUTTON |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Automatically assigns a button handle with up to a combination of four controller buttons or axis deflections. Simply call this subroutine up |
'| to four times to associate each axis or button with the handle. This allows axis deflections to be treated as button presses. Good for top |
'| hats and Nintendo style "plus" directionals. |
'| |
'| __AUTOASSIGN_BUTTON UPButton ' player chooses the UP ARROW key for instance and that gets saved in SLOT 1 |
'| __AUTOASSIGN_BUTTON UPButton ' player chooses the W key for instance and that gets saved in SLOT 2 |
'| __AUTOASSIGN_BUTTON UPButton ' player chooses the UP direction on a "plus" pad for instance and that gets saved in SLOT 3 |
'| ' the player now has three different methods of inputting a directional UP movement |
'| |
'| Handle - button handle |
'| |
'| The result of the scan is sent to either __ASSIGN_AXIS or __ASSIGN_BUTTON. See the documentation for these two subrotuines for more |
'| information on how the resulting values are stored and used. |
'| |
'| NOTE: Once all four button slots are filled any attempt to associate a handle with more axis or buttons is ignored. |
'| Mouse axes are ignored during auto assign. Use __ASSIGN_AXIS if you wish to assign a mouse axis as a button (not recommended). |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
DIM cid AS INTEGER ' controller id
DIM Number AS INTEGER ' axis/button number (or keyboard scan code) counter
DIM Button AS INTEGER ' button number (or keyboard scan code) that was pressed
DIM Axis AS INTEGER ' axis that was deflected
DIM AxisValue AS SINGLE ' value of axis that was deflected
DO ' begin controller interaction search
'+---------------------------------------------+
'| Wait for a controller to be interacted with |
'+---------------------------------------------+
_LIMIT 60 ' don't hog the CPU while waiting
cid = _DEVICEINPUT ' check for a controller interaction
IF cid THEN ' was a controller interacted with?
'+----------------------------------+
'| A controller was interacted with |
'+----------------------------------+
WHILE _DEVICEINPUT(cid): WEND
IF CL_CONTROLLER(cid).Buttons <> 0 THEN ' yes, does this controler have buttons?
'+---------------------------------------+
'| This controller has buttons available |
'+---------------------------------------+
Number = 0 ' yes, reset button number counter
Button = 0 ' reset button press number
DO ' begin button search
'+--------------------------------------+
'| Get button (if any) that was pressed |
'+--------------------------------------+
Number = Number + 1 ' increment button number counter
IF _BUTTON(Number) THEN Button = Number ' record this button number if it was pressed
LOOP UNTIL Number = _LASTBUTTON(cid) OR Button ' leave when all buttons checked or a button weas pressed
END IF
'+--------------------------------------------------+
'| A check for axis deflection will now be done. |
'| The mouse is purposely excluded from this check. |
'+--------------------------------------------------+
IF cid <> __MOUSECID THEN ' is this the mouse controller?
IF CL_CONTROLLER(cid).Axis <> 0 THEN ' no, does this controller have axis?
'+------------------------------------+
'| This controller has axis available |
'+------------------------------------+
Number = 0 ' yes, reset axis number counter
Axis = 0 ' reset axis deflection number
DO ' begin axis search
'+--------------------------------------------------------------------------+
'| Get axis (if any) that was deflected at least 50% (or threshold setting) |
'+--------------------------------------------------------------------------+
Number = Number + 1 ' increment axis number counter
AxisValue = _AXIS(Number) ' get current value of axis
IF ABS(AxisValue) >= CL_SETTINGS.Threshold THEN ' was axis delfected at least to sensitivity setting?
'+----------------------------------------------------------------------------------------------------------+
'| The axis number is recorded as a negative value if the deflection was in a negative direction. |
'| Likewise, the axis number is recorded as a positive value if the deflection was in a positive direction. |
'| This allows one axis to be recorded as two separate button actions (UP/DOWN or LEFT/RIGHT). |
'+----------------------------------------------------------------------------------------------------------+
Axis = Number * SGN(AxisValue) ' yes, record axis with sign (+/-) of deflection
END IF
LOOP UNTIL Number = _LASTAXIS(cid) OR Axis ' leave when all axis checked or an axis was deflected
END IF
END IF
END IF
LOOP UNTIL cid <> 0 AND (Button <> 0 OR Axis <> 0) ' leave when a controller interacted with and interaction was with a button or axis
IF cid = __KEYBOARDCID THEN _KEYCLEAR ' clear all keyboard buffers if the keyboard was interacted with
IF Button THEN __ASSIGN_BUTTON Handle, cid, Button ' assign the button to the handle
IF Axis THEN __ASSIGN_AXIS Handle, cid, Axis ' assign the axis to the handle
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __ASSIGN_AXIS (Handle AS INTEGER, cid AS INTEGER, Axis AS INTEGER) ' __ASSIGN_AXIS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Associates a handle with up to four axis from the mouse or joypads. Simply call this subroutine up to four times to associate a new axis to |
'| the handle. This allows axis deflections to be treated as button presses. Good for top hats and Nintendo style "plus" directionals. |
'| |
'| __ASSIGN_AXIS UPButton, __JOYPAD1INPUT, -1 ' joystick/gamepad axis 1 UP |
'| __ASSIGN_AXIS DOWNButton, __JOYPAD1INPUT, 1 ' joystick/gamepad axis 1 DOWN |
'| __ASSIGN_AXIS LEFTButton, __JOYPAD1INPUT, -2 ' joystick/gamepad axis 2 LEFT |
'| __ASSIGN_AXIS RIGHTButton, __JOYPAD1INPUT, 2 ' joystick/gamepad axis 2 RIGHT |
'| |
'| Handle - button handle |
'| cid - controller id (1-keyboard, 2-mouse, 3-joypad, etc..) |
'| Axis - controller axis number ( 1 to _LASTAXIS(id) ) |
'| the sign (+/-) of Axis determines which deflection direction will be used as a button press. |
'| Negative typically means UP or LEFT and positive typically means DOWN or RIGHT. |
'| |
'| NOTE: Once all four button slots are filled any attempt to associate a handle with more axis is ignored. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
SHARED CL_KEYNAME() AS STRING ' need access to _BUTTON keyboard key names
DIM Assigning AS TYPE__SLOT ' check slot UDT
DIM AssignedHandle AS INTEGER ' previously assigned button handle
DIM AssignedSlot AS INTEGER ' previously assigned button handle slot
DIM Aname AS STRING ' descriptive axis name
DIM Jname AS STRING ' joystick/game pad name
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__BUTTON_AXIS_ASSIGN"
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF ABS(Axis) < 1 OR ABS(Axis) > _LASTAXIS(cid) THEN __ERROR "The axis specified does not exist on controller."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-----------------------------------+
'| Check if axis is already assigned |
'+-----------------------------------+
Assigning.cid = cid ' set up check slot UDT
Assigning.Button = 0
Assigning.Axis = Axis
IF IUO__ALREADY_ASSIGNED(Assigning, AssignedHandle, AssignedSlot) THEN ' is this axis button already assigned?
'+-------------------------------------+
'| This axis has already been assigned |
'+-------------------------------------+
IF Handle = AssignedHandle THEN ' is this axis already assigned to this handle?
'+---------------------------------------------+
'| This axis is aleady assigned to this handle |
'+---------------------------------------------+
EXIT SUB ' yes, leave subroutine so duplicate is not made
ELSE ' no, this is a new valid assignment
IF CL_SETTINGS.Reassign THEN ' yes, is reassigning allowed?
'+-----------------------------------+
'| Reassigning of buttons is allowed |
'+-----------------------------------+
IF Handle = 0 OR CL_BUTTON(Handle).Slot1.cid = 0_
OR CL_BUTTON(Handle).Slot2.cid = 0_
OR CL_BUTTON(Handle).Slot3.cid = 0_
OR CL_BUTTON(Handle).Slot4.cid = 0 THEN ' yes, is there a slot available?
'+---------------------------------------------------------------+
'| This is either a new user assigned button or an existing user |
'| assigned button with a slot availabe so remove old assignment |
'+---------------------------------------------------------------+
__REMOVE_BUTTON AssignedHandle, AssignedSlot ' yes, remove previous button assignment
END IF
ELSE ' no, reassigning not allowed
'+---------------------------------------+
'| Reassigning of buttons is not allowed |
'+---------------------------------------+
EXIT SUB ' leave subroutine
END IF
END IF
END IF
'+----------------------------------------+
'| Create a descriptive name for the axis |
'+----------------------------------------+
Jname = "" ' clear joystick name
SELECT CASE cid ' which controller?
CASE __MOUSECID ' mouse
IF ABS(Axis) = 1 THEN ' is this axis 1?
IF SGN(Axis) = -1 THEN ' yes, up (negative)?
Aname = "Mouse Up" ' yes, create name
ELSE ' no, down (positive)
Aname = "Mouse Down" ' create name
END IF
ELSE ' no, this must be axis 2
IF SGN(Axis) = -1 THEN ' left (negative)?
Aname = "Mouse Left" ' yes, create name
ELSE ' no, right (positive)
Aname = "Mouse Right" ' create name
END IF
END IF
CASE __JOYPAD1CID: Jname = "J1" ' joystick/game pad 1
CASE __JOYPAD2CID: Jname = "J2" ' joystick/game pad 2
CASE __JOYPAD3CID: Jname = "J3" ' joystick/game pad 3
CASE __JOYPAD4CID: Jname = "J4" ' joystick/game pad 4
CASE __JOYPAD5CID: Jname = "J5" ' joystick/game pad 5
CASE __JOYPAD6CID: Jname = "J6" ' joystick/game pad 6
END SELECT
IF Jname <> "" THEN ' was a joystick name given?
'+-----------------------------------------+
'| The axis belongs to a joystick/game pad |
'+-----------------------------------------+
SELECT CASE ABS(Axis) ' yes, which axis?
CASE 1: IF SGN(Axis) = -1 THEN Aname = "A1 Left" ELSE Aname = "A1 Right" ' axis 1, left or right
CASE 2: IF SGN(Axis) = -1 THEN Aname = "A2 Up" ELSE Aname = "A2 Down" ' axis 2, up or down
CASE 3: IF SGN(Axis) = -1 THEN Aname = "A3 Left" ELSE Aname = "A3 Right" ' axis 3, left or right
CASE 4: IF SGN(Axis) = -1 THEN Aname = "A4 Up" ELSE Aname = "A4 Down" ' axis 4, up or down
END SELECT
Aname = Jname + Aname ' complete joystick name
END IF
'+-------------------------+
'| Save button information |
'+-------------------------+
Assigning.cid = cid ' set up button to save
Assigning.Button = 0
Assigning.Axis = Axis
Assigning.Name = Aname
Assigning.Cname = __CONTROLLER_NAME$(cid)
IF CL_BUTTON(Handle).Slot4.cid THEN ' 4 buttons/axis already assigned?
'+--------------------------------------------------------------------------+
'| There are no more available slots to assign another axis to this handle. |
'+--------------------------------------------------------------------------+
EXIT SUB ' yes, leave subroutine, no more room
ELSEIF CL_BUTTON(Handle).Slot3.cid THEN ' no, 3 buttons/axis already assigned?
CL_BUTTON(Handle).Slot4 = Assigning
ELSEIF CL_BUTTON(Handle).Slot2.cid THEN ' no, 2 buttons/axis already assigned?
CL_BUTTON(Handle).Slot3 = Assigning
ELSEIF CL_BUTTON(Handle).Slot1.cid THEN ' no, 1 button/axis already assigned?
CL_BUTTON(Handle).Slot2 = Assigning
ELSE ' no buttons/axis have been assigned yet
CL_BUTTON(Handle).Slot1 = Assigning
END IF
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __ASSIGN_BUTTON (Handle AS INTEGER, cid AS INTEGER, Button AS INTEGER) ' __ASSIGN_BUTTON |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Associates a handle with up to four buttons from the keyboard, mouse, or joypads. Simply call this subroutine up to four times to associate a |
'| new button to the handle. |
'| |
'| __ASSIGN_BUTTON FireButton, __KEYBOARDINPUT, CLKEY_SPACEBAR ' keyboard space bar (in first slot) |
'| __ASSIGN_BUTTON FireButton, __JOYPAD1INPUT, 1 ' joystick trigger (button 1) (in second slot) |
'| |
'| Handle - button handle |
'| cid - controller id (1-keyboard, 2-mouse, 3-joypad, etc..) |
'| Button - controller button number ( 1 to _LASTBUTTON(id) ) |
'| |
'| NOTE: Once all four button slots are filled any attempt to associate a handle with more buttons is ignored. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
SHARED CL_KEYNAME() AS STRING ' need access to _BUTTON keyboard key names
DIM Assigning AS TYPE__SLOT ' check slot UDT
DIM AssignedHandle AS INTEGER ' previously assigned button handle
DIM AssignedSlot AS INTEGER ' previously assigned button handle slot
DIM Bname AS STRING ' descriptive button name
'+------------------+
'| Check for errors |
'+------------------+
__CURRENT_ROUTINE = "__BUTTON_ASSIGN"
IF CL_CONTROLLER(cid).Found = 0 THEN __ERROR "The specified controller does not exist."
IF Button < 1 OR Button > _LASTBUTTON(cid) THEN __ERROR "The button specified does not exist on controller."
__PREVIOUS_ROUTINE = __CURRENT_ROUTINE
'+-------------------------------------+
'| Check if button is already assigned |
'+-------------------------------------+
Assigning.cid = cid ' set up check slot UDT
Assigning.Button = Button
Assigning.Axis = 0
IF IUO__ALREADY_ASSIGNED(Assigning, AssignedHandle, AssignedSlot) THEN ' is this button already assigned?
'+---------------------------------------+
'| This button has already been assigned |
'+---------------------------------------+
IF Handle = AssignedHandle THEN ' is this button already assigned to this handle?
'+-----------------------------------------------+
'| This button is aleady assigned to this handle |
'+-----------------------------------------------+
EXIT SUB ' yes, leave subroutine so duplicate is not made
ELSE ' no, this is a new valid assignment
IF CL_SETTINGS.Reassign THEN ' is reassigning allowed?
'+-----------------------------------+
'| Reassigning of buttons is allowed |
'+-----------------------------------+
IF Handle = 0 OR CL_BUTTON(Handle).Slot1.cid = 0_
OR CL_BUTTON(Handle).Slot2.cid = 0_
OR CL_BUTTON(Handle).Slot3.cid = 0_
OR CL_BUTTON(Handle).Slot4.cid = 0 THEN ' yes, is there a slot available?
'+---------------------------------------------------------------+
'| This is either a new user assigned button or an existing user |
'| assigned button with a slot availabe so remove old assignment |
'+---------------------------------------------------------------+
__REMOVE_BUTTON AssignedHandle, AssignedSlot ' yes, remove previous button assignment
END IF
ELSE ' no, reassigning not allowed
'+---------------------------------------+
'| Reassigning of buttons is not allowed |
'+---------------------------------------+
EXIT SUB ' leave subroutine
END IF
END IF
END IF
'+------------------------------------------+
'| Create a descriptive name for the button |
'+------------------------------------------+
SELECT CASE cid ' which controller?
CASE __KEYBOARDCID ' keyboard
Bname = CL_KEYNAME(Button) + " Key" ' create descriptive keyboard key name
CASE __MOUSECID ' mouse
IF Button = 1 THEN ' left button?
Bname = "Left Mouse" ' yes, create name
ELSEIF Button = 2 THEN ' no, middle button?
Bname = "Center Mouse" ' yes, create name
ELSE ' no, must be right button
Bname = "Right Mouse" ' create name
END IF
CASE __JOYPAD1CID: Bname = "J1B" + _TRIM$(STR$(Button)) ' joystick/game pad 1, create name
CASE __JOYPAD2CID: Bname = "J2B" + _TRIM$(STR$(Button)) ' joystick/game pad 2, create name
CASE __JOYPAD3CID: Bname = "J3B" + _TRIM$(STR$(Button)) ' joystick/game pad 3, create name
CASE __JOYPAD4CID: Bname = "J4B" + _TRIM$(STR$(Button)) ' joystick/game pad 4, create name
CASE __JOYPAD5CID: Bname = "J5B" + _TRIM$(STR$(Button)) ' joystick/game pad 5, create name
CASE __JOYPAD6CID: Bname = "J6B" + _TRIM$(STR$(Button)) ' joystick/game pad 6, create name
END SELECT
'+-------------------------+
'| Save button information |
'+-------------------------+
Assigning.cid = cid ' set up button to save
Assigning.Button = Button
Assigning.Axis = 0
Assigning.Name = Bname
Assigning.Cname = __CONTROLLER_NAME$(cid)
IF CL_BUTTON(Handle).Slot4.cid THEN ' 4 buttons/axis already assigned?
'+----------------------------------------------------------------------------+
'| There are no more available slots to assign another button to this handle. |
'+----------------------------------------------------------------------------+
EXIT SUB ' yes, leave subroutine, no more room
ELSEIF CL_BUTTON(Handle).Slot3.cid THEN ' no, 3 buttons/axis already assigned?
CL_BUTTON(Handle).Slot4 = Assigning
ELSEIF CL_BUTTON(Handle).Slot2.cid THEN ' no, 2 buttons/axis already assigned?
CL_BUTTON(Handle).Slot3 = Assigning
ELSEIF CL_BUTTON(Handle).Slot1.cid THEN ' no, 1 button/axis already assigned?
CL_BUTTON(Handle).Slot2 = Assigning
ELSE ' no buttons/axis have been assigned yet
CL_BUTTON(Handle).Slot1 = Assigning
END IF
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __IDENTIFY_CONTROLLERS () ' __IDENTIFY_CONTROLLERS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Finds all controllers (keyboard, mouse, gamepad, joystick) connected to the computer and polls them for information. |
'| |
'| __IDENTIFY_CONTROLLERS |
'| |
'| The following SHARED variables will be set with the controller's device id: |
'| __KEYBOARDCID - usually 1 if found, 0 otherwise |
'| __MOUSECID - usually 2 if found, 0 otherwise |
'| __JOYPAD1CID - usually 3 if found (typical: 1st game pad, 1st joystick, 1st flight yoke, 1st steering wheel) |
'| __JOYPAD2CID - usually 4 if found (typical: 2nd game pad, 2nd joystick, 2nd flight yoke, 1st rudder pedals, 1st gas/brake pedals) |
'| __JOYPAD3CID - usually 5 if found (typical: 3rd game pad, 3rd joystick, 3rd flight yoke, 2nd rudder pedals, 2nd steering wheel) |
'| __JOYPAD4CID - usually 6 if found (typical: 4th game pad, 4th joystick, 4th flight yoke, 2nd/3rd rudder pedals, 2nd/3rd gas/brake pedals) |
'| |
'| NOTE: The library will store the information for up to 6 controllers. This is typically 1 keyboard, 1 mouse, and up to four game pads and/or |
'| joysticks. The "typical:" devices listed above are what I experienced when plugging these devices into my system. Your configuration |
'| may vary wildly. If no keyboard or mouse is present it's possible to have up to six joysticks/game pads detected and stored. |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
SHARED CL_SETTINGS AS TYPE__SETTINGS ' need access to library settings
DIM Devices AS INTEGER ' number of controller devices connected to computer
DIM Device AS STRING ' description and properties of controller device
DIM cid AS INTEGER ' controller id loop counter
DIM Start AS INTEGER ' beginning position of device name
DIM Finish AS INTEGER ' ending position of device name
__KEYBOARDCID = 0 ' reset input controller identifiers
__MOUSECID = 0
__JOYPAD1CID = 0
__JOYPAD2CID = 0
__JOYPAD3CID = 0
__JOYPAD4CID = 0
__JOYPAD5CID = 0
__JOYPAD6CID = 0
Devices = _DEVICES ' get number of controllers connected to system
CL_SETTINGS.FoundDevices = Devices ' record number of devices initially found
cid = 0 ' reset controller counter
DO ' begin controller identification loop
cid = cid + 1 ' increment controller counter
IF cid <= Devices THEN ' was a controller found?
Device = _DEVICE$(cid) ' yes, get controller properties
CL_CONTROLLER(cid).Found = -1 ' mark this controller as found
IF INSTR(Device, "[KEYBOARD]") THEN ' is this a keyboard?
CL_CONTROLLER(cid).Name = "KEYBOARD" ' set a default descriptive name
__KEYBOARDCID = cid ' set keyboard's input controller id
END IF
IF INSTR(Device, "[MOUSE]") THEN ' is this a mouse?
CL_CONTROLLER(cid).Name = "MOUSE" ' set a default descriptive name
__MOUSECID = cid ' set mouse' input controller id
END IF
IF INSTR(Device, "[DISCONNECTED]") THEN ' is this controller disconnected?
CL_CONTROLLER(cid).Connected = 0 ' yes, mark controller as disconnected
ELSE ' no, controller is connected
CL_CONTROLLER(cid).Connected = -1 ' mark controller as connected
END IF
IF INSTR(Device, "[CONTROLLER]") THEN ' is this a game pad or joystick?
'+---------------------------------------------------------+
'| A generic name will be given to the joystick/game pad |
'| in the event the controller may not have a [NAME] field |
'| Note: controllers 5 and/or 6 will only exist if the |
'| keyboard and/or mouse are not connected |
'+---------------------------------------------------------+
IF __JOYPAD5CID THEN ' has joypad5's id already been set?
__JOYPAD6CID = cid ' yes, set joypad6's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD6" ' set a default descriptive name
ELSEIF __JOYPAD4CID THEN ' has joypad4's id already been set?
__JOYPAD5CID = cid ' yes, set joypad5's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD5" ' set a default descriptive name
ELSEIF __JOYPAD3CID THEN ' has joypad3's id already been set?
__JOYPAD4CID = cid ' yes, set joypad4's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD4" ' set a default descriptive name
ELSEIF __JOYPAD2CID THEN ' no, has joypad2's id already been set?
__JOYPAD3CID = cid ' yes, set joypad3's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD3" ' set a default descriptive name
ELSEIF __JOYPAD1CID THEN ' no, has joypad1's id already been set?
__JOYPAD2CID = cid ' yes, set joypad2's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD2" ' set a default descriptive name
ELSE ' no joypad ids set yet
__JOYPAD1CID = cid ' set joypad1's input controller id
CL_CONTROLLER(cid).Name = "JOYPAD1" ' set a default descriptive name
END IF
END IF
IF INSTR(Device, "[BUTTON]") THEN ' does this controller have buttons?
CL_CONTROLLER(cid).Buttons = _LASTBUTTON(cid) ' yes, record number of buttons controller has
ELSE ' no
CL_CONTROLLER(cid).Buttons = 0 ' record no buttons
END IF
IF INSTR(Device, "[AXIS]") THEN ' does this controller have axis inputs?
CL_CONTROLLER(cid).Axis = _LASTAXIS(cid) ' yes, record number of axis controller has
ELSE ' no
CL_CONTROLLER(cid).Axis = 0 ' record no axis
END IF
IF INSTR(Device, "[WHEEL]") THEN ' does this controller have wheels?
CL_CONTROLLER(cid).Wheels = _LASTWHEEL(cid) ' yes, record number of wheels controller has
ELSE ' no
CL_CONTROLLER(cid).Wheels = 0 ' record no wheels
END IF
IF INSTR(Device, "[NAME]") THEN ' is there a more descriptive name for this controller?
'+-------------------------------------------------------------+
'| Replace the generic name given with the controller's [NAME] |
'+-------------------------------------------------------------+
Start = INSTR(Device, "[NAME]") + 7 ' yes, get the start position of the name
Finish = INSTR(Start, Device, "]") ' get the end position of the name
CL_CONTROLLER(cid).Name = MID$(Device, Start, Finish - Start) ' extract and only use the descriptive name of the controller
END IF
ELSE ' no controller here
CL_CONTROLLER(cid) = CL_CONTROLLER(0) ' reset all controller settings
END IF
LOOP UNTIL cid = Devices OR cid = 6 ' leave when all controllers polled
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __INITIALIZE_CONTROLLERS () ' __INITIALIZE_CONTROLLERS |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Identify number and type of controllers and set initial variable values |
'| |
'| __INITIALIZE_CONTROLLERS |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_KEYNAME() AS STRING ' need access to _BUTTON keyboard key names
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to user assigned buttons
SHARED CL_CONTROLLER() AS TYPE__CONTROLLER ' need access to controller array
REDIM CL_BUTTON(1) AS TYPE__BUTTON ' clear user assigned buttons
DIM k AS INTEGER ' key counter
__KEYBOARDCID = 0 ' these will contain the device ids (_DEVICES)
__MOUSECID = 0
__JOYPAD1CID = 0
__JOYPAD2CID = 0
__JOYPAD3CID = 0
__JOYPAD4CID = 0
__JOYPAD5CID = 0
__JOYPAD6CID = 0
FOR k = 0 TO 6 ' clear controller array
CL_CONTROLLER(k).Found = 0
CL_CONTROLLER(k).Name = ""
CL_CONTROLLER(k).Buttons = 0
CL_CONTROLLER(k).Axis = 0
CL_CONTROLLER(k).Wheels = 0
NEXT k
__IDENTIFY_CONTROLLERS ' identify controllers attached to system
__SET_AXIS_THRESHOLD .5 ' set sensitivity of axis user defined button detection
__BUTTON_REASSIGN_ALLOWED ' allow user defined button reassignments
FOR k = 1 TO 350 ' read in names of keyboard controller keys
CL_KEYNAME(k) = "" ' clear key name
IF k < 90 THEN READ CL_KEYNAME(k) ' first 89 names are in data statements
IF k = 285 THEN READ CL_KEYNAME(k) ' 285, 90 through 284 are skipped
IF k = 286 THEN READ CL_KEYNAME(k) ' 286
IF k = 310 THEN READ CL_KEYNAME(k) ' 310, 287 through 309 are skipped
IF k > 325 THEN READ CL_KEYNAME(k) ' 326 through 350 are in data statements
NEXT k
'Keyboard _BUTTON 1 - 20
DATA "","Escape","1","2","3","4","5","6","7","8","9","0","Minus","Equals","Backspace","Tab","Q","W","E","R"
'Keyboard _BUTTON 21 - 40
DATA "T","Y","U","I","O","P","Left Bracket","Right Bracket","Enter","Left CTRL","A","S","D","F","G","H","J","K","L","Semicolon"
'Keyboard _BUTTON 41 - 50
DATA "Quote","","Left Shift","Back Slash","Z","X","C","V","B","N"
'Keyboard _BUTTON 51 - 60
DATA "M","Comma","Period","Fore Slash","Right Shift","Numpad Multiply","","Space Bar","Caps Lock","F1"
'Keyboard _BUTTON 61 - 70
DATA "F2","F3","F4","F5","F6","F7","F8","F9","","Pause"
'Keyboard _BUTTON 71 - 80
DATA "Scroll Lock","Numpad 7","Numpad 8","Numpad 9","Numpad Minus","Numpad 4","Numpad 5","Numpad 6","Numpad Plus","Numpad 1"
'Keyboard _BUTTON 81 - 89
DATA "Numpad 2","Numpad 3","Numpad 0","Numpad Period","","","","F11","F12"
'Keyboard _BUTTON 285 - 286
DATA "Numpad Enter","Right CTRL"
'Keyboard _BUTTON 310
DATA "Numpad Divide"
'Keyboard _BUTTON 326 - 340
DATA "Number Lock","","Home","UP Arrow","Page UP","","LEFT Arrow","","RIGHT Arrow","","End","DOWN Arrow","Page Down","Insert","Delete"
'Keyboard _BUTTON 341 - 350
DATA "","","","","","","","Left Win","Right Win","Menu"
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
SUB __ERROR (Message AS STRING) ' __ERROR |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Set screen to text mode and display error information passed in. |
'| |
'| __ERROR "Message" |
'| |
'| NOTE: Fatal error trap - halts program execution. |
'\_______________________________________________________________________________________________________________________________________________/
_FULLSCREEN _OFF ' turn off full screen if active
SCREEN 0, 0, 0, 0 ' set screen to pure text mode
CLS ' clear screen
PLAY "l64o3ao2ao1ao3ao2ao1ao3ao2ao1a" ' get developer's attention
COLOR 12, 0
PRINT ' print error message
PRINT " Controller Library has encountered the following error condition:"
COLOR 15, 0
PRINT
PRINT " Error in routine: ";
COLOR 14, 0
PRINT __CURRENT_ROUTINE
COLOR 15, 0
PRINT " Previous routine: ";
COLOR 14, 0
PRINT __PREVIOUS_ROUTINE
COLOR 11, 0
PRINT
PRINT " "; Message
COLOR 7, 0
_KEYCLEAR ' clear all key buffers
END ' terminate with "Press any key to continue..."
END SUB
' ______________________________________________________________________________________________________________________________________________
'/ \
FUNCTION IUO__ALREADY_ASSIGNED (Button AS TYPE__SLOT, Handle AS INTEGER, Slot AS INTEGER) ' IUO__ALREADY_ASSIGNED |
' __________________________________________________________________________________________________________________________________________|____
'/ \
'| Returns -1 (TRUE) if a button is already assigned, 0 (FALSE) otherwise. |
'| |
'| IF IUO__ALREADY_ASSIGNED(Assigning, HandleFound, SlotFound) |
'| |
'| Button - the new button being assigned |
'| Handle - the button handle that already contains this assignment |
'| Slot - the slot number that already contains this assignment |
'| |
'| NOTE: IUO - Internal Use Only |
'\_______________________________________________________________________________________________________________________________________________/
SHARED CL_BUTTON() AS TYPE__BUTTON ' need access to button array
IUO__ALREADY_ASSIGNED = 0 ' assume button is not preassigned
Handle = 0 ' reset button handle
Slot = 0 ' reset slot number
DO ' begin assignment search
Handle = Handle + 1 ' increment handle counter
IF CL_BUTTON(Handle).Slot1.cid = Button.cid THEN ' do the controller ids match in slot 1?
IF CL_BUTTON(Handle).Slot1.Button = Button.Button THEN ' yes, do the buttons match?
IF CL_BUTTON(Handle).Slot1.Axis = Button.Axis THEN ' yes, do the axes match?
Slot = 1 ' yes, slot 1 already has this button assigned
END IF
END IF
END IF
IF CL_BUTTON(Handle).Slot2.cid = Button.cid THEN
IF CL_BUTTON(Handle).Slot2.Button = Button.Button THEN
IF CL_BUTTON(Handle).Slot2.Axis = Button.Axis THEN
Slot = 2 ' slot 2 already has this button assigned
END IF
END IF
END IF
IF CL_BUTTON(Handle).Slot3.cid = Button.cid THEN
IF CL_BUTTON(Handle).Slot3.Button = Button.Button THEN
IF CL_BUTTON(Handle).Slot3.Axis = Button.Axis THEN
Slot = 3 ' slot 3 already has this button assigned
END IF
END IF
END IF
IF CL_BUTTON(Handle).Slot4.cid = Button.cid THEN
IF CL_BUTTON(Handle).Slot4.Button = Button.Button THEN
IF CL_BUTTON(Handle).Slot4.Axis = Button.Axis THEN
Slot = 4 ' slot 4 already has this button assigned
END IF
END IF
END IF
LOOP UNTIL (Handle = UBOUND(CL_BUTTON)) OR Slot ' leave when all checked or a slot contains assignment
IF Slot THEN IUO__ALREADY_ASSIGNED = -1 ' report button already assigned
END FUNCTION
Code: (Select All)
'$INCLUDE:'CONTROLLER.BI'
'----------------------------------------------------------------------------------------------------
' Controller Library Example 1
' Creating user defined buttons that include keyboard keys and joystick axes
'
' Use the keyboard ARROW keys, keyboard WASD keys, or Joystick 1 to move the circle around the screen
'
' Terry Ritchie
' April 11th, 2023 - initial release
' May 17th, 2023 - updated to use Controller Library v1.10
'----------------------------------------------------------------------------------------------------
DIM UP_Button AS INTEGER ' user defined button handles with up to four associated controller buttons and/or axes
DIM DOWN_Button AS INTEGER
DIM LEFT_Button AS INTEGER
DIM RIGHT_Button AS INTEGER
DIM x AS INTEGER ' circle x location
DIM y AS INTEGER ' circle y location
__INITIALIZE_CONTROLLERS ' initialize controller library
__MAKE_BUTTON UP_Button
__MAKE_BUTTON DOWN_Button
__MAKE_BUTTON LEFT_Button
__MAKE_BUTTON RIGHT_Button
'+----------------------------------------------------------------------------------+
'| Assign keyboard ARROW keys, WASD keys, and joystick 1 to the four button handles |
'+----------------------------------------------------------------------------------+
__ASSIGN_BUTTON UP_Button, __KEYBOARDCID, CLKEY_UP ' keyboard UP ARROW key assigned to UP_Button [SLOT1]
__ASSIGN_BUTTON UP_Button, __KEYBOARDCID, CLKEY_W ' Keyboard W key also assigned to UP_Button [SLOT2]
__ASSIGN_AXIS UP_Button, __JOYPAD1CID, -2 ' joystick vertical axis UP (-) also assigned to UP_Button [SLOT3]
__ASSIGN_BUTTON DOWN_Button, __KEYBOARDCID, CLKEY_DOWN ' keyboard DOWN ARROW key assigned to DOWN_Button [SLOT1]
__ASSIGN_BUTTON DOWN_Button, __KEYBOARDCID, CLKEY_S ' keyboard S key also assigned to DOWN_Button [SLOT2]
__ASSIGN_AXIS DOWN_Button, __JOYPAD1CID, 2 ' joystick vertical axis DOWN (+) also assigned to DOWN_Button [SLOT3]
__ASSIGN_BUTTON LEFT_Button, __KEYBOARDCID, CLKEY_LEFT ' keyboard LEFT ARROW key assigned to LEFT_Button [SLOT1]
__ASSIGN_BUTTON LEFT_Button, __KEYBOARDCID, CLKEY_A ' keyboard A key also assigned to LEFT_Button [SLOT2]
__ASSIGN_AXIS LEFT_Button, __JOYPAD1CID, -1 ' joystick horizontal axis LEFT (-) also assigned to LEFT_Button [SLOT3]
__ASSIGN_BUTTON RIGHT_Button, __KEYBOARDCID, CLKEY_RIGHT ' keyboard RIGHT ARROW key assigned to RIGHT_Button [SLOT1]
__ASSIGN_BUTTON RIGHT_Button, __KEYBOARDCID, CLKEY_D ' keyboard D key also assigned to RIGHT_Button [SLOT2]
__ASSIGN_AXIS RIGHT_Button, __JOYPAD1CID, 1 ' joystick horizontal axis RIGHT (+) also asigned to RIGHT_Button [SLOT3]
SCREEN _NEWIMAGE(640, 480, 32)
x = 319
y = 239
DO
_LIMIT 30
CLS
LOCATE 2, 1
PRINT " Controller Library Demo 1"
PRINT " Use ARROW keys, WASD keys, or Joystick 1"
PRINT " ESC to exit"
IF __BUTTON_DOWN(UP_Button) THEN y = y - 5 ' press UP ARROW key, W key, or move joystick UP
IF __BUTTON_DOWN(DOWN_Button) THEN y = y + 5 ' press DOWN ARROW key, S key, or move joystick DOWN
IF __BUTTON_DOWN(LEFT_Button) THEN x = x - 5 ' press LEFT ARROW key, A key, or move joystick LEFT
IF __BUTTON_DOWN(RIGHT_Button) THEN x = x + 5 ' press RIGHT ARROW key, D key, or move joystick RIGHT
CIRCLE (x, y), 30
_DISPLAY
LOOP UNTIL _KEYDOWN(27) ' exit when ESC pressed
SYSTEM
'$INCLUDE:'CONTROLLER.BM'
Code: (Select All)
'$INCLUDE:'CONTROLLER.BI'
'----------------------------------------------------------------------------------------------------
' Controller Library Example 2
' Remapping joystick axes
'
' Use Joystick 1 to move the circle around the screen
'
' Terry Ritchie
' April 11th, 2023 - original release
' May 17th, 2023 - updated to use Controller Library v1.10
'----------------------------------------------------------------------------------------------------
__INITIALIZE_CONTROLLERS ' initialize controller library
SCREEN _NEWIMAGE(640, 480, 32)
DO
_LIMIT 30
CLS
LOCATE 2, 1
PRINT " Controller Library Demo 2"
PRINT " Use Joystick 1"
PRINT " ESC to exit"
x = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD1CID, 1), 0, 639) ' joystick 1 axis now 0 to 639
y = __MAP_AXIS(__CONTROLLER_AXIS(__JOYPAD1CID, 2), 0, 479) ' joystick 2 axis now 0 to 479
CIRCLE (x, y), 30
_DISPLAY
LOOP UNTIL _KEYDOWN(27) ' exit when ESC pressed
SYSTEM
'$INCLUDE:'CONTROLLER.BM'
Code: (Select All)
'$INCLUDE:'CONTROLLER.BI'
'----------------------------------------------------------------------------------------------------
' Controller Library Example 3
' Polling controllers for information
'
' Reports information on all controllers found.
'
' Terry Ritchie
' April 11th, 2023 - original release
' May 17th, 2023 - updated to use Controller Library v1.10
'----------------------------------------------------------------------------------------------------
__INITIALIZE_CONTROLLERS ' initialize controller library
DIM Joysticks AS INTEGER
DIM Format AS STRING
DIM j AS INTEGER
DIM jid AS INTEGER
Joysticks = __JOYPAD_EXISTS(1)
Format = " | # | \ \ | ### | ## |"
CLS
PRINT
PRINT " ___________________________________________________________________"
PRINT " / CONTROLLERS FOUND CONNECTED TO YOUR COMPUTER \"
PRINT " |----------------+---------------------------------+---------+------|"
PRINT " | CONTROLLER ID | CONTROLLER NAME | BUTTONS | AXES |"
PRINT " |----------------+---------------------------------+---------+------|"
IF __KEYBOARD_EXISTS THEN PRINT USING Format; __KEYBOARDCID; __CONTROLLER_NAME$(__KEYBOARDCID); __BUTTON_TOTAL(__KEYBOARDCID); 0
PRINT " |----------------+---------------------------------+---------+------|"
IF __MOUSE_EXISTS THEN PRINT USING Format; __MOUSECID; __CONTROLLER_NAME$(__MOUSECID); __BUTTON_TOTAL(__MOUSECID); __AXIS_TOTAL(__MOUSECID)
FOR j = 1 TO Joysticks
SELECT CASE j
CASE 1: jid = __JOYPAD1CID
CASE 2: jid = __JOYPAD2CID
CASE 3: jid = __JOYPAD3CID
CASE 4: jid = __JOYPAD4CID
CASE 5: jid = __JOYPAD5CID
CASE 6: jid = __JOYPAD6CID
END SELECT
PRINT " |----------------+---------------------------------+---------+------|"
PRINT USING Format; jid; __CONTROLLER_NAME$(jid); __BUTTON_TOTAL(jid); __AXIS_TOTAL(jid)
NEXT j
PRINT " \________________|_________________________________|_________|______/"
PRINT
PRINT " Press ESC to exit"
SLEEP
SYSTEM
'$INCLUDE:'CONTROLLER.BM'