Computer Science Canada

[tutorial] joysticks/joypads (finally)

Author:  Nick [ Mon Jan 28, 2008 7:56 pm ]
Post subject:  [tutorial] joysticks/joypads (finally)

Introduction


Hello welcome to my tutorial on using joysticks/joypads. I personally have a joypad with 2 analog sticks, 12 buttons, and a D-PAD/POV which has been tested. This tutorial will require two things: Firstly, you have atleast one joystick/joypad. 2)you grab my revised module at the bottom as the Turing default is not the best. Now for some Q and A.

FAQS

q)So what do you plan to accomplish in this tutorial?

a)Well I'm planning to tackle the four main parts of the joystick module, breaking it down into parts, and ultimatly sharing this method of input with the world!

q)So what's so great about joysticks/joypads?

a)Well the mouse has upto 3 buttons and a cursor, a keyboard has keys, however a joypad (depending on the model) will have upto 32 buttons, upto 3 analog sticks, and a D-PAD/POV! that equals a ton more input and functionallity.

q)What if I don't have a joypad/joystick?

a)Not to worry just follow along and post/PM me with the questions (I'm sometimes busy so results not will be immediate).

Well now to get started!

Body


The body will contain of four main parts, Setup, Button input, Analog input, and D-PAD/POV input. The tutorial will use an example program included at the bottom and will break down the code to show what exactly is happening (grab that now and the module too).

Setup


First things first, since the module is not pervasive it needs to be imported, also make sure the module is in the same folder as the program using it.

code:
import joystick


Now that that is done varibles need to be initalized just as though mouse input or keyboard input were being used
.
code:
type joypad : % create a joypad type
    record
        button : array 1 .. 32 of boolean %create 32 instances of buttons
        pos : joystick.PosRecord /*used to find all joypad intake with
         the exception of buttons*/
        caps : joystick.CapsRecord %used to find the max on joypad analog
    end record

var joy : array 1 .. 2 of joypad %create an array of joypad


What just happened? Well now to break that down.

First an instance of the joypad type containing a set of varibles was created. The first varible is an array of 32 boolean the number can be any number 1<n<32, basically it's all the buttons being used (32buttons were used to show the maximum potential). The next varible is actually taking the type of another record.
The record can be found in the joystick module it is basically bringing all input except the button states. Next is another type found in the joystick module this time bringing back the maximum potential of the joystick/joypad. Then a joy varible to use the varibles was created an array can be used for multiple joysticks/joypads.

Well now that is done time to move on. Default values need to be assigned as a failsafe for any joysticks not detected.

code:
/*set default joypad varibles*/
for i : 1 .. upper (joy)
    for ii : 1 .. upper (joy (i).button)
        joy (i).button (ii) := false
    end for
    joy (i).pos.POV := 66535
    joystick.Capabilities (i - 1, joy (i).caps)
end for


What just happened is rather simple. First a for loop was created to to cover all elements of joy, then another for loop for all 32 buttons to set the array to false false. Then the D-PAD/POV' was set to the default value of 66535. Lastly the joystick capibilities was called to find maximum capiblities of the joystick/joypad. Next joystick needs to be galled upon each loop run in the main program to gather information to what buttons are being pressed, etc... just as if it were a mouse or keyboard.

code:
joystick.GetInfo (joystick[1/2], joy ([1/2]).button)
joystick.Read (joystick[1/2], joy ([1/2]).pos)


The GetInfo procedure will return upto 32 button values. The Read procedure will return with Analog and D-PAD/POV information.

Using Buttons


This part of the tutorial is similar to a keyboard. A keyboard has an array of keys that return true if the key is pressed (info found with Input.KeyDown). A joystick/joypad has an array of buttons that return true if the button is pressed (info found with joystick.GetInfo). Therefore:

code:
if joy.button(4) then
    put "Button 4 is being pressed"
end if


Hopefully that is understandable. And that is all for buttons.

Using Analog Sticks


This part is not to hard however the analog does not return an X/Y pixel value, so a conversion is needed. First to get the current analog position.

code:
put "analog 1 - x - ", joy (1).pos.xpos
put "analog 1 - y - ", joy (1).pos.ypos


Well these values need to be converted like so.

code:

put "analog 1 - x - ", round (joy (joystickNO + 1).pos.xpos / joy (joystickNO + 1).caps.maxX * maxx)
put "analog 1 - y - ", round (joy (joystickNO + 1).pos.ypos / joy (joystickNO + 1).caps.maxY * maxy)


This must be done everytime but it shouldn't be to hard to create a function to do this.

The axis use a name for each x and y direction: analog 1 x - xpos, analog 1 y - ypos, analog 2 x - zpos, analog 2 y - rpos, analog 3 x - upos, analog 3 y - vpos.

Using D-PAD/POV


First off, reading D-PAD/POV data.

code:
put joy ([1/2]).pos.POV


This to needs to be converted into usable code.

code:
put "D-PAD (AKA POV) - " ..
if joy (    [ 1 / 2]).pos.POV = 0 then
    put "up"
elsif joy (    [ 1 / 2]).pos.POV = 4500 then
    put "up right"
elsif joy (    [ 1 / 2 ]).pos.POV = 9000 then
    put "right"
elsif joy (    [ 1 / 2 ]).pos.POV = 13500 then
    put "down right"
elsif joy (    [ 1 / 2 ]).pos.POV = 18000 then
    put "down"
elsif joy (    [ 1 / 2  ]).pos.POV = 22500 then
    put "down left"
elsif joy (    [ 1 / 2 ]).pos.POV = 27000 then
    put "left"
elsif joy (    [ 1 / 2  ]).pos.POV = 31500 then
    put "up left"
else
    put "none"
end if


Conclusion


Well that is all there is to it.

Challenges


Here are some challenges to try out.

1)make a circle that moves with the analog stick

2)move a sprite around the screen with the D-PAD/POV

3)make a simple Simon game with the buttons

4)try to make a basic game where you talk to people, walking around with D-PAD/POV talking to the character with the buttons

Refrences


1) joystick info http://compsci.ca/v3/viewtopic.php?t=6373

2) joystick info http://compsci.ca/v3/viewtopic.php?t=169

And I am terribly sorry but there was one another post that really helped me understand joysticks myself but I forget who posted it and I can no longer find the post.

Good Bye

Author:  ericfourfour [ Mon Jan 28, 2008 8:09 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

I made a program a while back that pointed out the undocumented features of the Joystick module. I'm not sure if this tutorial gets into those features. Maybe you could write a part two from that.

Author:  Clayton [ Mon Jan 28, 2008 8:40 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

This is a valiant attempt, however, I have one, huge, stinking, major issue. Use proper grammar! I don't mean to sound like an ass here, but when you're just posting stuff, that's one thing, however, when you're writing a tutorial however, you really want the quality of the material to be higher. I suggest you edit this, then send it to me in a PM (BBCode and all) and then I'll edit it. Bits are in store for when you do this.

Author:  Nick [ Wed Feb 06, 2008 2:19 am ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

updated thanks to Clayton for encouraging me to better myself and also thanks for posting newer version

Author:  Tony [ Wed Mar 26, 2008 1:55 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

if you can use this to read from USB controllers, could this possibly be also used to read from arbitrary USB devises?

Either way this is pretty awesome +Bits

Author:  Nick [ Wed Mar 26, 2008 2:02 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

define arbitrary USB devices

Author:  Tony [ Wed Mar 26, 2008 2:24 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

Something that is not a controller. I'm thinking USB flash drive, though really, it could be any USB connected device (printer?).

If one can read and write arbitrary binary data to the USB port, one can develop device drivers to communicate with the said devices.

Author:  Nick [ Wed Mar 26, 2008 2:43 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

from what I've seen his is not possible however when I went through the joystick module I focused mainly on Joysticks

Author:  BigBear [ Mon Mar 16, 2009 10:15 pm ]
Post subject:  Re: [tutorial] joysticks/joypads (finally)

At first when I saw how much was needed to get started compared to just calling Joystick.GetInfo (0, x, y, b1, b2)

But it is sooo much better, especially the button but I don't fully get how to use the buttons.

I am using a wired xbox 360 (USB) controller, with 10 button and I noticed the right analog stick can only control up and down and the trigger are the left and right is this right?

Also when I was moving with the first analog stick the y-axis seems to be inversed. I tried comparing two different location to see if they were moving in a specif direction then changing the x and y variables of where I am drawing the circle but that didn't work very well.

Here is as far as I got. You will need the .tu file from this tutorial.

How do I get the y-axis non inverted.
And am I doing buttons properly?

Turing:

import joystick
View.Set ("offscreenonly")
type joypad : % create a joypad type
    record
        button : array 1 .. 32 of boolean %create 32 instances of buttons
        pos : joystick.PosRecord /*used to find all joypad intake with
         the exception of buttons*/

        caps : joystick.CapsRecord %used to find the max on joypad analog
    end record

var joy : array 1 .. 2 of joypad %create an array of joypad
/*set default joypad varibles*/
for i : 1 .. upper (joy)
    for ii : 1 .. upper (joy (i).button)
        joy (i).button (ii) := false
    end for
    joy (i).pos.POV := 66535
    joystick.Capabilities (i - 1, joy (i).caps)
end for
var hit := true
var x, y : int := 10
var x2, y2 : int
var fail := 0
var score : int := 0
var ans : string (1) := ""
var button : int
var xpos, ypos, maxX, maxY : int := 200
var timer := 0
loop
    loop
        joystick.GetInfo (joystick1, joy (1).button)
        joystick.Read (joystick1, joy (1).pos)
        x2 := round (joy (joystick1 + 1).pos.xpos / joy (joystick1 + 1).caps.maxX * maxx)
        y2 := round (joy (joystick1 + 1).pos.ypos / joy (joystick1 + 1).caps.maxY * maxy)
        if hit = true then
            randint (button, 1, 10)
        end if
        hit := false
        put "You have until Timer: get to 1000"
        put "You have one shot to guess the button"
        put "If you fail 10 times you will lose\n"
        put "Press button number ", button
        put "Times Failed: ", fail
        put "Your Score: ", score
        put "Timer:", timer
        drawfillbox (x, y, x + 20, y + 20, blue)
        drawfillbox (x2, y2, x2 + 30, y2 + 30, red)
        View.Update
        timer += 1
        exit when fail = 10
        for i : 1 .. 31
            if joy (1).button (i) then
                put "You chose button ", i
                View.Update
                delay (1000)
                if i = button then
                    hit := true
                    put "Correct"
                    View.Update
                    delay (1000)
                    score += 10
                elsif i not= button or timer = 600 then
                    put "FAIL"
                    fail += 1
                    hit := true
                    View.Update
                    delay (1000)
                end if
                timer := 0
            end if
        end for
        if timer = 600 then
            put "FAIL"
            fail += 1
            hit := true
            timer := 0
            delay (1000)
        end if
        View.Update
        if joy (1).pos.POV = 0 then
            y += 5
        elsif joy (1).pos.POV = 4500 then
            y += 5
            x += 5
        elsif joy (1).pos.POV = 9000 then
            x += 5
        elsif joy (1).pos.POV = 13500 then
            y -= 5
            x += 5
        elsif joy (1).pos.POV = 18000 then
            y -= 5
        elsif joy (1).pos.POV = 22500 then
            y -= 5
            x -= 5
        elsif joy (1).pos.POV = 27000 then
            x -= 5
        elsif joy (1).pos.POV = 31500 then
            y += 5
            x -= 5
        end if
        delay (20)
        cls
    end loop
    put "Play again"
    View.Update
    getch (ans)
    exit when ans = "n" or ans = "N"
end loop

Author:  Tony [ Mon Mar 16, 2009 10:51 pm ]
Post subject:  Re: [tutorial] joysticks/joypads (finally)

code:

if joy (1).pos.POV = 0 then
   y += 5

BigBear @ Mon Mar 16, 2009 10:15 pm wrote:

How do I get the y-axis non inverted.

You invert the axis again.
code:

if joy (1).pos.POV = 0 then
   y -= 5

Author:  BigBear [ Mon Mar 16, 2009 11:02 pm ]
Post subject:  Re: [tutorial] joysticks/joypads (finally)

For the D-Pad that would work, but that would make it inverted.

I want to make the left analog not inverted. Right now you push up on the analog stick and the box moves down.

I am getting the coordinates here

Turing:

x2 := round (joy (joystick1 + 1).pos.xpos / joy (joystick1 + 1).caps.maxX * maxx)
y2 := round (joy (joystick1 + 1).pos.ypos / joy (joystick1 + 1).caps.maxY * maxy)


and then using them here

Turing:

 drawfillbox (x2, y2, x2 + 30, y2 + 30, red)


I tried getting x2 then getting another variable x3 and seeing if x3 > x2 move +=

But that required a rather large delay.

Also @nick I was wondering why didn't you make the screenlocations a constant or a procedure in your module

Author:  Tony [ Mon Mar 16, 2009 11:11 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

Oh right.. so then invert that coordinate.

Would
code:

y2 := round (-1*(joy (joystick1 + 1).pos.ypos / joy (joystick1 + 1).caps.maxY * maxy) + maxy)

work?

Author:  BigBear [ Mon Mar 16, 2009 11:21 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

Yeah that's it.

What about the buttons they seem to work but it seems wierd going through that for loop.

Author:  Tony [ Mon Mar 16, 2009 11:28 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

You have an array that represents the input state, very similar to the one you would have from Input.KeyDown. If you want a particular button, just check the corresponding index directly.

(that is, you don't normally loop over every keyboard key, looking if letter 'Q' was pressed)

Author:  BigBear [ Mon Mar 16, 2009 11:44 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

So it doesn't stay in that for loop checking all 31 buttons?

Also in nicks example.t file he uses
Turing:
for i : 3 .. 3 + 31
        Text.Locate (i, getCol (joystickNO))
        put i - (3 - 1), " - ", joy (joystickNO + 1).button (i - 3 + 1)
    end for
to check for button input
What is with the 3.. 3 +31

Mod Edit: Fixed the broken syntax tags

Author:  BigBear [ Tue Mar 17, 2009 11:26 pm ]
Post subject:  Re: RE:[tutorial] joysticks/joypads (finally)

Tony @ Mon Mar 16, 2009 11:28 pm wrote:
You have an array that represents the input state, very similar to the one you would have from Input.KeyDown. If you want a particular button, just check the corresponding index directly.

(that is, you don't normally loop over every keyboard key, looking if letter 'Q' was pressed)


So could write a program using Input.KeyDown then use something like this

Turing:

Input.KeyDown (key)
for i : 1 .. 31
    if joy (1).button (i) then
        if i = 1 then
            key = ('1')
        elsif i = 2 then
            key = ('2')
        elsif i = 3 then
            key = ('3')
        elsif i = 4 then
            key = ('4')
        elsif i = 5 then
            key = ('5')
        end if
    end if
end for

Author:  Tony [ Tue Mar 17, 2009 11:35 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

No, that doesn't even make sense. If you are looking for a specific button #5
code:

if joy (1).button (5) then
   put "win"
end

Author:  BigBear [ Wed Mar 18, 2009 12:07 am ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

OK but with this
Turing:
if joy (2).button (1) then
        keys := ('1')
    elsif joy (2).button (2) then
        keys := ('2')
    elsif joy (2).button (3) then
        keys := ('3')
    elsif joy (2).button (4) then
        keys := ('4')
    elsif joy (2).button (5) then
        keys := ('5')
    end if


I am getting

Assigned value is the wrong type

Author:  Nick [ Wed Mar 18, 2009 6:59 pm ]
Post subject:  Re: RE:[tutorial] joysticks/joypads (finally)

BigBear @ Mon Mar 16, 2009 11:44 pm wrote:
What is with the 3.. 3 +31


that's for Text.Locate

BigBear wrote:
I am getting

Assigned value is the wrong type


that's because you're mixing keys with button, look at Tony's post a second time

Author:  BigBear [ Wed Mar 18, 2009 8:34 pm ]
Post subject:  RE:[tutorial] joysticks/joypads (finally)

I wanted to know if you could easily use joystick buttons to seem like keys were being pressed.

I wanted to do this so I could take this Guitar Hero Game found here

http://compsci.ca/v3/viewtopic.php?t=15739&highlight=guitar+hero

And just add the joystick information and that check for buttons to be keys.

But I guess I will have make one that I (1) understand and (2) uses joystick buttons.

Author:  The_Bean [ Wed Mar 18, 2009 9:27 pm ]
Post subject:  Re: [tutorial] joysticks/joypads (finally)

You should be able to do it the way you want to, you're just mixing up what the 'keys' variable is.

The variable keys is defined as an array char of boolean
If you break it up, you get :an array with an element for every char of the keyboard as a boolean value
So if you push a key down, then that char in the array will become true.
What you need to do is make the program think that the keyboard key is pushed down when it's actually on the controller.
to change the boolean value of an individual char use:
Turing:

keys(chr(46)):=true %for the number 1 on the keyboard


: