Jump to content

Help detecting controller input


Recommended Posts

Thanks for the response. I got it to detect the controller input, however I have run into another problem. Hopefully I can get it resolved on here rather than starting another thread.

As I said, I got the controller input to be detected and all goes well, however I am having difficulty getting a response when more than one input is received.

I'll use what I have so far:

#include <GUIConstants.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("TrayIconHide", 1)
$dll = DllOpen("user32.dll")

;Begin GUI
$Form1 = GUICreate("Title", 230, 191, 193, 115)
GUISetState(@SW_SHOW)
;End GUI

$joy    = _JoyInit()

While 1
    $msg = GUIGetMsg()
    $j  = _GetJoy($joy,0)
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Select
            Case $j[0] < 25000 ;If (L) Analog is Moved Left
                send("{LEFT Down}")
                    Case $j[0] > 25000 And _IsPressed("25", $dll)
                send("{LEFT up}")
            
            Case $j[7] = 1 ;If A Button is Pressed
                send("{A Down}")
                    Case $j[7] <> 1 And _IsPressed("41", $dll)
                send("{A up}")
        EndSelect
WEnd

;======================================
;   _JoyInit()
;======================================
Func _JoyInit()
    Local $joy
    Global $JOYINFOEX_struct    = "dword[13]"

    $joy    = DllStructCreate($JOYINFOEX_struct)
    if @error Then Return 0
    DllStructSetData($joy,1,DllStructGetSize($joy),1);dwSize = sizeof(struct)
    DllStructSetData($joy,1,255,2)                  ;dwFlags = GetAll
    return $joy
EndFunc

;======================================
;   _GetJoy($lpJoy,$iJoy)
;   $lpJoy  Return from _JoyInit()
;   $iJoy   Joystick # 0-15
;   Return  Array containing X-Pos, Y-Pos, Z-Pos, R-Pos, U-Pos, V-Pos,POV
;           Buttons down
;
;           *POV This is a digital game pad, not analog joystick
;           65535   = Not pressed
;           0       = U
;           4500    = UR
;           9000    = R
;           Goes around clockwise increasing 4500 for each position
;======================================
Func _GetJoy($lpJoy,$iJoy)
    Local $coor,$ret

    Dim $coor[8]
    DllCall("Winmm.dll","int","joyGetPosEx", _
            "int",$iJoy, _
            "ptr",DllStructGetPtr($lpJoy))

    if Not @error Then
        $coor[0]    = DllStructGetData($lpJoy,1,3)
        $coor[1]    = DllStructGetData($lpJoy,1,4)
        $coor[2]    = DllStructGetData($lpJoy,1,5)
        $coor[3]    = DllStructGetData($lpJoy,1,6)
        $coor[4]    = DllStructGetData($lpJoy,1,7)
        $coor[5]    = DllStructGetData($lpJoy,1,8)
        $coor[6]    = DllStructGetData($lpJoy,1,11)
        $coor[7]    = DllStructGetData($lpJoy,1,9)
    EndIf

    return $coor
EndFunc

Ideally, I would like to be able to hit both the LEFT and A keys at the same time.(Example: Being able to walk and shoot at the same time, etc.)

I will be adding many more commands responding to controller inputs, so I can't have it just performing one action at a time.

Thank you,

-Chris

EDIT: Looks like if I create a separate "Select/EndSelect" for each command it works fine. I'll keep dabbling with it. If anybody else has a more efficient/less tedious form, feel free to share.

Edited by Vicate
Link to comment
Share on other sites

Your post actually got me to playing with my 360 controller too LOL, here is what I have so far for future reference in-case I ever need it:

#include <GUIConstants.au3>

;655535

$Form1 = GUICreate("Xbox 360 Controller", 300, 400)
$X0 = GUICtrlCreateLabel('', 10, 10, 30, 20)
$S0 = GUICtrlCreateSlider(40, 05, 250, 20, 0x0010)
$X1 = GUICtrlCreateLabel('', 10, 30, 30, 20)
$S1 = GUICtrlCreateSlider(40, 25, 250, 20, 0x0010)
$X2 = GUICtrlCreateLabel('', 10, 50, 30, 20)
$S2 = GUICtrlCreateSlider(40, 45, 250, 20, 0x0010)
$X3 = GUICtrlCreateLabel('', 10, 70, 30, 20)
$S3 = GUICtrlCreateSlider(40, 65, 250, 20, 0x0010)
$X4 = GUICtrlCreateLabel('', 10, 90, 30, 20)
$S4 = GUICtrlCreateSlider(40, 85, 250, 20, 0x0010)
$X5 = GUICtrlCreateLabel('', 10, 110, 30, 20)
$X6 = GUICtrlCreateLabel('', 10, 130, 30, 20)
$X7 = GUICtrlCreateLabel('', 10, 150, 30, 20)
GUICtrlCreateLabel('Buttons Pressed:', 10, 170, 280, 20)
$XB = GUICtrlCreateLabel('', 10, 190, 280, 20)
GUISetState(@SW_SHOW)

$joy = _JoyInit()

While 1
    Sleep(10)
    $msg = GUIGetMsg()
    $j = _GetJoy($joy, 0)
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop

    ;Get Array values from _GetJoy return and display
    For $a = 0 To 7
        $control = Execute('$X' & $a)
        If GUICtrlRead($control) <> $j[$a] Then GUICtrlSetData($control, $j[$a])
    Next

    ;Get buttons pressed and display
    $Spressed = GetPressed($j[7])
    If GUICtrlRead($XB) <> $Spressed Then GUICtrlSetData($XB, $Spressed)

    ;Set sliders to correct position
    For $a = 0 To 4
        SetSliders($j[$a], $a)
    Next
WEnd

Func GetPressed($Val)
    $SButtons = ''
    If BitAND($Val, 1) Then $SButtons &= '(A)'
    If BitAND($Val, 2) Then $SButtons &= '(B)'
    If BitAND($Val, 4) Then $SButtons &= '(X)'
    If BitAND($Val, 8) Then $SButtons &= '(Y)'
    If BitAND($Val, 16) Then $SButtons &= '(LB)'
    If BitAND($Val, 32) Then $SButtons &= '(RB)'
    If BitAND($Val, 64) Then $SButtons &= '(Back)'
    If BitAND($Val, 128) Then $SButtons &= '(Start)'
    If BitAND($Val, 256) Then $SButtons &= '(LS)'
    If BitAND($Val, 512) Then $SButtons &= '(RS)'
    Return $SButtons
EndFunc   ;==>GetPressed

Func SetSliders($Val, $Slide)
    $control = Execute('$S' & $Slide)
    If $Val = 65535 Then
        GUICtrlSetData($control, 0)
    ElseIf $Val = 0 Then
        GUICtrlSetData($control, 100)
    Else
        GUICtrlSetData($control, ((65535 - $Val) / 65535) * 100)
    EndIf
EndFunc   ;==>SetSliders

;======================================
;   _JoyInit()
;======================================
Func _JoyInit()
    Local $joy
    Global $JOYINFOEX_struct = "dword[13]"
    $joy = DllStructCreate($JOYINFOEX_struct)
    If @error Then Return 0
    DllStructSetData($joy, 1, DllStructGetSize($joy), 1);dwSize = sizeof(struct)
    DllStructSetData($joy, 1, 255, 2) ;dwFlags = GetAll
    Return $joy
EndFunc   ;==>_JoyInit

;======================================
;   _GetJoy($lpJoy,$iJoy)
;   $lpJoy  Return from _JoyInit()
;   $iJoy   Joystick # 0-15
;   Return  Array containing X-Pos, Y-Pos, Z-Pos, R-Pos, U-Pos, V-Pos,POV
;           Buttons down
;
;           *POV This is a digital game pad, not analog joystick
;           65535   = Not pressed
;           0       = U
;           4500    = UR
;           9000    = R
;           Goes around clockwise increasing 4500 for each position
;======================================
Func _GetJoy($lpJoy, $iJoy)
    Local $coor, $ret
    Dim $coor[8]
    DllCall("Winmm.dll", "int", "joyGetPosEx", _
            "int", $iJoy, _
            "ptr", DllStructGetPtr($lpJoy))
    If Not @error Then
        $coor[0] = DllStructGetData($lpJoy, 1, 3)
        $coor[1] = DllStructGetData($lpJoy, 1, 4)
        $coor[2] = DllStructGetData($lpJoy, 1, 5)
        $coor[3] = DllStructGetData($lpJoy, 1, 6)
        $coor[4] = DllStructGetData($lpJoy, 1, 7)
        $coor[5] = DllStructGetData($lpJoy, 1, 8)
        $coor[6] = DllStructGetData($lpJoy, 1, 11)
        $coor[7] = DllStructGetData($lpJoy, 1, 9)
    EndIf
    Return $coor
EndFunc   ;==>_GetJoy
Link to comment
Share on other sites

Awesome :]

Glad to be of inspiration!

So my current code appears to be a resource hog and drastically reduces the FPS in my game.

Not to mention it tends to hold down the CTRL key a lot for no apparent reason.

If anybody can point me toward a more resource-friendly alternative to this code, please share it :]

Link to comment
Share on other sites

Ah, I see the problem now...

Try something like this instead. Let me know if you have any questions.

#include <GUIConstants.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
Opt("TrayIconHide", 1)
$dll = DllOpen("user32.dll")

Global $direction = '', $OLDdirection = '', $Buttons = '', $OLDButtons = ''

;Begin GUI
$Form1 = GUICreate("Title", 230, 191, 193, 115)
GUISetState(@SW_SHOW)
;End GUI

$joy = _JoyInit()

While 1
    Sleep(10)
    $msg = GUIGetMsg()
    $j = _GetJoy($joy, 0)
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    $direction = ''
    If $j[0] < 25000 Then $direction = 'L' ;If (L) Analog is Moved Left
    If $j[0] > 42000 Then $direction = 'R' ;If (L) Analog is Moved Right
    $Buttons = $j[7]
    PressKeys()
WEnd

Func PressKeys()
    If $direction <> $OLDdirection Then
        If $OLDdirection = 'L' Then Send('{left up}')
        If $OLDdirection = 'R' Then Send('{right up}')
        If $direction = 'L' Then Send('{left down}')
        If $direction = 'R' Then Send('{right down}')
        $OLDdirection = $direction
    EndIf
    If $Buttons <> $OLDButtons Then
        ;Button (A)
        If BitAND($Buttons, 1) Then
            If Not BitAND($OLDButtons, 1) Then Send('{a down}'); If it wasn't pressed and is now send down
        Else
            If BitAND($OLDButtons, 1) Then Send('{a up}'); If it was pressed and isn't now send up
        EndIf
        ;Button (B)
        If BitAND($Buttons, 2) Then
            If Not BitAND($OLDButtons, 2) Then Send('{b down}'); If it wasn't pressed and is now send down
        Else
            If BitAND($OLDButtons, 2) Then Send('{b up}'); If it was pressed and isn't now send up
        EndIf
        ;Button (X)
        If BitAND($Buttons, 4) Then
            If Not BitAND($OLDButtons, 4) Then Send('{x down}'); If it wasn't pressed and is now send down
        Else
            If BitAND($OLDButtons, 4) Then Send('{x up}'); If it was pressed and isn't now send up
        EndIf
        ;Button (Y)
        If BitAND($Buttons, 8) Then
            If Not BitAND($OLDButtons, 8) Then Send('{y down}'); If it wasn't pressed and is now send down
        Else
            If BitAND($OLDButtons, 8) Then Send('{y up}'); If it was pressed and isn't now send up
        EndIf
        $OLDButtons = $Buttons
    EndIf
EndFunc   ;==>PressKeys

;======================================
;   _JoyInit()
;======================================
Func _JoyInit()
    Local $joy
    Global $JOYINFOEX_struct = "dword[13]"

    $joy = DllStructCreate($JOYINFOEX_struct)
    If @error Then Return 0
    DllStructSetData($joy, 1, DllStructGetSize($joy), 1);dwSize = sizeof(struct)
    DllStructSetData($joy, 1, 255, 2) ;dwFlags = GetAll
    Return $joy
EndFunc   ;==>_JoyInit

;======================================
;   _GetJoy($lpJoy,$iJoy)
;   $lpJoy  Return from _JoyInit()
;   $iJoy   Joystick # 0-15
;   Return  Array containing X-Pos, Y-Pos, Z-Pos, R-Pos, U-Pos, V-Pos,POV
;           Buttons down
;
;           *POV This is a digital game pad, not analog joystick
;           65535   = Not pressed
;           0       = U
;           4500    = UR
;           9000    = R
;           Goes around clockwise increasing 4500 for each position
;======================================
Func _GetJoy($lpJoy, $iJoy)
    Local $coor, $ret

    Dim $coor[8]
    DllCall("Winmm.dll", "int", "joyGetPosEx", _
            "int", $iJoy, _
            "ptr", DllStructGetPtr($lpJoy))

    If Not @error Then
        $coor[0] = DllStructGetData($lpJoy, 1, 3)
        $coor[1] = DllStructGetData($lpJoy, 1, 4)
        $coor[2] = DllStructGetData($lpJoy, 1, 5)
        $coor[3] = DllStructGetData($lpJoy, 1, 6)
        $coor[4] = DllStructGetData($lpJoy, 1, 7)
        $coor[5] = DllStructGetData($lpJoy, 1, 8)
        $coor[6] = DllStructGetData($lpJoy, 1, 11)
        $coor[7] = DllStructGetData($lpJoy, 1, 9)
    EndIf

    Return $coor
EndFunc   ;==>_GetJoy

EDIT: I should add that this currently only does, left stick, left and right, as well as buttons A,B,X, and Y. Using this code you should be able to be holding a direction and pressing up to all 4 buttons at the same time and get the expected result. If you continue on, you can easily see how to add the remaining buttons needed to complete the controller, but like I said, if you have any questions, ask :idea:

Edited by danwilli
Link to comment
Share on other sites

Yeah, I understand it, and the resource use is MUCH less.

I appreciate it, thanks.

Now I'm working on adding a button that allows you to assign the joystick buttons to perform a certain action:

example: In my game, I have an inventory system that pops up when you hold down I

http://slightlyrelevant.com/lb/arcanum_inventory.jpg

Each slot in the inventory remains at a consistent xy coordinate.

Let's say an inventory slot(Inventory Slot 1) is at 600, 350

I would like to make it assignable to where you can select which button sends the following commands:

Send('{i down}')

Sleep(100)

MouseClick( "left", 600, 350, 2, 0)

Send ('{i up}')

So that I can assign, say, the Y button to double-click inventory slot 1, thus equipping the respective item.

EDIT: By some extreme stretch, I'll then attempt to make the inventory 'hotkey' configurations saveable/loadable(I'm assuming via formatted .txt file). I'll keep tinkering with it :idea:

Thank you again for your help.

-Chris

Edited by Vicate
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...