- From: Florian Bösch <pyalot@gmail.com>
- Date: Sat, 4 Aug 2012 19:10:43 +0200
- To: Glenn Maynard <glenn@zewt.org>
- Cc: Scott Graham <scottmg@chromium.org>, Rick Waldron <waldron.rick@gmail.com>, olli@pettay.fi, Webapps WG <public-webapps@w3.org>, Ted Mielczarek <ted@mielczarek.org>
- Message-ID: <CAOK8ODiWV0BMZiHe5UhSFFg5M3LuoTD_vYiDx3pp0kvhEixXXQ@mail.gmail.com>
On Sat, Aug 4, 2012 at 7:03 PM, Glenn Maynard <glenn@zewt.org> wrote:
> Here's a rough sketch of an API that provides clean forwards-compatibility
> for devices. I think this also avoids all of the issues I talked about
> earlier: it gives a clean, easy to use event-based API that preserves
> ordering and timestamps; it can be used in both an event-based and polling
> way; it can retrieve both events and the current state; and most
> importantly it doesn't push things into a library, with all of the serious
> (and hopefully obvious to everyone on this list) problems that would cause.
>
> // Retrieve a representation of the device, with no actual access to
> inputs:
> var gamepad = getSomeInputDevice();
>
> // Get a list of supported layouts:
> console.log(gamepad.layouts);
> ["X360", "NES", "SNES", "raw"]
>
> // Get an interface, specifying which layout to use.
> var gamepadInput = gamepad.getLayout("X360");
>
> // Read the current state.
> var state = gamepadInput.getCurrentState();
> /* state == {
> // These values are defined by the X360 layout.
> leftThumbStickX: 0, leftThumbStickY: 0,
> rightThumbStickX: 0.4, rightThumbStickY: 0.5,
> up: true, right: false, down: false, left: false,
> buttonX: false, buttonY: false, buttonA: false, buttonB: false,
>
> // Inputs which have no representation in this layout are returned in
> raw form.
> rawCompassAngle: 45,
> } */
>
> // Read the buffer of changes:
> var stateChanges = gamepadInput.read();
> /* stateChanges == [{
> input: "rightThumbstickX", // These labels are equal to the object
> keys in "state" above.
> value: 0.5,
> lastValue: 0.4,
> timestamp: 1336102719319,
> }, {
> input: "rawCompassAngle",
> value: 55,
> lastValue: 45,
> timestamp: 1336102721319,
> }] */
>
> function processInput(stateChanges)
> {
> // Process inputs:
> for(var i = 0; i < stateChanges.length; ++i)
> {
> var change = stateChanges[i];
> var delta = change.lastValue - change.value;
> switch(change.input)
> {
> case "left": console.log("Left button was " + change.value?
> "pushed":"released"); break;
> case "leftThumbStickX":
> console.log("Left stick X axis:" + change.value + " with a
> relative change of " + delta);
> break;
> }
> }
>
> // Update the game state. This API allows us to process all inputs
> that happen simultaneously together,
> // such as axis changes, and then only update the game state once for
> the whole batch.
> processInputs();
> }
>
> // Receiving an event on change:
> gamepadInput.onchange = function(e) { processInput(gamepadInput.read());
> };
>
> Some points:
>
> - A browser may support many different layouts for the same device. For
> example, an Xbox 360 controller can easily be used as an NES or SNES
> controller, so it can expose those profiles.
> - Raw inputs for any unmapped inputs are included for all profiles. This
> allows games to make use of additional controls, without being forced to
> drop back to "raw" to access them at all.
> - If a profile is exposed at all, the inputs of the profile must be
> completely covered.
> - Layout may not always map 1:1 to raw inputs. For example, the
> Playstation controller's D-pad is four buttons in a cross; layouts may map
> these four buttons down to two axes.
> - All data in getCurrentState is absolute, since it doesn't mutate the
> object. Therefore, purely relative inputs, such as trackballs and
> (probably) steering wheels, are returned in an absolute, accumulated form.
> To get relative motion, subtract the value from the previous value.
>
> By the way, while I only included "NES" as an example, having a "baseline"
> layout like that (with a more generic name) is useful: tons of simple games
> use only a D-pad and a couple buttons. This would give them get the widest
> input device support possible, by not having to request a profile with far
> more features than they need.
>
> I haven't tried to incorporate Florian's suggestion of using something
> like ArrayBuffer. That could be supported later, eg. by providing a
> readIntoBuffer(buffer) next to read(). That's too complex to try to tackle
> all at once.
What happens if there is no supported profile?
Received on Saturday, 4 August 2012 17:11:12 UTC