X-box Gamepad Routines - SMcNeill - 01-26-2025
Code: (Select All)
'The type and ReDim statements should go at the top of your code
'Or go in a BI file
Type Axis_Type
Active As _Byte
X As Integer
Y As Integer
Vert As Single
Hort As Single
Angle As Single
End Type
ReDim Shared As Axis_Type JoyStick(0)
ReDim Shared As Long Button(0)
Do
Cls
ReadJoyStick 'Use this command to read your joystick
'The code here is what we use to check the results of our joystick input
For i = 1 To UBound(JoyStick) 'this checks for each axis of our joystick
'joystick(1) should be the left paddle
'joystick(2) should be the right paddle
'joystick(3) should be the d-pad
If JoyStick(i).Active Then 'check to see if any of the joysticks are active
Print Using "STICK # ACTIVE:"; i
Print "Hort:", JoyStick(i).Hort, "Vert:", JoyStick(i).Vert 'if one is, you can get the direction it's pressed in
Print "X:", JoyStick(i).X, "Y:", JoyStick(i).Y 'simply by referencing these global variables
Print "Angle:", JoyStick(i).Angle 'and this gives you the angle of the joystick
End If
Next
For b = 1 To UBound(Button)
'button(1) is the A button
'button(2) is the B button
'button(3) is the X button
'button(4) is the Y button
'button(5) is the top-left button on the front of the game pad
'button(6) is the top-right button on the front of the game pad
'button(7) is the select button (top of game pad, beside the d-pad
'button(8) is the start button (top of game pad, right of button(7)
'button(9) is the left paddle being pushed in as a button
'button(10) is the right paddle being pushed in as a button
'button(11) is the bottom-left button on the front of the game pad (Z-Axis)
'button(12) is the bottom-right button on the front of the game pad (Z-Axis)
If Button(b) Then Print Using "Button ## down (of ##)"; b, UBound(Button) 'if the button is down, process it
Next
_Limit 30
_Display
Loop
'This sub needs to go at the end of your code, or in a BM file
Sub ReadJoyStick
Static As Long d, LA, LB 'Last Axis, Last Button
If d = 0 Then d = _Devices
If d < 3 Then Exit Sub '3 is joystick. Without one, then there's no reason to waste effort doing anything else.
If LA = 0 Then LA = _LastAxis(3): ReDim JoyStick(1 To 3) As Axis_Type
If LA = 0 Then Exit Sub 'if there's no axis on your joystick, I don't know how to read it!
If LB = 0 Then LB = _LastButton(3): ReDim Button(1 To LB + 2) As Long
If LB = 0 Then Exit Sub 'if there's no buttons on your joystick, then it's not a proper controller. Go buy one!
Dim axis(LA) As Single
Do
di = _DeviceInput
Select Case di
Case 3 'We have joystick input
For a = 1 To LA: axis(a) = Int(100 * _Axis(a)) / 100: Next 'read the input on each axis
JoyStick(1).Hort = axis(1): JoyStick(1).Vert = axis(2) 'left pad is axis 1 and 2
'axis 3 is the botton left/right buttons on the front of my joystick
JoyStick(2).Hort = axis(5): JoyStick(2).Vert = axis(4) 'right pad is axis 5 and 4
JoyStick(3).Hort = axis(6): JoyStick(3).Vert = axis(7) 'd-pad is axis 6 and 7
'right-pad seems to be mapped backwards to the other axis??!!
For i = 1 To LB
Button(i) = _Button(i)
Next
Button(LB + 1) = _FALSE: Button(LB + 2) = _FALSE
Select Case _Axis(3) 'this is an odd axis which reads off the left/right buttons on the front of the gamepad
Case Is > 0.4: Button(LB + 1) = _TRUE
Case Is < -0.4: Button(LB + 2) = _TRUE
End Select
End Select
Loop Until di = 0
For j = 1 To 3
If Abs(JoyStick(j).Vert) <= .01 Then JoyStick(j).Vert = 0 'remove some natural drift from the keypad
If Abs(JoyStick(j).Hort) <= .01 Then JoyStick(j).Hort = 0 'my joystick seldom resets back to perfect 0
' the code below here gives me a simple X/Y value for left/right, up/down of _TRUE/_FALSE
'I personally find it easier for my 2-d style games to process than having to use frational results.
'Feel free to change the threshold as necessary for your own uses. 0.4 works fine for cardinal directions and diagionals for my use.
If Abs(JoyStick(j).Vert) > 0.4 Then JoyStick(j).Y = Sgn(JoyStick(j).Vert) Else JoyStick(j).Y = 0
If Abs(JoyStick(j).Hort) > 0.4 Then JoyStick(j).X = Sgn(JoyStick(j).Hort) Else JoyStick(j).X = 0
'the angle here is just like the one we learned in school with 0/360 to the right, 90 up, 180 left, and 270 down
'Tweak this as needed so it fits the coordinate system of your own stuff as desired.
JoyStick(j).Angle = _Atan2(JoyStick(j).Hort, JoyStick(j).Vert)
JoyStick(j).Angle = (_R2D(JoyStick(j).Angle) + 270) Mod 360
'And below here is what determines if a joystick was active or not
If JoyStick(j).Vert = 0 And JoyStick(j).Hort = 0 Then JoyStick(j).Active = _FALSE Else JoyStick(j).Active = _TRUE
Next
End Sub
All the mappings here work for my gamepad, though some buttons just fail to report. Even checking the Windows controller test routine, they fail to read, so this appears to be a Windows issue and not a QB64PE issue.
As it is, 16 of my 21 buttons are now mapped and reading properly, with 5 of them just lost.
Keep in mind though, that 4 of the buttons that work are double-mapped to the same input.
My left-paddle can be pressed down to generate a button event. On the bottom of my controller is another button that generates that exact same event. The controller was made like this, just for ease of producing that event.
Same with the right-paddle and pressing it down to generate a button event. On the bottom of the controller is another button that mimics that same press. It's just the way it's designed.
My Z-Axis (the left and right bottom buttons on the front) for some reason are separated into two distinct buttons. Perhaps an ergonomics thing? Either way, both of them generate the same button response as the button beside them.
I don't know if other's controllers are configured the same, but I would hope so. Hopefully several folks will test this out and report back for us, and let us know if everything maps to the same buttons for them.
I commented the crapola out of this code, so it should be easy to read, understand, and maintain in the future. There's a few parts which people might want to tweak for their own personal preferences, so be certain to take a moment to look at those. (The angle we return is one which I'd think various programs might need to tweak for their own usage.)
Try it out. Report back. I hope it works just as well for everyone else as it does on my personal game pad.
|