Joystick reinsertion event.jaxis.which problem

Hi all,
First time SDL game developer and first time on this forum, :smiley: . I’m working on a vertical scrolling SHMUP and I’ve become stuck on a joystick handling problem, so I was wondering if anyone could help?

I’m running VS2013 Express in Window 8.1 (Home) with SDL 2.0.3 and getting a problem when reinserting a Xbox gamepad.

If I insert the pad before or during the execution of my project, as I move the joystick around, the joystick X & Y axis values are assigned to Joystick_0_X_axis_val & Joystick_0_Y_axis_val, no problems. At this point event.jaxis.which returns 0, the index of joystick 0.

However, if I disconnect then reconnect the pad whilst the executable is still running I see that SDL_JOYAXISMOTION events are being produced as I move the stick, but the event.jaxis.which value is now 1, instead of 0. If I disconnect then reconnect the pad again, event.jaxis.which returns 2, and so on, incrementing it on every joystick dis/reconnnect. Of course, as my code is monitoring event.jaxis.which for 0 (Joystick 0), the X&Y values never get assigned.

I have confirmed that the joystick does actually create windows system axis values after a reinsertion by checking the windows joystick properties dialog.

One theory I have is that when a joystick has been inserted (First time), a record is made somewhere (GUID?) which is confusing the SDL system when the joy is reinserted, hence the increment in event.jaxis.which values.

Below is the complete code for the project. Am I missing something or is this possibly a bug? Matt

As you can see, I have a lot of printf output for debugging this problem.

Code:
#include <SDL.h>
#include <stdio.h>

SDL_Joystick* Joystick_0_ptr; // Joystick pointer.
SDL_Event event;

bool Joystick_0_Is_Connected; // true / false depending on whether the joystick is connected.
int Joystick_0_X_axis_val; // Joy 0 X axis value.
int Joystick_0_Y_axis_val; // Joy 0 Y axis value.
bool Restart_Joystick_SubSystem = false; // To restrart the joystick subsystem if all joysticks have been disconnected.

bool Quit_App = false;

int main(int argc, char* args[])
{
//Initialize SDL
if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
{
printf( “Error: %s\n”, SDL_GetError() );
Quit_App = true;
}

while (!Quit_App)
{
	if (SDL_NumJoysticks() < 1)		// NUmber of joysticks less than 1? Then Restart_Joystick_SubSystem flag = true.
	{
		printf("No joysticks connected\n");
		Restart_Joystick_SubSystem = true;
		SDL_JoystickClose(Joystick_0_ptr);
		Joystick_0_ptr = NULL;
	}

	if (Restart_Joystick_SubSystem == true)	// Restart_Joystick_SubSystem flag == true? Then reinitialise Joystick SubSys.
	{
		SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
		SDL_InitSubSystem(SDL_INIT_JOYSTICK);
		Restart_Joystick_SubSystem = false;
		printf("joystick Subsystem has been reinitialised!\n");
	}

	Joystick_0_ptr = SDL_JoystickOpen(0);	
	if (Joystick_0_ptr == NULL)				
	{
		Joystick_0_Is_Connected = false;	// If we cannot open joystick 0, set the Joystick_0_Is_Connected = false.
	}
	else
	{
		Joystick_0_Is_Connected = true;		// and vice versa.
	}	

	// Check for JOYAXISMOTION events.
	while (SDL_PollEvent(&event) != 0)
	{
		if (event.type == SDL_QUIT)
		{
			Quit_App = true;
		}

		if (event.type == SDL_JOYAXISMOTION)
		{
			printf("event.type == SDL_JOYAXISMOTION.\n");

			if (event.jaxis.which == 0) // If joystick 0 triggered the axis event.
			{
				printf("event.jaxis.which == 0.\n");
				if (event.jaxis.axis == 0)	// 0 = axis X
				{
					printf("event.jaxis.axis == 0.\n");
					Joystick_0_X_axis_val = event.jaxis.value;	// Assign a value between -32768 and +32768.
				}
				if (event.jaxis.axis == 1)	// 1 = axis Y
				{
					printf("event.jaxis.axis == 0.\n");
					Joystick_0_Y_axis_val = event.jaxis.value;	// Assign a value between -32768 and +32768.
				}
			}
			else
			{
				printf("event.jaxis.which == %d.\n", event.jaxis.which);
			}

		}
	}	

	// End of while event polling loop.

	// If joystick connected flag is true, print out a notification and the the axis values.
	if (Joystick_0_Is_Connected)
	{
		printf("Joystick is connected.\n");
		printf("X val: %d\n", Joystick_0_X_axis_val);
		printf("Y val: %d\n", Joystick_0_Y_axis_val);
	}
	else
	{
		printf("Joystick not connected\n");
	}

	SDL_Delay(2000); // Slow down the console output updates.
}

//Close controller etc...
SDL_JoystickClose(Joystick_0_ptr);
Joystick_0_ptr = NULL;
SDL_Quit();
return true;

}

Okay, so I’ve found a workround to this joystick problem. Ignore the event.jaxis.which value completely, and only allow one gamepad at any time. This of course means that there can be no simultaneous two player option, (Keyboard control excluded). But as the game is being developed for cross-platform, including mobile and tablets, which are essentially one player at-a-time experiences, it’s not going to be a problem.

Still, bit of a shame.

Matt.

the ?which? field in the joystick event structs only refers to the device index in the SDL_JOYDEVICEADDED event. In all other cases it refers to the joystick?s instance ID, which changes when the joystick is disconnected and reconnected.

You can get a joystick?s instance ID with the SDL_JoystickInstanceID function.On Jun 8, 2014, at 6:18 AM, MattRobinson <matt.robinson.mail at gmail.com> wrote:

Hi all,
First time SDL game developer and first time on this forum, . I’m working on a vertical scrolling SHMUP and I’ve become stuck on a joystick handling problem, so I was wondering if anyone could help?

I’m running VS2013 Express in Window 8.1 (Home) with SDL 2.0.3 and getting a problem when reinserting a Xbox gamepad.

If I insert the pad before or during the execution of my project, as I move the joystick around, the joystick X & Y axis values are assigned to Joystick_0_X_axis_val & Joystick_0_Y_axis_val, no problems. At this point event.jaxis.which returns 0, the index of joystick 0.

However, if I disconnect then reconnect the pad whilst the executable is still running I see that SDL_JOYAXISMOTION events are being produced as I move the stick, but the event.jaxis.which value is now 1, instead of 0. If I disconnect then reconnect the pad again, event.jaxis.which returns 2, and so on, incrementing it on every joystick dis/reconnnect. Of course, as my code is monitoring event.jaxis.which for 0 (Joystick 0), the X&Y values never get assigned.