Seite 1 von 1

Analoger "Joystick" - Aber wie?

Verfasst: 09.06.2013 13:59
von KatSeiko
Hallo,

Ich habe, nachdem meine XBox aufgegeben hat, den Controller an meinem Windows-Rechner. Das Ganze ist nun ein "Joystick" mit 5 Achsen und 10 Tasten geworden. Leider ist der eingebaute "Support" von PB mehr als mangelhaft, da er nur die ersten zwei Achsen erkennt und nur digitalen Output liefert.

Gibt es eine Möglichkeit, die Funktionsfähigkeit des Joysticks unter PB voll zu nutzen? Ich habe bereits nach "joystick analog" gesucht, aber alles, was ich gefunden habe ist mehrere Jahre alt und funktioniert entweder (als Code) mit der aktuellen Version nicht mehr oder ist (als Download) lange nicht mehr verfügbar.

Ich hoffe, dass mir jemand ein wenig aushelfen kann, dieses Problem zu lösen. Ich habe in etwa folgende Vorstellung:

JoystickGetName(#Joystick) - Rückgabe Text, Name wie in Systemsteuerung
JoystickGetNumAxis(#Joystick) - Rückgabe Integer, Zahl der vorhandenen Achsen für gewählten Joystick
JoystickGetNumButtons(#Joystick) - wie gehabt, nur für Zahl der Buttons
JoystickGetAxis(#Joystick, #Axis[0..n]) - Rückgabe float.
JoystickButton(), ExamineJoystick() und InitJoystick() entsprechen den Bedürfnissen.

Aktuell habe ich diesen Code für ein Test-Programm, mit "Bordmitteln":

Code: Alles auswählen

;Code Sample for Joystick "Xbox 360 Controller"

MainWindow = OpenWindow(#PB_Any, 0, 0, 255, 85, "Joystick Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

AxisX = ProgressBarGadget(#PB_Any, 5, 5, 245, 20, -50, 50)
AxisY = ProgressBarGadget(#PB_Any, 5, 30, 245, 20, -50, 50)

Button0 = ButtonGadget(#PB_Any, 5, 60, 20, 20, "A", #PB_Button_Toggle)
Button1 = ButtonGadget(#PB_Any, 30, 60, 20, 20, "B", #PB_Button_Toggle)
Button2 = ButtonGadget(#PB_Any, 55, 60, 20, 20, "X", #PB_Button_Toggle)
Button3 = ButtonGadget(#PB_Any, 80, 60, 20, 20, "Y", #PB_Button_Toggle)
Button4 = ButtonGadget(#PB_Any, 105, 60, 20, 20, "LB", #PB_Button_Toggle)
Button5 = ButtonGadget(#PB_Any, 130, 60, 20, 20, "RB", #PB_Button_Toggle)
Button6 = ButtonGadget(#PB_Any, 155, 60, 20, 20, "BK", #PB_Button_Toggle)
Button7 = ButtonGadget(#PB_Any, 180, 60, 20, 20, "ST", #PB_Button_Toggle)
Button8 = ButtonGadget(#PB_Any, 205, 60, 20, 20, "L", #PB_Button_Toggle)
Button9 = ButtonGadget(#PB_Any, 230, 60, 20, 20, "R", #PB_Button_Toggle)

GadgetToolTip(Button4, "Left Bank")
GadgetToolTip(Button5, "Right Bank")
GadgetToolTip(Button6, "Back")
GadgetToolTip(Button7, "Start")
GadgetToolTip(Button8, "Left Joystick Press")
GadgetToolTip(Button9, "Right Joystick Press")

InitJoystick()

For i = -50 To 50
  SetGadgetState(AxisX, i)
  SetGadgetState(AxisY, i)
  WaitWindowEvent()
Next

SetGadgetState(AxisX, 0)
SetGadgetState(AxisY, 0)
WaitWindowEvent()

Repeat
  ExamineJoystick(0)
  ;Achsen
  OldX = NewX
  OldY = NewY
  ;10 buttons
  Old0 = New0
  Old1 = New1
  Old2 = New2
  Old3 = New3
  Old4 = New4
  Old5 = New5
  Old6 = New6
  Old7 = New7
  Old8 = New8
  Old9 = New9
  ;Änderungen
  NewX = JoystickAxisX(0)
  NewY = JoystickAxisY(0)
  New0 = JoystickButton(0, 1)
  New1 = JoystickButton(0, 2)
  New2 = JoystickButton(0, 3)
  New3 = JoystickButton(0, 4)
  New4 = JoystickButton(0, 5)
  New5 = JoystickButton(0, 6)
  New6 = JoystickButton(0, 7)
  New7 = JoystickButton(0, 8)
  New8 = JoystickButton(0, 9)
  New9 = JoystickButton(0, 10)
  ;Bei Unterschieden Gadgets ändern
  If OldX <> NewX 
    SetGadgetState(AxisX, JoystickAxisX(0)*50)
  EndIf
  If OldY <> NewY
    SetGadgetState(AxisY, JoystickAxisY(0)*50)
  EndIf
  If Old0 <> New0
    SetGadgetState(Button0, New0)
  EndIf
  If Old1 <> New1
    SetGadgetState(Button1, New1)
  EndIf
  If Old2 <> New2
    SetGadgetState(Button2, New2)
  EndIf
  If Old3 <> New3
    SetGadgetState(Button3, New3)
  EndIf
  If Old4 <> New4
    SetGadgetState(Button4, New4)
  EndIf
  If Old5 <> New5
    SetGadgetState(Button5, New5)
  EndIf
  If Old6 <> New6
    SetGadgetState(Button6, New6)
  EndIf
  If Old7 <> New7
    SetGadgetState(Button7, New7)
  EndIf
  If Old8 <> New8
    SetGadgetState(Button8, New8)
  EndIf
  If Old9 <> New9
    SetGadgetState(Button9, New9)
  EndIf
Until WaitWindowEvent(100) = #PB_Event_CloseWindow
End
Ich weiß, den Code kann man kürzen. In dieser Form ist er jedoch lauffähig und selbsterklärend. Was mich jedoch stört ist die Tatsache, dass mir 3 Achsen fehlen, die ich nicht ansprechen kann und dass die Achsen die ich habe nur digital verfügbar sind. Außerdem ist eine "Rundumsichtskontrolle" verfügbar, die jedoch mit "Bordmitteln" ebenfalls nicht lesbar ist. Ich hoffe sehr auf eure Hilfe für dieses Problem.

Re: Analoger "Joystick" - Aber wie?

Verfasst: 09.06.2013 14:17
von Dave
Hi,

Versuchs mal hiermit:
http://www.purearea.net/pb/CodeArchiv/I ... ck_Test.pb


Kleines Beispiel:

Code: Alles auswählen

Structure _MinMax
  Max.l
  Min.l
EndStructure

Structure _J_Info
  X._MinMax
  Y._MinMax
  Z._MinMax
  R._MinMax
  U._MinMax
  V._MinMax
EndStructure

Structure _J_Status
  X.l
  Y.l
  Z.l
  R.l
  U.l
  V.l
  POV.l
EndStructure



Procedure Joystick_Info(Joystick, *Info._J_Info)
  Protected J.JOYCAPS
  
  ret=joyGetDevCaps_(Joystick, @J, SizeOf(JOYCAPS)) 
  If ret = 0
    With *Info
      \X\Max = J\wXmax  :  \X\Min = J\wXmin
      \Y\Max = J\wYmax  :  \Y\Min = J\wYmin
      If J\wCaps & #JOYCAPS_HASZ  :  \Z\Max = J\wZmax  :  \Z\Min = J\wZmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASR  :  \R\Max = J\wRmax  :  \R\Min = J\wRmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASU  :  \U\Max = J\wUmax  :  \U\Min = J\wUmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASV  :  \V\Max = J\wVmax  :  \V\Min = J\wVmin  :  EndIf
    EndWith  
  EndIf
EndProcedure


Procedure Joystick_Status(Joystick, *Status._J_Status)
  Protected J_Status.JOYINFOEX 
  
  J_Status\dwSize = SizeOf(JOYINFOEX) 
  J_Status\dwFlags = #JOY_RETURNALL
  ret=joyGetPosEx_(Joystick, @J_Status) 
  If ret = 0
    With *Status
      \X = J_Status\dwXpos
      \Y = J_Status\dwYpos
      \Z = J_Status\dwZpos
      \R = J_Status\dwRpos
      \U = J_Status\dwUpos
      \V = J_Status\dwVpos
      \POV = J_Status\dwPOV
    EndWith
  EndIf
EndProcedure





;________Beispiel_________
AnzahlJoysticks = InitJoystick()
If AnzahlJoysticks > 0 And OpenWindow(0, 0, 0, 300, 210, "Joystick Beispiel", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(0, 0, 0, 300, 210)
  Joystick_Info(0, @Info._J_Info)
  
  Repeat
    
    Joystick_Status(0, @Status._J_Status)
   
    If StartDrawing(CanvasOutput(0))
      Box(0, 0, 300, 210, $FFFFFF)
      
      X1.f = 150 / Info\X\Max * Status\X
      Y1.f = 150 / Info\Y\Max * Status\Y
      Circle(X1 , Y1, 5, $000000)
      X2.f = 150 / Info\Z\Max * Status\Z
      Y2.f = 150 / Info\R\Max * Status\R
      Circle(X2 +150, Y2, 5, $000000)
      
      Line(150, 0, 1, 150, $000000)
      Line(0, 150, 300, 1, $000000)
      DrawingMode(#PB_2DDrawing_Transparent)
      DrawText(5, 155, "X: "+Str(Status\X), $000000)
      DrawText(5, 170, "Y: "+Str(Status\Y), $000000)
      DrawText(155, 155, "Z: "+Str(Status\Z), $000000)
      DrawText(155, 170, "R: "+Str(Status\R), $000000)
      
      Select Status\POV
        Case #JOY_POVFORWARD
          POV$ = "Oben"
        Case #JOY_POVRIGHT
          POV$ = "Rechts"
        Case #JOY_POVBACKWARD
          POV$ = "Unten"
        Case #JOY_POVLEFT
          POV$ = "Links"
        Default
          POV$ = ""
      EndSelect
      DrawText(5, 190, "POV: "+POV$, $000000)
      
      StopDrawing()
    EndIf
   
  Until WaitWindowEvent(2) = #WM_CLOSE
EndIf
End
Lg Dave

Re: Analoger "Joystick" - Aber wie?

Verfasst: 10.06.2013 10:23
von Chimorin
Von mir, vor ein paar Jahren geschrieben. Können sinnlose Sachen drin sein, war eins meiner ersten Projekte (wenn auch klein) :)

http://www.development-lounge.de/viewto ... =16&t=6651

Re: Analoger "Joystick" - Aber wie?

Verfasst: 10.06.2013 12:02
von NicTheQuick
Was meinst du damit, dass die Achsen nur digital verfügbar sind? Wie sollen sie denn sonst verfügbar sein? Im Computer gibt es nun mal nur Einsen und Nullen. Da ist alles digital.

Re: Analoger "Joystick" - Aber wie?

Verfasst: 10.06.2013 12:13
von WPö
Moin!

Vermutlich meint er, daß bei der Aussteuerung der analogen Steuerknüppel eine NULL ausgegeben wird, bis zu einem fraglichen Punkt (50% Aussteuerung?) und dann eine EINS ausgegeben wird.

Gruß - WPö

Re: Analoger "Joystick" - Aber wie?

Verfasst: 17.06.2013 01:27
von KatSeiko
NicTheQuick hat geschrieben:Was meinst du damit, dass die Achsen nur digital verfügbar sind? Wie sollen sie denn sonst verfügbar sein? Im Computer gibt es nun mal nur Einsen und Nullen. Da ist alles digital.
Naja, wenn man nen analogen Joystick hat, sollte man auch ne 0,345 haben können, wenn man den Joystick nur ein wenig bewegt..

Das Beispiel von Dave ist gut, darauf kann ich aufbauen. Danke! Ich hab das mal für den XBox-Controller geändert - super Code!

Code: Alles auswählen

Structure _MinMax
  Max.l
  Min.l
EndStructure

Structure _J_Info
  X._MinMax
  Y._MinMax
  Z._MinMax
  R._MinMax
  U._MinMax
  V._MinMax
EndStructure

Structure _J_Status
  X.l
  Y.l
  Z.l
  R.l
  U.l
  V.l
  POV.l
EndStructure



Procedure Joystick_Info(Joystick, *Info._J_Info)
  Protected J.JOYCAPS
  
  ret=joyGetDevCaps_(Joystick, @J, SizeOf(JOYCAPS)) 
  If ret = 0
    With *Info
      \X\Max = J\wXmax  :  \X\Min = J\wXmin
      \Y\Max = J\wYmax  :  \Y\Min = J\wYmin
      If J\wCaps & #JOYCAPS_HASZ  :  \Z\Max = J\wZmax  :  \Z\Min = J\wZmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASR  :  \R\Max = J\wRmax  :  \R\Min = J\wRmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASU  :  \U\Max = J\wUmax  :  \U\Min = J\wUmin  :  EndIf
      If J\wCaps & #JOYCAPS_HASV  :  \V\Max = J\wVmax  :  \V\Min = J\wVmin  :  EndIf
    EndWith  
  EndIf
EndProcedure


Procedure Joystick_Status(Joystick, *Status._J_Status)
  Protected J_Status.JOYINFOEX 
  
  J_Status\dwSize = SizeOf(JOYINFOEX) 
  J_Status\dwFlags = #JOY_RETURNALL
  ret=joyGetPosEx_(Joystick, @J_Status) 
  If ret = 0
    With *Status
      \X = J_Status\dwXpos
      \Y = J_Status\dwYpos
      \Z = J_Status\dwZpos
      \R = J_Status\dwRpos
      \U = J_Status\dwUpos
      \V = J_Status\dwVpos
      \POV = J_Status\dwPOV
    EndWith
  EndIf
EndProcedure





;________Beispiel_________
AnzahlJoysticks = InitJoystick()
If AnzahlJoysticks > 0 And OpenWindow(0, 0, 0, 300, 210, "Joystick Beispiel", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(0, 0, 0, 300, 210)
  Joystick_Info(0, @Info._J_Info)
  
  Repeat
    
    Joystick_Status(0, @Status._J_Status)
   
    If StartDrawing(CanvasOutput(0))
      Box(0, 0, 300, 210, $FFFFFF)
      
      X1.f = 150 / Info\X\Max * Status\X
      Y1.f = 150 / Info\Y\Max * Status\Y
      Circle(X1 , Y1, 5, $000000)
      X2.f = 150 / Info\Z\Max * Status\U
      Y2.f = 150 / Info\R\Max * Status\R
      Circle(X2 +150, Y2, 5, $000000)
      
      Line(150, 0, 1, 150, $000000)
      Line(0, 150, 300, 1, $000000)
      DrawingMode(#PB_2DDrawing_Transparent)
      DrawText(5, 155, "X: "+Str(Status\X), $000000)
      DrawText(5, 170, "Y: "+Str(Status\Y), $000000)
      DrawText(155, 155, "U: "+Str(Status\U), $000000)
      DrawText(155, 170, "R: "+Str(Status\R), $000000)
      
      Select Status\POV
        Case #JOY_POVFORWARD
          POV$ = "Oben"
        Case #JOY_POVRIGHT
          POV$ = "Rechts"
        Case #JOY_POVBACKWARD
          POV$ = "Unten"
        Case #JOY_POVLEFT
          POV$ = "Links"
        Default
          POV$ = ""
      EndSelect
      DrawText(5, 190, "POV: "+POV$, $000000)
      
      StopDrawing()
    EndIf
   
  Until WaitWindowEvent(2) = #WM_CLOSE
EndIf
End