Getting Input from Gamepads with HTML5 and JavaScript

The JavaScript program below, when run, will display the current state of all gamepads connected to the user’s system. To see it in action, copy it into an .html file and open that file in a web browser that runs JavaScript.

This code makes use of the semi-standardized Gamepad API for web browsers, which is still surprisingly tricky. There’s supposed to be a way to capture events when the user connects and/or disconnects a gamepad, but Google Chrome doesn’t fully support it, so I’m not checking for that. So the code basically just polls all the gamepads 10 times a second and updates the display accordingly. After first plugging in the controller, or after leaving it unattended for a few minutes, it may be necessary to press certain buttons on the controller to “wake it up” and then restart the program.

GamepadStatus


<html>
<body>

<div id="divOutput"></div>

<script type="text/javascript">

// main

function main()
{
	var inputHelper = new InputHelper();
	new TimerHelper(inputHelper).initialize();
}

// classes

function Gamepad(index)
{
	this.index = index;
	this.axisDisplacements = [];
	this.buttonsPressed = [];
}
{
	Gamepad.prototype.statusAsString = function(inputHelper)
	{
		var returnValue = "Gamepad " + this.index + ": ";

		for (var i = 0; i < this.axisDisplacements.length; i++)
		{
			var axisDisplacement = this.axisDisplacements[i];
			var axisDisplacementAsString = 
				"A" + i + "="
				+ axisDisplacement + " ";
			returnValue += axisDisplacementAsString;			
		}

		for (var i = 0; i < this.buttonsPressed.length; i++)
		{
			var isButtonPressed = this.buttonsPressed[i];
			var buttonAsString = 
				"B" + i + "=" 
				+ (isButtonPressed == true ? 1 : 0) + " ";
			returnValue += buttonAsString;
		}

		return returnValue;
	}

	Gamepad.prototype.updateFromSystemGamepad = function(systemGamepad)
	{
		var systemAxisDisplacements = systemGamepad.axes;
		for (var i = 0; i < systemAxisDisplacements.length; i++)
		{
			var systemAxisDisplacement = systemAxisDisplacements[i];
			this.axisDisplacements[i] = systemAxisDisplacement;
		}

		var systemButtons = systemGamepad.buttons;
		for (var i = 0; i < systemButtons.length; i++)
		{
			var isButtonPressed = systemButtons[i].pressed;
			this.buttonsPressed[i] = isButtonPressed;
		}
	}
}

function DisplayHelper()
{
	// static class
}
{
	DisplayHelper.showMessage = function(message)
	{
		var divOutput = document.getElementById("divOutput");
		divOutput.innerHTML = message;
	}
}

function InputHelper()
{
	this.gamepadsConnected = [];
}
{
	InputHelper.prototype.checkForGamepads = function()
	{
		var systemGamepads = this.systemGamepads();
		for (var i = 0; i < systemGamepads.length; i++)
		{
			var systemGamepad = systemGamepads[i];
			if (systemGamepad != null)
			{
				var gamepad = new Gamepad(i);
				this.gamepadsConnected.push(gamepad);
			}
		}
	}

	InputHelper.prototype.displayStatus = function()
	{
		DisplayHelper.showMessage(this.statusAsString());
	}

	InputHelper.prototype.initialize = function()
	{
		this.checkForGamepads();

		this.displayStatus();
	}

	InputHelper.prototype.statusAsString = function()
	{
		var returnValue = 
			"There are currently " 
			+ this.gamepadsConnected.length 
			+ " gamepad(s) connected:";

		for (var i = 0; i < this.gamepadsConnected.length; i++)
		{
			var gamepad = this.gamepadsConnected[i];
			var gamepadStatus = gamepad.statusAsString();
			returnValue += "<br />" + gamepadStatus;
		}
	
		return returnValue;
	}

	InputHelper.prototype.systemGamepads = function()
	{
		return navigator.getGamepads();
	}

	InputHelper.prototype.update = function()
	{
		var systemGamepads = this.systemGamepads();

		for (var i = 0; i < this.gamepadsConnected.length; i++)
		{
			var gamepad = this.gamepadsConnected[i];
			var systemGamepad = systemGamepads[gamepad.index];
			gamepad.updateFromSystemGamepad(systemGamepad);
		}
		
	}
}

function TimerHelper(inputHelper)
{
	this.inputHelper = inputHelper;
}
{
	TimerHelper.prototype.initialize = function()
	{
		this.inputHelper.initialize();

		this.timer = window.setInterval
		(
			this.handleEventTimerTick.bind(this),
			100 // millisecondsPerTick
		);
	}

	TimerHelper.prototype.handleEventTimerTick = function()
	{
		this.inputHelper.update();
		this.inputHelper.displayStatus();
	}
}

// main

main();

</script>
</body>
</html>

This entry was posted in Uncategorized and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s