Issue with JOYX (pub.freejoy)

Started by Yellownakji, May 06, 2018, 01:49:05

Previous topic - Next topic

Yellownakji

I'm trying to implement controller support (directinput)

According to Wikibooks,  JOYX, when left, should be negative, when middle should be 0 and when right should be positive. However, in my tests, JOYX is returning weird values.

On Windows 10:  (values returned when pressing on x axis)
Left = -1
Middle = 0.7 (what?)
Right = 1

On Windows 9x:
Left = -1
Middle = 0.7 (again?)
Right = 0.9 (hmmm??)

---

I can't wrap my head around it, been going for a while at it.   Need advice.

If the 'middle' value wasn't past or below 0, it would be fine.

This is hindering my progress.  ???

TomToad

Go into the joystick settings on windows and recalibrate.
------------------------------------------------
8 rabbits equals 1 rabbyte.

Yellownakji

Quote from: TomToad on May 06, 2018, 02:09:48
Go into the joystick settings on windows and recalibrate.

That questionably made it worse.   I'm not sure why my joysticks are doing this.  -- I've tested 4 brands and it's always like this.   See my results below.

Henri

#3
Hi,

to me, your original center value (0.007) seems reasonable. I don't have experience with joysticks in modern languages, but I do have Logitech gamepad, so I tried it out. I  went to Devices and Printers and found my gamepad, selected preferences and it display current joystick values (gamepad has two analog controllers which equal to joysticks.) I saw that values were off, so I calibrated my device. With each step you should see movement, otherwise something is wrong. After calibrating everything seemed good. I tried the joystick example in Blitz-folder and to me, everything was as I would expect. With analog device, IMO you can't assume resting state of joystick is always going to be zero.

Joystick example:
Code (blitzmax) Select

' testjoy.bmx

Import Pub.FreeJoy

Strict

If Not JoyCount() RuntimeError "No joystick found!"

Graphics 640,480

Function drawprop(n$,p#,y)
Local w
DrawText n$,0,y
w=Abs(p)*256
If p<0
DrawRect 320-w,y,w,16
Else
DrawRect 320,y,w,16
EndIf
End Function

Local t=0

While Not KeyHit(KEY_ESCAPE)
Cls

SetColor 255,255,255
Local n=JoyCount()
DrawText "joycount="+n,0,0
DrawText "JoyName(0)="+JoyName(0),0,20
DrawText "JoyButtonCaps(0)="+Bin$(JoyButtonCaps(0)),0,40
DrawText "JoyAxisCaps(0)="+Bin$(JoyAxisCaps(0)),0,60

For Local i=0 To 31
SetColor 255,255,255
If JoyDown(i) SetColor 255,0,0
DrawOval i*16,80,14,14
Next

SetColor 255,255,0
drawprop "JoyX=",JoyX(0),100
drawprop "JoyY:",JoyY(0),120
drawprop "JoyZ:",JoyZ(0),140
drawprop "JoyR:",JoyR(0),160
drawprop "JoyU:",JoyU(0),180
drawprop "JoyV:",JoyV(0),200
drawprop "JoyHat:",JoyHat(0),220
drawprop "JoyWheel:",JoyWheel(0),240

DrawRect 0,280,t,10
t=(t+1)&511

Flip
Wend

End


Edit:   Joystick vendors own driver might give different results.

-Henri
- Got 01100011 problems, but the bit ain't 00000001

Yellownakji

I did use the same example, it's on Wikibooks.    I compiled it with 486 support so i could test on Win9X and my Windows10 machines.

Honestly, i don't mean to 'assume' anything.   I've actually never used joysticks for anything, ever, in terms of programming.   I really don't know.   --- I got buttons to work, after using the microsoft configuration tool to see what's what.

My little debug window thingy can detect 'left', 'right' and 'middle' but it's a little wonky when actually applying it to my movement code.   The actual raw values, especially the 'middle' value on boot is weird.   Wikibooks said it should be 0, not a decimal so i really don't know.

I can move the debug left and right, also center it to middle but with the weird raw numbers.   The example also works great.

I'm just a little confused as to what i'm doing wrong, maybe.     Since i can successfully detect the direction in the debug, i'll probably just store the direction as a variable and add a check for it in my movement code.   That's probably what i'll do.

Derron

If you know that "whatevervalue" is "no direction" and "whatevervalue until 1" is "right" plus "whatevervalue till -1" is "left" it is up to you to interpret the values.

If your "center" is eg. "0.5" it means that for left movement you will have a range of "1.5" and for right movement a "0.5" distance. If you want to accelerate/deaccelerate you just need to multiply/divide accordingly to scale 1.5 to 1, an 0.5 to 1.


bye
Ron

Yellownakji

#6
Is it still healthy for the number to error out though?    After calibration (W10 only), the number does have an 'e' inside of it, which i assume is an overflow of decimal positions.

Is that still ok?   I really don't know.


---

Also what i mentioned in my previous post worked.   I just made the string output, output into a variable.   Then i just checked for the state of the variable.

So, not i just have one X/Y check function and it'll work for the menus and the player.  cool;  this was an interesting learning curve for me.

I also figured out that if you check for a controller or controller presses/direction WITHOUT a controller plugged in, the FPS will crap itself.   I guess it's trying to check every frame for a controller which is heavy on the CPU.

So, i made a hybrid mode.  Required some code duplication but works very well.   So now, if joystick is toggled, a keyboard + joy mode will activate otherwise, keyboard only.

Thanks guys.  I learned something.

Holzchopf

Quote from: Yellownakji on May 07, 2018, 01:03:05the number does have an 'e' inside of it, which i assume is an overflow of decimal positions.

Is that still ok?   I really don't know.

That's scientific notation. 2e3 equals "2 shifted 3 decimal places to the left", which is 2000, 2e-3 equals "2 shifted 3 decimal places to the right", which is 0.002. When printing floating point values this notation is chosen automatically for either really big or tiny values - or, if I understand you right, as you said when the decimal point "overflows" the length of what's supposed to be enough to display the value in standard notation.

If it's ok depends of the number behind the e; you expect a value near 0, so if it's negative, this means the value is pretty small / quite near to 0 / ok.

Derron

#8
As Holzchopf said: e is for "exponent". It is some kind of short notation for "10^x" (x is exponent, 10 is base).
1.23311e-5 could be written as "1.23311 * 10^-15".


@ hybrid mode
Do not mix up stuff that way.

For easy stuff you could always have something like:

Code (BlitzMax) Select

global downPressed:int
global upPressed:int
global leftPressed:int
global rightPressed:int
global joystickNumber:int = -1

Function UpdateInput:int()
  if joystickNumber = -1
    downPressed = KeyDown(KEY_LEFT)
    upPressed = KeyDown(KEY_UP)
  else
    downPressed = JoyDown(joystickNumber)
    upPressed = JoyUp(joystickNumber)
  endif
End Function


'call this _one_time_ before level start and game start
Function DetectInput()
  'check for joystick here...
  joystickNumber = ...
End Function

(I do not know the joystick code and am not able to test this now, so function names might differ).


In a better world you would have all the input already abstracted:
Type TPlayerControl
field downPressed:int
...


Then you have
Type TPlayerControlKeyboard extends TPlayerControl
Type TPlayerControlJoystick extends TPlayerControl
and even (for multiplayer over network ;-)
Type TPlayerControlRemote extends TPlayerControl

All of them have a "method UpdateInput" doing individual handling. They Keyboard one is checking KeyStates (each instance could have different Keys for "left/right/..." so you could play together on the same keyboard). The Joystick instance would call joyDown() and the likes. And the Remote one would get filled by your network class (so it does not know about the network itself) - so when your network stuff receives "remotePlayerX: downPressed=True", it sets "playerControlRemote.downPressed" to this value and so on.


PS: if you check for "KeyDown(sameKey)" multiple times per loop you might consider using Brucey's github.com/maxmods/brl.mod as it contains a "SetAutoPoll()" function allowing to disable it at the begin of a loop and enable it at the end - else each check polls the system - leading to unneeded overhead/workload.


bye
Ron