[Python] Joystick Connected?

Is there any way of checking whether or not a joystick is plugged in?

I am aware that you can check a slot like this:



from bge import logic

def main(cont):
     if logic.joysticks[0]:
         Connected
     else:
          Not Connected


But this only works initially when you start the game engine. If I were to unplug the joystick in-game, the joystick still has a reference, and if I plug in a joystick in-game, a reference isn’t created. I think it may be a problem with Blender’s source.

Is there any way to check whether or not a joystick has been plugged in or out in-game? Am I doing something wrong? Or is this a bug? Is there a way outside of the BGE to access joysticks (I’m thinking of using pygame; it works there)?

I don’t think it’s worth the trouble to use pygame when bge has it pretty well done. But for some reason this gets me…

As far as I know, there’s no way to poll the joystick to see if it’s still connected. I think even libraries like SDL can have issues with this, as well.

This sounds like an unusual situation.

It might be the BGE assumes the user will not plug/unplug hardware while the game is running. Therefore it was not necessary to add a “plug-in” feature.

If you really need it, I guess the source is the right place to check, as this is really low level.

Without SDL 2 (together with a fix in blender source that not exists at this moment) it is not possible to that in blender. There is a bug reflecting that issue in the tracker.

Well then I need a way of doing this with pygame, could anyone help me with that?

I’ve discovered that if you initiate pygame.joystick after you quit, you can check for joystick disconnections or reconnections. The idea is that you’d need to initiate and quit to check for new joystick plug-ins and disconnections every few frames (I’d do a check for every 5 seconds or something). The problem is what when you initiate and quit pygame.joystick, all Joystick objects breaks. If there was a way of checking whether or not a joystick has disconnected without initiating and quitting then it’d be fine, but, as far as I know, there isn’t.

I was thinking of checking values of a joystick (hoping it’d raise an exception) but it stays suspended until you plug it back in.

Ideas?

It is the same problem that we have using blender api. Pygame uses SDL library but the joystick detection when it is plugged/unplugged after initialization it is only possible using the new SDL2. You will have to wait until blender/pygame uses SDL2.

EDIT:
You can see it here: http://wiki.libsdl.org/MigrationGuide#Joysticks

JoysticksThis is almost completely compatible with 1.2. The only real exception is that joystick events now refer to an SDL_JoystickID. This is because SDL 2.0 can handle joysticks coming and going, as devices are plugged in and pulled out during your game’s lifetime, so the index into the device list that 1.2 uses would be meaningless as the available device list changes.

Ahh, alright thanks guys. I’ll have to wait for it.

I guess I’ll give the option for the user to plug-in a joystick, and then click a button to restart the game. Shouldn’t be too difficult.

You could make a “Poll” button on the options screen that would both restart the game and kick them back to the options screen. (The options screen just seems like the best place for that kind of a button.)

Yeah, that alternative is perfect, thanks.

I’ve heard you found a way of binding joystick and keyboard controls, may I see your code for reference? I’ve done the same thing for my project but I’m not sure if it’s the best way to do it.

Sure. You can find it with my other stuff on my Google Code page. The page for the binding module itself is here. The idea is that you can bind multiple things to names for input, rather than having to set it up manually so much each time. For example…



import BGInput, JoyProfile,  # Note that JoyProfile is another of my modules for indexes for different joysticks

def System(cont):

    obj = cont.owner

    if not 'init' in obj:
        
        obj['init'] = 1

        jprof = JoyProfile.XBOX360
        
        logic.c_input = BGInput.CInputDevice() # Create an input device; this holds the input checking for mouse, keyboard, and joysticks

        logic.c_input.Add("jump", BGInput.KEYPRESSED, events.ZKEY) # Create a binding between the Z key on the keyboard, and call it "jump"

        logic.c_input.Add("jump", BGInput.JOYBUTTONPRESSED, jprof['A']) # Create a binding between the A button on a 360 controller, and add it to the existing "jump" binding

    logic.c_input.Poll() # Now poll the bindings once per game-frame.
    
    bindings = logic.c_input.bindings

    if bindings['jump']:
         print ("You hit either the A button on the joystick, or the Z key on the keyboard)


This is the basic idea. Basically, the goal was to make an input handling system in which it doesn’t matter which input device you’re using, as it should work the same way, regardless. This way, you as the developer don’t have to worry about input handling so much, but rather, can focus on getting the game up and running.

The Poll function also can take an optional argument of a specific group that you can add bindings into (another optional argument in the Add() function). That way, you can do things like easily switch to specific keyboard handling groups / modes.

In the above example, if you either press the A button on a 360 controller, or the Z key on a keyboard, it will set the “jump” binding appropriately.

I’ll update the SVN later today.

EDIT: Updated SVN to add a bit to a couple of modules.

Hmm… I did it the same way, but it’s more engineered for my specific purpose.

I didn’t want to just bind buttons and keys, I also wanted to bind mouse, keys and axes.

I used a simple algorithm to display keyboard strokes like axes values, and same with the mouse.
I didn’t want to check both WASD and joystick axes, as well as, mouse displacement and joystick axes. So for the same purpose you’ve said. It’s pretty cool!

Maybe you’d find it helpful even though you’ve done something similar:


#Uses the Keyboard class from nilutils by Goran

def direction_input(self):
	key_vec = Vector((
		Keyboard.key_down(self.keys['rightward'])-Keyboard.key_down(self.keys['leftward']),
		Keyboard.key_down(self.keys['forward'])-Keyboard.key_down(self.keys['backward'])
		))
		
	analogue = self.joy_buttons['movement']
	
	joy_vec = Vector((
		self.joy_obj.axis_values[analogue][0] if abs(self.joy_obj.axis_values[analogue][0]) > self.joy_thresh else 0,
		-self.joy_obj.axis_values[analogue][1] if abs(self.joy_obj.axis_values[analogue][1]) > self.joy_thresh else 0
		))
		

		
	dir_vec = key_vec + joy_vec
		
	if dir_vec.magnitude > 1:
		dir_vec.normalize()
		
	x, y = dir_vec
		
	return Vector((x, y, 0))

It should be self explanatory, it’s a very simple script. (:
The mouse and joystick one is basically the same thing. As I said it’s very engineered for my game because the class this is in solely deals with the player’s input.

My mistake, my module also does joystick axes and mouse axes. I just used a keyboard key and a joystick button as an example. For BGInput, the supported events that bindings execute on are:

KEYDOWN = 0

KEYUP = 1

KEYPRESSED = 2

KEYRELEASED = 3

JOYBUTTONDOWN = 4

JOYBUTTONUP = 5

JOYBUTTONPRESSED = 6

JOYBUTTONRELEASED = 7

JOYHATDOWN = 8

JOYHATUP = 9

JOYHATPRESSED = 10

JOYHATRELEASED = 11

JOYAXIS = 12 # Return the percentage that the axis is being pressed (the axis values themselves)

JOYAXISDOWN = 13

JOYAXISUP = 14

JOYAXISPRESSED = 15

JOYAXISRELEASED = 16

MOUSEAXIS = 17 # Return the delta for the mouse’s movement on a specified axis

EDIT: Your code above is good, but it assumes that the player both has connected and wants to use a joystick. If you wanted to add an options screen where you could just tick “Joystick Enabled” or not, it would require rewriting your movement function.

My Python module’s pretty much the same, but pushes the joystick, keyboard, and mouse stuff together into a single class, and abstracts out the input handling from the input binding. So pressing left is pressing left, whether you use a joystick analog stick, or a D-Pad, or use WASD or the arrow keys on the keyboard, etc.

Also, pressing left on the joystick or pressing A on the keyboard can both trigger “left”, but can also treat an analog input as an axis value (a percentage) that gets returned. That way, the same code that handles moving for the keyboard can also handle slower movement for a partially “engaged” joystick.

EDIT 2: Here’s a quick movement function from a project that uses BGInput. It ties in friction, acceleration, maximum speed, and analog sensitivities (a lot simpler than I had it months ago, haha). Adding keyboard input should be trivial, as it’s already set up to work with a joystick movement mode, and keyboard movement would be pretty much the same, but just on or off.



def PlayerUpdate(cont, obj):
    
    sce = obj.scene
    camera = sce.active_camera
    controls = logic.input.bindings
    g_obj = obj['game_object']    
    m_vel = obj.worldLinearVelocity.xy
    
    cam_rot = camera.worldOrientation.to_euler()
    
    cam_rot.x, cam_rot.y = 0, 0
    
    if m_vel.magnitude > g_obj.friction:
        m_vel.magnitude -= g_obj.friction
    else:
        m_vel.zero()
    
    move_vec = mathutils.Vector([controls['move_right'] - controls['move_left'], controls['move_up'] - controls['move_down'], 0.0])
    
    analog_tilt = move_vec.magnitude
        
    move_vec.normalize()
    
    move_vec.rotate(cam_rot)
    
    move_vec *= g_obj.acceleration
    
    if (m_vel + move_vec.xy).magnitude <= g_obj.speed * analog_tilt:
    
        m_vel += move_vec.xy
    
    obj.worldLinearVelocity.xy = m_vel.xy


A down-side of my current system is that joystick, key, and axis presses and releases are all different bindings, along-side the existin button presses. So, you would have to add different bindings for each state of the keys that you need (i.e. “JumpReleased”, “ShootPressed”, etc.). Changing the system to add an ability to check what state a single binding is in, rather than adding new bindings for each status as it is currently shouldn’t be hard at all, though.

EDIT 3: It would appear I’ve forgotten to add mouse button detection to my module, though. Gotta add it to the to-do list. :slight_smile:

Oh yeah, I knew you had a binding for axes, I was just showing a simple alternative geared towards a specific task.

it assumes that the player both has connected and wants to use a joystick.

Well, in my script there will always be a joystick… Even if one isn’t plugged in. For some reason I thought my player_input class would be too convoluted if I were make sure the joystick was enabled for every method.

As an alternative, I made a fake/ghost joystick object… lol It’s a bad solution but the code looks cleaner over all (imo). It plugs itself in if there aren’t any joysticks already plugged in. All of it’s values are zero.