Author Topic: Simple Joystick Input with STICK and STRIG  (Read 145 times)

0 Members and 1 Guest are viewing this topic.

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 2936
    • Steve’s QB64 Archive Forum
Simple Joystick Input with STICK and STRIG
« on: November 28, 2020, 11:14:14 AM »
For whatever reason, _DEVICES tosses glitches with my old controller, so I was looking for an alternative way to get results without the errors appearing in my code.  Below is what works for me, using our simple legacy commands of STICK and STRIG, which are carried over from the older QB45 days.  Why these work and why _DEVICES tosses false results, I don't have a clue, but this method is working for me, so I thought I'd go ahead and share it for others to take a look at.

Code: QB64: [Select]
  1. d = _DEVICES '          use devices to get basic information on the joystick
  2. a = _LASTAXIS(3) \ 2 '  such as how many AXIS that it may have
  3. '                       (We half the number of reported AXIS, as devices uses a different axis
  4. '                       for left/right, up/down, and STICK uses one index, with a second parameter,
  5. '                       as you can see from the code below.)
  6. b = _LASTBUTTON(3) - 1 'And here, we subtract one, as STRIG starts counting at 0, and devices starts counting
  7. '                       at 1.
  8.  
  9.     CLS
  10.     PRINT "AXIS:", "L/R", "U/D"
  11.     FOR i = 1 TO a
  12.         PRINT "AXIS"; i; ":", STICK(0, i), STICK(1, i)
  13.     NEXT
  14.     FOR i = 0 TO b
  15.         PRINT "BUTTON"; i; ":", STRIG(i * 4 + 1)
  16.     NEXT
  17.     _DISPLAY
  18.     _LIMIT 30

No WHILE:WENDs required.  No need to clear the buffers, no need for _DEVICEINPUT.  Just a simple call to our functions to see what's going on with them.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SierraKen

  • Forum Resident
  • Posts: 1156
Re: Simple Joystick Input with STICK and STRIG
« Reply #1 on: November 28, 2020, 09:39:59 PM »
These are for USB joysticks right? I remember using STICK and STRIG back in the 90's using the old 15 pin game port.

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 2936
    • Steve’s QB64 Archive Forum
Re: Simple Joystick Input with STICK and STRIG
« Reply #2 on: November 28, 2020, 10:27:25 PM »
Works with my USB gamepad, without any issues, which confuses the heck out of me.  The glitch my controller reports is always around a 0.0078... range of variance off center.  STICK offers a range from 1 to 254, with 127 being center, giving us 127 levels of precision in any direction.  1/127 is 0.0078... The variance _DEVICES reports is *exactly* the same amount as 1 level off on STICK — yet, it’s not going off center.

(Maybe because with 127 as a start, and 1 as the bottom, there’s only 126 levels of “negative” direction, and that minute fractional difference between 1/127 and 1/126 is enough to remove the glitch from triggering??)

It’s puzzling as heck, (especially since both basically break down to the same internal functions under the hood,) but at the end of the day, one works for me and the other doesn’t.  Since it’s simple enough to implement, I thought I’d go ahead and share a sample of their usage here, for anyone who might be interested.  STICK and STRIG are probably the two commands I’ll stick with, for my own programming, from now on, since the overall use/syntax just seems simpler to me.

If you assume no joystick with have more than 3 directional controls, and no more than 12 buttons, (all via standard controller setup nowadays,) then all you need is the following:

Code: [Select]
DO
    CLS
    PRINT "AXIS:", "L/R", "U/D"
    FOR i = 1 TO 3
        PRINT "AXIS"; i; ":", STICK(0, i), STICK(1, i)
    NEXT
    FOR i = 0 TO 11
        PRINT "BUTTON"; i; ":", STRIG(i * 4 + 1)
    NEXT
    _DISPLAY
    _LIMIT 30
LOOP

Check the 3 axis.  Check the 12 buttons.  Deal with the results.
« Last Edit: November 28, 2020, 10:32:05 PM by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SierraKen

  • Forum Resident
  • Posts: 1156
Re: Simple Joystick Input with STICK and STRIG
« Reply #3 on: November 28, 2020, 10:56:36 PM »
Cool Steve, I wish I had a USB joystick. I remember back in the day it was the same problem though, there was never a 0.0 center. It was always off by a tiny fraction.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1566
Re: Simple Joystick Input with STICK and STRIG
« Reply #4 on: Yesterday at 07:37:06 AM »
Hi
I'm becoming craving of Joystick! :-)
so I test this different approach to the joystick using this new code of Steve
(PS @ Steve: nothing wrong in your code with _DEVICE  I find that the interpretation of output of Device was confounding, changing the output it is ok. No unwanted events have been detected. You can see my reply on the other thread.)

Well it is working very good with my Generic USB joystick like thishttps://images-na.ssl-images-amazon.com/images/I/61syjHsPlAL._AC_SX569_.jpg

Good job to port an alternative way to manage joystick, so there are different possibilities to build up an application with joystick support.

Thanks

PS
in math  x = y is the same  x-y = 0
so I MOD your example to manage the STICK countbutton following my mindset ( I hate starting counting from 0)

Code: QB64: [Select]
  1. d = _DEVICES '          use devices to get basic information on the joystick
  2. a = _LASTAXIS(3) \ 2 '  such as how many AXIS that it may have
  3. '                       (We half the number of reported AXIS, as devices uses a different axis
  4. '                       for left/right, up/down, and STICK uses one index, with a second parameter,
  5. '                       as you can see from the code below.)
  6. b = _LASTBUTTON(3) 'And here, we subtract one, as STRIG starts counting at 0, and devices starts counting
  7. '                       at 1.
  8.  
  9.     CLS
  10.     PRINT "AXIS:", "L/R", "U/D"
  11.     FOR i = 1 TO a
  12.         PRINT "AXIS"; i; ":", STICK(0, i), STICK(1, i)
  13.     NEXT
  14.     FOR i = 1 TO b
  15.         PRINT "BUTTON"; i; ":", STRIG((i - 1) * 4)
  16.     NEXT
  17.     _DISPLAY
  18.     _LIMIT 30
  19.  

And the results are the same, in fact say "Sky is blue" and "Blue is sky" is the same.
Programming isn't difficult, only it's  consuming time and coffee

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 2936
    • Steve’s QB64 Archive Forum
Re: Simple Joystick Input with STICK and STRIG
« Reply #5 on: Yesterday at 08:06:05 AM »
@TempodiBasic

 STRIG((i - 1) * 4) and  STRIG((i * 4 +1) aren’t the same.

STRIG has 2 things it can report to us for each button:

0 — has it changed?
1 — is it down?

My little code is testing to see if the button is down, yours is testing to see if it’s changed states.

Starting out, they seem the same, but they’re not.

Button starts UP, both report 0.
Press the button down, both report -1 (true).  (State has changed, and it’s down.)
Hold it down, and STRIG(0) reports 0, STRIG(1) reports -1.  (State hasn’t changed, but the button is down.)
Release the button, STRIG(0) reports -1, STRIG(1) reports 0.  (State changed, and the button is up.)
Leave it up and both report 0, and we’re back to start.

In my little menu program, I actually check both:

IF STRIG(0) AND STRIG(1) THEN...

This means the button had to have been up, and then was pressed down as a selection tool.  There’s no chance a stuck button would just blow past the input like that.  ;)

My sky is blue; yours is blue, tinged with a hint of a red sunrise.  Similar, but not exactly the same.

I’m reading from STRIG 1, 5, 9, 13, 17...
You’re reading from STRIG 0, 4, 8, 12, 16...

(And if you’re curious, the buttons between are for a second controller.)
2/3 are state change/up and down for button 1 of controller 2.
6/7 are for button 2 of controller 2...

This all goes back to the legacy days of QB45 where we only had 1-axis and 1-button on each controller to support.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1566
Re: Simple Joystick Input with STICK and STRIG
« Reply #6 on: Yesterday at 10:34:10 AM »
Hi Steve
I must agree  with my change to your code I have missed the +1) so I'm testing if it changes and not its state.
Now reading the WIKI I can get more details about these informations that you passed to me!
https://www.qb64.org/wiki/index.php/STRIG

So I must remark
now sky is blue  == blue is sky :-)
Code: QB64: [Select]
  1. d = _DEVICES '          use devices to get basic information on the joystick
  2. a = _LASTAXIS(3) \ 2 '  such as how many AXIS that it may have
  3. '                       (We half the number of reported AXIS, as devices uses a different axis
  4. '                       for left/right, up/down, and STICK uses one index, with a second parameter,
  5. '                       as you can see from the code below.)
  6. b = _LASTBUTTON(3) 'And here, we subtract one, as STRIG starts counting at 0, and devices starts counting
  7. '                       at 1.
  8.  
  9.     CLS
  10.     PRINT "AXIS:", "L/R", "U/D"
  11.     FOR i = 1 TO a
  12.         PRINT "AXIS"; i; ":", STICK(0, i), STICK(1, i)
  13.     NEXT
  14.     FOR i = 1 TO b
  15.         PRINT "BUTTON"; i; ":", STRIG((i - 1) * 4 + 1)
  16.         ' if we call STRIG with even  parameter we read if button state changes    IS IT CHANGED?
  17.         ' if we call STRIG with odd   parameter we read how is the state of button  IS IT DOWN?
  18.     NEXT
  19.     _DISPLAY
  20.     _LIMIT 30
  21.  
  22.  
saving my need of OPTION BASE 1 for button counting :)
Programming isn't difficult, only it's  consuming time and coffee

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 2936
    • Steve’s QB64 Archive Forum
Re: Simple Joystick Input with STICK and STRIG
« Reply #7 on: Yesterday at 12:01:03 PM »
One last thing which is worth pointing out -- you don't have to use _DEVICES to get the actual number of axis and buttons which a device has.  Just make certain to run a loop large enough to check the state for a sufficient number for your needs.  QB64 won't toss an error message if you try and check for a value which a device doesn't support with STICK or STRIG.

Code: QB64: [Select]
  1.     CLS
  2.     PRINT "AXIS:", "L/R", "U/D"
  3.     FOR i = 1 TO 5
  4.         PRINT "AXIS"; i; ":", STICK(0, i), STICK(1, i)
  5.     NEXT
  6.     FOR i = 1 TO 30
  7.         PRINT "BUTTON"; i; ":"; STRIG((i - 1) * 4 + 1),
  8.         ' if we call STRIG with even  parameter we read if button state changes    IS IT CHANGED?
  9.         ' if we call STRIG with odd   parameter we read how is the state of button  IS IT DOWN?
  10.     NEXT
  11.     _DISPLAY
  12.     _LIMIT 30

The above works just fine.  The advantage of checking as I did above to get an exact number of axis and buttons is just a minute amount of speed saved where we don't have to check for items that don't exist on controller.  If we know our controller only has 1 axis, and 1 button (like for the Atarii 2600 joysticks) we really don't need to check any more than that, so we save ourselves a little processing time checking for states of non-existent items. 

If your needs are simple enough that loop speeds aren't a concern, then feel free to just ignore the _DEVICES, _LASTBUTTON, and _LASTAXIS checks.  Keep your code as simple as possible and just check sufficient levels for your program's needs.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!