|
DirectInput
- Joystick |
|
Die Verwaltung eines Joysticks über DirectInput
ist im Grunde recht einfach. Da ein Joystick kein Systemeingabegerät ist, kann
nicht davon ausgegangen werden, dass an jedem
Computer ein Joystick angeschlossen ist. Daher ist eine Auflistung
der vorhandenen Eingabegeräte notwendig.
Es ist ja nicht sinnvoll dem Anwender die Möglichkeit
anzubieten ein Spiel mit einem Joystick zu spielen,
wenn gar kein Joystick am Computer angeschlossen ist.
Des weiteren sollten auch die Eigenschaften eines
ggf. vorhandenen Joysticks abgefragt werden.
|
Es ist zwar toll wenn
ein Spiel 10 Joystick-Tasten unterstützt, aber
nicht sinnvoll für einen Spieler der einen Joystick
mit nur 5 Tasten besitzt. In diesem Teil unseres
DirectInput-Tutorials wird
immer die Bezeichnung Joystick verwendet. Diese Bezeichnung
steht für alle Arten von Joysticks, Flightsticks,
GamePads und Steuerräder ausgenommen der Force-Feedback-Geräte.
|
Es
gibt zwei Möglichkeiten um Eingabedaten eines Joysticks
abzufragen:
|
Doch
zunächst muss festgestellt werden, ob und wie
viele Joysticks am Computer angeschlossen
sind. Hierfür benötigt man ein DirectInputEnumDevices-Objekt
und die Funktion GetDIEnumDevices vom DirectInput-Objekt
(siehe Grundlagen),
wobei nicht alle Eingabegeräte, sondern nur die angeschlossenen Joysticks
abgefragt
werden.
|
Dies
erfolgt mit dem Typ-Filter DIDEVTYPE_JOYSTICK und
dem Flag DIEDFL_ATTACHEDONLY. So erhalten wir eine
Liste der z.Zt. am Computer angeschlossenen Joysticks.
Ist die Liste leer (GetCount = 0), dann ist kein Joystick
vorhanden.
|
|
|
Dim diJoystick As DirectInputDevice
Dim enumDevice As DirectInputEnumDevices
'Auflistung aller angeschlossenen Joysticks einlesen
Set enumDevice = DI.GetDIEnumDevices(DIDEVTYPE_JOYSTICK, _
DIEDFL_ATTACHEDONLY)
If enumDevice.GetCount = 0 Then
MsgBox "Es sind keine Joysticks am PC angeschlossen.", _
vbInformation
End If |
|
|
Gehen
wir davon aus es ist ein Joystick angeschlossen.
Nun möchten wir aber auch wissen welche Eigenschaften
dieser Joystick besitzt, wie z.B. wie viel Achsen,
Tasten,
Schieberegler usw. Nicht jeder Joystick hat z.B. die
gleiche Anzahl an Tasten. Um die Eigenschaften
zu erhalten, muss ein DirectInputDevice-Objekt erstellt,
und über ein DirectInputEnumDeviceObjects-Objekt
können
diese dann abgefragt werden.
|
Im folgenden Beispiel
wird nur die Anzahl der Tasten ermittelt. Zu beachten
ist, das es für Joysticks keine SystemGUID gibt.
Wir müssen daher die GUID des Joysticks aus der
Auflistung nehmen.
|
|
|
Dim Caps As DIDEVCAPS
Dim diEnumObjects As DirectInputEnumDeviceObjects
'erstelle Input-Objekt mit GUID aus der Liste
Set diJoystick = _
DI.CreateDevice(enumDevice.GetItem(1).GetGuidInstance)
'setze DirectInput DatenFormat auf Joystick
diJoystick.SetCommonDataFormat DIFORMAT_JOYSTICK
'setze Cooperative Level
diJoystick.SetCooperativeLevel Me.hWnd, _
DISCL_BACKGROUND Or DISCL_EXCLUSIVE
'hole Fähigkeiten des Joysticks
diJoystick.GetCapabilities Caps
'irgendwelche Fähigkeiten hat der Joystick hoffentlich
If Caps.lFlags Then
'hole Tasten-Auflistung vom Joystick
Set diEnumObjects = diJoystick.GetDeviceObjectsEnum(DIDFT_BUTTON)
'wieviele Tasten hat der Joystick
JSButton = diEnumObjects.GetCount
End If |
|
|
Das richtige
Setzen des Cooperative Level ist wichtig, da sonst
Windows bzw. andere Anwendungen nicht wissen wie sie
das Eingabegerät mit ihrem Programm teilen sollen.
Wie dies genau geht, ist in unserem Abschnitt CooperativeLevel und Datenformat
genau beschrieben.
|
Die
Funktion GetDeviceObjectsEnum bietet eine
Fülle an Informationen über den Joystick, und folgende
Eigenschaften können abgefragt werden:
|
|
DIDFT_ABSAXIS
|
Absolute Achsen
|
|
DIDFT_ALIAS
|
Ist zu
benutzen wie eine Steuerung, die durch ein HID (Human
Interface Device = ein Gerät das es dem Mensch ermöglicht,
mit dem Computer zu kommunizieren) identifiziert
wurde. Diese Eigenschaft gilt nur für HID kompatiblen
USB-Geräte.
|
|
DIDFT_ALL
|
Alle Eigenschaften
|
|
DIDFT_ANYINSTANCE
|
Für die erste
Instanz, auf die andere Kriterien wie auf DIDFT_AXIS
oder DIDFT_BUTTON zutreffen.
|
|
DIDFT_AXIS
|
Anzahl
der absoluten als auch relativen Achsen
|
|
DIDFT_BUTTON
|
Anzahl
aller Tasten
|
|
DIDFT_COLLECTION
|
HID-Ausstattung.
Die HID-Ausstattung generiert keine eigenen Daten.
|
|
DIDFT_FFACTUATOR
|
Objekt,
das einen Force-Feedback Auslöser enthält. Forces
(Kräfte) können auf dieses Objekt angewendet werden.
|
|
DIDFT_FFEFFECTTRIGGER
|
Objekt,
mit dem Force-Feedback Effekte ausgelöst werden können.
|
|
DIDFT_INSTANCEMASK
|
das
gleiche wie DIDFT_ANYINSTANCE
|
|
DIDFT_NOCOLLECTION
|
Objekt,
das zu keiner HID-Ausstattung gehört, das heißt, ein
Objekt zu dem DirectInputDeviceObjectInstance.GetCollectionNumber
eine 0 zurückliefert.
|
|
DIDFT_NODATA
|
Objekt,
das keine Daten generiert.
|
|
DIDFT_OUTPUT
|
Objekt,
das Daten mit der DirectInputDevice8.SendDeviceData
Methode senden kann.
|
|
DIDFT_POV
|
Point-of-view
Controller
|
|
DIDFT_PSHBUTTON
|
PushButton - Eine
Taste die bei Drücken ihren Zustand ändert und
solange beibehält, bis sie losgelassen wird.
|
|
DIDFT_RELAXIS
|
Relative Achsen
|
|
DIDFT_TGLBUTTON
|
ToggleButton - Eine
Taste die bei einmaligem Drücken ihren Zustand (gedrückt
oder nicht-gedrückt) ändert und solange beibehält,
bis sie nochmals gedrückt wird.
|
|
DIDFT_VENDORDEFINED
|
Ein vom Hersteller definierter
Objekttyp.
|
|
|
'z.B.
Einlesen aller Eigenschaften
Set diEnumObjects = diJoystick.GetDeviceObjectsEnum(DIDFT_ALL) |
|
|
Jetzt muss das Eingabegerät für die Anwendung
reserviert werden. Hiefür wird die Funktion Acquire
vom DirectInputDevice-Objekt verwendet. Anders als bei
der Maus und der Tastatur braucht man auch noch die
Funktion Poll. Die Poll Funktion stellt die Eingabeinformationen
des Joysticks zur Verfügung.
|
|
|
diJoystick.Acquire
diJoystick.Poll
|
|
|
Nun steht
die
Verbindung und die Eingabeinformationen können
verarbeitet werden. Zu beachten ist noch, dass bei den
Achsen die Mittelstellung nicht den Wert 0 sondern
den Wert 32768 liefert. Bei einem GamePad kann daher
ruhig der Wert 32768 abgezogen werden um bei der Mittelstellung
der Achse Null zu erhalten, da die Achsen eines GamePads
sowieso einen statischen Wert liefern, egal ob
Links/Rechts oder Rauf/Runter.
|
Ein normaler Joystick hingegen liefert einen Wert
zwischen 0 und dem maximalen äußeren Wert.
Bei solchen Joysticks kommt noch hinzu das sich die
Werte der Achsen bei Mittelstellung ein klein wenig
verändern. Dieses "Zittern" kann über
setzen von Joystickeigenschaften ausgeschaltet werden
und wird weiter unten erklärt. Die Joystickdaten
erhält man über den Typ DIJOYSTATE und der
Funktion GetDeviceStateJoystick vom DirectInputDevice-Objekt.
|
|
|
Dim JoystickState As DIJOYSTATE
diJoystick.GetDeviceStateJoystick JoystickState |
|
|
Soll
die Steuerung bei einem Spiel hauptsächlich durch
einen Joystick erfolgen, dann ist es sinnvoll, die Eingabeinformationen
in der Hauptschleife des Spieles zu verarbeiten.
|
|
|
Dim JoystickState As DIJOYSTATE
'stelle Verbindung her
diJoystick.Acquire
'mache Daten verfügbar
diJoystick.Poll
'hole aktuelle Daten
'entweder mit der GetDeviceStateJoystick-Funktion
diJoystick.GetDeviceStateJoystick JoystickState
'oder mit der GetDeviceState-Funktion
'diJoystick.GetDeviceState Len(JoystickState), JoystickState
'gib AchsenWerte in einer TextBox aus
txt_XY.Text = "X: " & (JoystickState.x - JOYSTICKCENTERED) & _
vbCrLf & "Y: " & (JoystickState.y - JOYSTICKCENTERED) &
_
vbCrLf & "Z: " & (JoystickState.z - JOYSTICKCENTERED)
'gibt Tasten-Status in einer TextBox aus
For i = 1 To JSButton
strhilf = "Nein"
If JoystickState.buttons(i - 1) > 0 Then _
strhilf = "Ja"
txt_Buttons.Text = txt_Buttons.Text & _
"Button " & i & " : " & strhilf & vbCrLf
Next
|
|
|
Eine
Möglichkeit, die die Ressourcen am Wenigsten
beansprucht ist, auf
ein DirectXEvent zu warten, um dann erst die Joystickdaten
zu verarbeiten. Dazu muss ein DirectXEvent
erstellt werden und die Prozedur
DirectXEvent_DXCallback im Hauptfenster der Anwendung vorhanden
sein.
|
Zu beachten ist hier,
dass bei Verwendung
von mehreren DXEvents (z.B. wenn Wave-Dateien gestreamt
werden) die Event-ID abgefragt wird, da ansonsten
die Joystickdaten verarbeitet werden obwohl gar kein
Ereignis
von DirectInput vorliegt.
Setzen
der Joystickeigenschaften
|
Anders
als bei einem GamePad liefern alle Joysticks nicht
immer die gleichen Wertebereiche bei einer Achsenabfrage.
Daher ist es sinnvoll diesen Wertebereich in der
Anwendung zu setzen. Die definierten Grenzen werden
dann von allen Joysticks beachtet und die Anwendung
erhält von allen Joysticks einheitliche Daten.
Im folgenden Beispiel wird ein Wertebereich von 0
bis 10.000 mit einen toten Bereich (DeadZone) auf allen
Achsen gesetzt.
|
DirectInput liefert nur dann Werte wenn sich
der Joystick außerhalb des toten Bereiches bewegt.
Das bedeutet, dass kleinste Bewegungen (zittern) des
Joysticks nicht registriert werden. Aber auch dann,
wenn ein Wertebereich gesetzt wird, liefert die Mittelstellung
der Achse nicht den Wert Null, sondern die Hälfte
des Wertebereichs.
|
|
|
'setzen der Eigenschaften für alle Joysticks
'setzen eines neuen Wertebereiches
Dim DiProp_Range As DIPROPRANGE
With DiProp_Range
.lHow = DIPH_DEVICE
.lSize = Len(DiProp_Range)
.lMin = 0
.lMax = 10000
End With
diJoystick.SetProperty "DIPROP_RANGE", DiProp_Range
'setzen einer toten Zone
Dim DiProp_Dead As DIPROPLONG
With DiProp_Dead
.lData = 1000
.lSize = Len(DiProp_Dead)
.lHow = DIPH_BYOFFSET
.lObj = DIJOFS_X
diJoystick.SetProperty "DIPROP_DEADZONE", DiProp_Dead
.lObj = DIJOFS_Y
diJoystick.SetProperty "DIPROP_DEADZONE", DiProp_Dead
End With
|
|
|
Wird
das Programm beendet, sollten die Objekte und
das Eingabegerät mit
der Funktion Unacquire vom DirectInputDevice-Objekt
wieder freigegeben werden. Das
DirectInput-Objekt wird danach einfach auf Nothing gesetzt.
|
|
|
diJoystick.Unacquire
Set diJoystick = Nothing
|
|
|
Ein
Beispiel für die Verwaltung von Joystickdaten
können Sie hier downloaden.
|
|
|
Download
tip0196.zip
(10,6 kB) |
|
Downloads
bisher: [ 3942
] |
|