Page 1 of 1

Gamepad (Web, HTML5)

Posted: Fri Nov 07, 2014 12:50 am
by Rescator
This is a companion to Gamepad (Windows 2000/XP/Vista/7/8/10) thread,
only this is for W3C Gamepad standard compatible browsers.

I'm also partly posting this here since I'm not regged on the SpiderBasic forums, and I'm very lazy. (Fred & Freak feel free to steal code from here for use in SpiderBasic, no credit required in that case.)

Currently this works in latest versions of Chrome, Firefox and Opera, not current IE (IE 12 and later most likely will though).
Do note that the browsers do their own internal mapping and if a common gamepad is not supported then that should reported to the browser developer, any Xinput gamepad or gamepad with a Xinput mode should work fine. DirectInput gamepads are re-mapped automatically.

The following code is fully standalone, just create a .html file and paste this code inside then open the html in Firefox, Chrome or Opera.
Combined with the PureBasic code in the other thread the testing of Gamepads and other compatible input devices should be very easy.

Code: Select all

<!doctype html>
<html>
<!-- (c) 2014 Roger Hågensen -->
<!-- zlib License, http://en.wikipedia.org/wiki/Zlib_License -->
<meta charset="utf-8">
<title>Gamepad Test</title>
</body>
<script>
var gamepad = new Object();
function gamepad_init()
{
	gamepad.name = '';
	gamepad.face1 = 0.0;
	gamepad.face2 = 0.0;
	gamepad.face3 = 0.0;
	gamepad.face4 = 0.0;
	gamepad.shoulderl = 0.0;
	gamepad.shoulderr = 0.0;
	gamepad.triggerl = 0.0;
	gamepad.triggerr = 0.0;
	gamepad.back = 0.0;
	gamepad.forward = 0.0;
	gamepad.stickl = 0.0;
	gamepad.stickr = 0.0;
	gamepad.dpadu = 0.0;
	gamepad.dpadr = 0.0;
	gamepad.dpadl = 0.0;
	gamepad.dpadd = 0.0;
	gamepad.sticklx = 0.0;
	gamepad.stickly = 0.0;
	gamepad.stickrx = 0.0;
	gamepad.stickry = 0.0;
	gamepad.enabled = true;
	if (typeof navigator.getGamepads === 'undefined')
	{
		gamepad.enabled = false;
	}
}

//returns true if a gamepad with that index exists and it's current state.
//the index number may change if a gamepad is re-ordered by the OS or the browser.
function gamepad_get(index)
{
	if (gamepad.enabled === false)
	{
		return false;
	}
	if ((index < 0) || (index > 15))
	{
		return false;
	}
	var tmpad = navigator.getGamepads();
	if (tmpad.length === 0)
	{
		return false;
	}
	if (typeof tmpad[index] === 'undefined')
	{
		return false;
	}
	if (tmpad[index] === null)
	{
		return false;
	}

	gamepad.name = tmpad[index].mapping;
	gamepad.face1 = tmpad[index].buttons[0].value;
	gamepad.face2 = tmpad[index].buttons[1].value;
	gamepad.face3 = tmpad[index].buttons[2].value;
	gamepad.face4 = tmpad[index].buttons[3].value;
	gamepad.shoulderl = tmpad[index].buttons[4].value;
	gamepad.shoulderr = tmpad[index].buttons[5].value;
	gamepad.triggerl = tmpad[index].buttons[6].value;
	gamepad.triggerr = tmpad[index].buttons[7].value;
	gamepad.back = tmpad[index].buttons[8].value;
	gamepad.forward = tmpad[index].buttons[9].value;
	gamepad.stickl = tmpad[index].buttons[10].value;
	gamepad.stickr = tmpad[index].buttons[11].value;
	gamepad.dpadu = tmpad[index].buttons[12].value;
	gamepad.dpadd = tmpad[index].buttons[13].value;
	gamepad.dpadl = tmpad[index].buttons[14].value;
	gamepad.dpadr = tmpad[index].buttons[15].value;
	gamepad.sticklx = tmpad[index].axes[0];
	gamepad.stickly = tmpad[index].axes[1];
	gamepad.stickrx = tmpad[index].axes[2];
	gamepad.stickry = tmpad[index].axes[3];

	return true;
}

//Apply the deadzones and return the result, indicate if the result should be smoothed or not.
//float = gamepad_deadzone(float, float, float, true | false)
function gamepad_deadzone(input, inner, outer, smooth)
{
	if (input === 0.0)
	{
		return input;
	}

	if (smooth !== true)
	{
		if (input > 0.0)
		{
			if (input > outer)
			{
				input = 1.0;
			}
			else if (input < inner)
			{
				input = 0.0;
			}
			return input;
		}
		if (input < -outer)
		{
			input = -1.0;
		}
		else if (input > -inner)
		{
			input = 0.0;
		}
		return input;
	}

	if (input > 0.0)
	{
		if (input > outer)
		{
			input = outer;
		}
		else if (input < inner)
		{
			input = inner;
		}
		return (input - inner) / (outer - inner);
	}

	if (input < -outer)
	{
		input = -outer;
	}
	else if (input > -inner)
	{
		input = -inner;
	}
	return (input + inner) / (outer - inner);
}

function example_gamepadloop()
{
	var text, result, i;

	if (player_gamepad === -1)
	{
		text = 'Please press a button or connect your controller.';
		document.getElementById('example').innerHTML = text;
		for (i = 0; i <= 15; i += 1)
		{
			result = gamepad_get(i);
			if (result === true)
			{
				player_gamepad = i;
				break;
			}
		}
		setTimeout('example_gamepadloop()', 100);
		return;
	}

	result = gamepad_get(player_gamepad);
	if (result === false)
	{
		player_gamepad = -1;
		setTimeout('example_gamepadloop()', 100);
		return;
	}
	text = 'Mapping: ' + gamepad.name + '<br>' +
	'Face 1: ' + gamepad.face1.toFixed(3) + '<br>' +
	'Face 2: ' + gamepad.face2.toFixed(3) + '<br>' +
	'Face 3: ' + gamepad.face3.toFixed(3) + '<br>' +
	'Face 4: ' + gamepad.face4.toFixed(3) + '<br>' +
	'Left Shoulder: ' + gamepad.shoulderl.toFixed(3) + '<br>' +
	'Right Shoulder: ' + gamepad.shoulderr.toFixed(3) + '<br>' +
	'Back: ' + gamepad.back.toFixed(3) + '<br>' +
	'Forward: ' + gamepad.forward.toFixed(3) + '<br>' +
	'Left Stick: ' + gamepad.stickl.toFixed(3) + '<br>' +
	'Right Stick: ' + gamepad.stickr.toFixed(3) + '<br>' +
	'D-Pad Up: ' + gamepad.dpadu.toFixed(3) + '<br>' +
	'D-Pad Down: ' + gamepad.dpadd.toFixed(3) + '<br>' +
	'D-Pad Left: ' + gamepad.dpadl.toFixed(3) + '<br>' +
	'D-Pad Right: ' + gamepad.dpadr.toFixed(3) + '<br>' +
	'Left Trigger: ' + gamepad.triggerl.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.triggerl, 0.125, 0.875, false).toFixed(3) + '<br>' +
	'Right Trigger: ' + gamepad.triggerr.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.triggerr, 0.125, 0.875, true).toFixed(3) + '<br>' +
	'Left Stick X: ' + gamepad.sticklx.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.sticklx, 0.25, 0.75, true).toFixed(3) + '<br>' +
	'Left Stick Y: ' + gamepad.stickly.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.stickly, 0.25, 0.75, true).toFixed(3) + '<br>' +
	'Right Stick X: ' + gamepad.stickrx.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.stickrx, 0.25, 0.75, false).toFixed(3) + '<br>' +
	'Right Stick Y: ' + gamepad.stickry.toFixed(3) + ' (Deadzone) ' + gamepad_deadzone(gamepad.stickry, 0.25, 0.75, false).toFixed(3);
	document.getElementById('example').innerHTML = text;
	setTimeout('example_gamepadloop()', 100);
}

function page_init()
{
	gamepad_init();
	example_gamepadloop();
}

var player_gamepad = -1;

addEventListener('load', page_init, false); 

</script>

<div id="example">
</div>
</body>
</html>