Analoger "Joystick" - Aber wie?

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
KatSeiko
Beiträge: 367
Registriert: 19.07.2008 07:47

Analoger "Joystick" - Aber wie?

Beitrag 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.
Win7 Ultimate x64, PureBasic 5.11

There is no substitute..
BildBildBild
Benutzeravatar
Dave
Beiträge: 22
Registriert: 12.06.2011 21:39
Computerausstattung: Windows 10 x64, Intel Core i7 7700k @4.2Ghz, 16GB RAM, PureBasic 5.72

Re: Analoger "Joystick" - Aber wie?

Beitrag 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
Zuletzt geändert von Dave am 10.06.2013 21:43, insgesamt 1-mal geändert.
Benutzeravatar
Chimorin
Beiträge: 451
Registriert: 30.01.2013 16:11
Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit

Re: Analoger "Joystick" - Aber wie?

Beitrag 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
Bild

- formerly known as Bananenfreak -
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Analoger "Joystick" - Aber wie?

Beitrag 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.
Benutzeravatar
WPö
Moderator
Beiträge: 669
Registriert: 27.05.2008 12:44
Wohnort: Oberland
Kontaktdaten:

Re: Analoger "Joystick" - Aber wie?

Beitrag 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ö
Ich glaube nur der Statistik, die ich selbst gefälscht habe!
Meine Netzpräsenz: WPö.de
PB5.31 auf LMDE und Pentium T7200 2,00GHz, 4GB DDR2, ATI X1400.
Benutzeravatar
KatSeiko
Beiträge: 367
Registriert: 19.07.2008 07:47

Re: Analoger "Joystick" - Aber wie?

Beitrag 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
Win7 Ultimate x64, PureBasic 5.11

There is no substitute..
BildBildBild
Antworten