A Joystick Library. |
by Steve Baker |
This Joystick Library (JS) is a portable interface that has no inherent restrictions over the number and type of joysticks it supports - although in actuality, most implementations will simply sit on top of an underlying driver provided by the Operating System.
You should include the JS header file '/usr/include/plib/js.h' and link to the JS library '/usr/lib/libjs.a'.
Before using any JS functions, you should initialise the library by calling:
jsInit () ;JS is essentially just a wrapper to make the various underlying OS mechanisms look the same to application code.
class jsJoystick { jsJoystick ( int id = 0 ) ; ~jsJoystick () ; const char* getName () const ; int getNumAxes () const ; int getNumButtons () const ; int notWorking () const ; void setError () ; float getDeadBand ( int axis ) const ; void setDeadBand ( int axis, float db ) ; float getSaturation ( int axis ) const ; void setSaturation ( int axis, float st ) ; void setMinRange ( float *axes ) ; void setMaxRange ( float *axes ) ; void setCenter ( float *axes ) ; void getMinRange ( float *axes ) const ; void getMaxRange ( float *axes ) const ; void getCenter ( float *axes ) const ; void read ( int *buttons, float *axes ) ; void rawRead ( int *buttons, float *axes ) ; }You pass the identifier (0..n) of the joystick you wish to open into the constructor function. If you leave the number off, it'll grab the first joystick available.
If the joystick is unavailable, not working, not installed or
otherwise bad, the package will return zero for all the axes
and all the buttons will appear to be up. If you need to
check for the existance of a particular stick, you can
call notWorking()
which returns JS_TRUE if
there is some problem with that stick, JS_FALSE otherwise.
getName()
tells you the device name of the
joystick, if available through API calls in your OS. A
typical value is "CH PRODUCTS CH PRO PEDALS USB ". If no
name is available, this method will return the empty string.
getNumAxes()
tells you how many axes the stick
has. Note that it is NOT safe to assume that all sticks have
the same number of axes - or that they all have a maximum of
three or something. When you pass axis data into and out of
JS, your arrays MUST be sized large enough for that stick.
When you are testing joystick code, you need to be sure your
program does the right thing when no joystick is installed.
Since it's inconvenient to do keep uninstalling your stick
to do that, we provide setError()
which causes
that stick to react exactly as if it were not installed.
To read the joystick, just call read(&buttons,axes)
where 'buttons' is an integer and 'axes' is an array of
floating point numbers. The buttons variable will be populated
with a number that has one bit per button (0==Not Pressed, 1==Pressed)
and the elements of the axis array will be scaled from an idealized
-1.0 to +1.0 range. (In practice, your stick may not reach those
limits - or it may marginally exceed them).
For a basic two axis stick, axis zero is Left/Right with left being negative and right positive. Axis one is North/South with north being negative and right positive (this is counter-intuitive - but that's what they do).
M$-Windows letters its stick axes X,Y,Z,R,U,V. These correspond to JS axes 0,1,2,3,4,5,6.
Anyway, some joysticks have features that operate by setting two or more button bits at once. This is quite easy to catch by masking multiple bits from the 'buttons' word.
rawRead
routine bypasses all the scaling and
offsetting to return RAW data directly from the OS that you can use during
calibration.
For each axis of the joystick, you should provide a maximum number
(that you wish to correspond to 1.0 returned by read()
),
a minimum number (corresponding to -1.0) and a center point number
(corresponding to 0.0) by calling
setMaxRange()/setMinRange()/setCenter()
as appropriate.
However, even with calibration, you should expect the joystick to
drift somewhat over time due to the position of the cable, the
temperature of the potentiometers and probably, the phase of the moon.
This drift is typically not serious at the max and min limits - but
in some applications, the user will expect (for example) for his
character in a game to stop moving completely when he releases the
stick. Since we cannot guarantee to get the same exact number out
of the stick when he does this, you'll need to implement a 'dead band'
in the middle of the stick's travel. This is done with
setDeadBand(axis,amount)
where 'axis' is the number of the
axis you wish to have a dead band implemented on - and 'amount' is the
amount of dead band either side of 0.0.
There are corresponding 'get' routines for each 'set'.
The read
routine is auto-calibrated when you create
the joystick class - so if the joystick is not centered at that
moment, you will get bad data from that point onwards. This is
quite common in games - so don't feel too badly about it. Just
arrange to 'new' all your joysticks early on in the program - when
your user's hands are likely to still be on the keyboard or mouse -
and provide a hot-key to pause the game and recalibrate the stick
on demand.
Steve J. Baker. <sjbaker1@airmail.net> |