Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

6 years ago by ansimuz

Hi

I am trying to implement gamepad support to my game and been having some issues detecting up and down events from the gamepad.

The thing is that if i press any button it will be detected as is beign on autofire. I am trying to solve this by checking the timestamp as described in this article: http://www.html5rocks.com/en/tutorials/doodles/gamepad/?redirect_from_locale=es#toc-presses-movement

/><br />
<br />
<br />
But seems it escape from my comprehension. I have the following function that checks if the button that shoots arrows is pressed:<br />
<br />
<pre class= gamePadShoot: function(state){ this.gamepadUpdate(); if(this.gamepad.buttons[this.gamepad.BUTTONS.FACE_CUADRO]){ if(this.gamepad.timestamp == this.prevGamePadTimeStamp){ // ig.log('same timestamp: button is beign pressedd......'); ig.log('pressed'); return; } // save timestamp previous var this.prevGamePadTimeStamp = this.gamepad.timestamp; } } gamepadUpdate: function(){ this.gamepad = navigator.webkitGetGamepads && navigator.webkitGetGamepads()[2]; // code for buttons this.gamepad.BUTTONS = { FACE_EQUIS: 0, // Face (main) buttons FACE_CIRCULO: 1, FACE_CUADRO: 2, FACE_TRIANGULO: 3, LEFT_SHOULDER: 4, // Top shoulder buttons RIGHT_SHOULDER: 5, LEFT_SHOULDER_BOTTOM: 6, // Bottom shoulder buttons RIGHT_SHOULDER_BOTTOM: 7, SELECT: 8, START: 9, LEFT_ANALOGUE_STICK: 10, // Analogue sticks (if depressible) RIGHT_ANALOGUE_STICK: 11, PAD_TOP: 12, // Directional (discrete) pad PAD_BOTTOM: 13, PAD_LEFT: 14, PAD_RIGHT: 15 }; },
Hope you can provide some direction :s

6 years ago by dominic

Ideally, this would be implemented as a plugin that injects into ig.Input, so that you could do the following:

// bind keyboard and gamepad buttons
ig.input.bind( ig.KEY.X, 'shoot');
ig.input.bind( ig.GAMEPAD.FACE_1, 'shoot');

// use .pressed() and .state() as usual
if( ig.input.pressed('shoot') ) {
    // shoot
}

If you keep track of which buttons were held down in the last frame, you don't need the timestamp thing. Luckily, Impact already does this for each bound button, so we just have to hook into this.

UPDATE: fixed and tested in Chrome. Put this in a file at lib/plugins/gamepad.js and require plugins.gamepad in your main module.

ig.module(
	'plugins.gamepad' 
)
.requires(
	'impact.input',
	'impact.game'
)
.defines(function(){

// Assign some values to the Gamepad buttons. We use an offset of 256
// here so we don't collide with the keyboard buttons when binding.
ig.GAMEPAD_BUTTON_OFFSET = 256;
ig.GAMEPAD = {
	FACE_1: ig.GAMEPAD_BUTTON_OFFSET + 0,
	FACE_2: ig.GAMEPAD_BUTTON_OFFSET + 1,
	FACE_3: ig.GAMEPAD_BUTTON_OFFSET + 2,
	FACE_4: ig.GAMEPAD_BUTTON_OFFSET + 3,
	LEFT_SHOULDER: ig.GAMEPAD_BUTTON_OFFSET + 4,
	RIGHT_SHOULDER: ig.GAMEPAD_BUTTON_OFFSET + 5,
	LEFT_SHOULDER_BOTTOM: ig.GAMEPAD_BUTTON_OFFSET + 6,
	RIGHT_SHOULDER_BOTTOM: ig.GAMEPAD_BUTTON_OFFSET + 7,
	SELECT: ig.GAMEPAD_BUTTON_OFFSET + 8,
	START: ig.GAMEPAD_BUTTON_OFFSET + 9,
	LEFT_ANALOGUE_STICK: ig.GAMEPAD_BUTTON_OFFSET + 10,
	RIGHT_ANALOGUE_STICK: ig.GAMEPAD_BUTTON_OFFSET + 11,
	PAD_TOP: ig.GAMEPAD_BUTTON_OFFSET + 12,
	PAD_BOTTOM: ig.GAMEPAD_BUTTON_OFFSET + 13,
	PAD_LEFT: ig.GAMEPAD_BUTTON_OFFSET + 14,
	PAD_RIGHT: ig.GAMEPAD_BUTTON_OFFSET + 15
};


ig.normalizeVendorAttribute(navigator, 'getGamepads');

if( !navigator.getGamepads ) {
	// No Gamepad support; nothing to do here
	return;
}

ig.Input.inject({
	gamepad: null,
	lastButtons: [],
	hasButtonObject: !!window.GamepadButton,

	getFirstGamepadSnapshot: function() {
		var gamepads = navigator.getGamepads();
		for( var i = 0; i < gamepads.length; i++ ) {
			if( gamepads[i] ) {
				return gamepads[i];
			}
		}
		return null;
	},

	pollGamepad: function() {
		this.gamepad = this.getFirstGamepadSnapshot();
		if( !this.gamepad ) {
			// No gamepad snapshot?
			return;
		}

		// Iterate over all buttons, see if they're bound and check
		// for their state
		for( var button = 0; button < this.gamepad.buttons.length; button++ ) {
			var action = this.bindings[button+ig.GAMEPAD_BUTTON_OFFSET];

			// Is the button bound to an action?
			if( action ) {
				currentState = this.hasButtonObject
					? this.gamepad.buttons[button].pressed // W3C Standard 
					: this.gamepad.buttons[button]; // Current Chrome version

				var prevState = this.lastButtons[button];
				
				// Was not pressed, but is now?
				if( !prevState && currentState ) {					
					this.actions[action] = true;
					this.presses[action] = true;
				}
				// Was pressed, but is no more?
				else if( prevState && !currentState ) {
					this.delayedKeyup[action] = true;
				}
			}

			this.lastButtons[button] = currentState;
		}
	}
});

// Always poll gamepad before each frame
ig.Game.inject({
	run: function() {
		ig.input.pollGamepad();
		this.parent();
	}
})

});

6 years ago by ansimuz

Thanks,

I think theres a missing parameter since the keyboard stopped working. Think should be like this:

state: function( action ) {
                this.pollGamepad();
                return this.parent(action);

            },

            pressed: function( action ) {
                this.pollGamepad();
                return this.parent(action);
            },

            released: function( action ) {
                this.pollGamepad();
                return this.parent(action);
            },

6 years ago by ansimuz

However still not working where should the gamepad be defined?

I added to the pollGamepad function

ig.game.gamepad = navigator.webkitGetGamepads && navigator.webkitGetGamepads()[0];

and seems like this is empty

this.gamepad.buttons[]

I am lost :D

6 years ago by lTyl

For a project I'm working on, I wanted the player to be able to set-up his own controls and to support key sequences. In order to do this, I built my own Input system and used this library to handle the gamepad: http://kallaspriit.github.io/HTML5-JavaScript-Gamepad-Controller-Library/. It works as-is for my needs, and is released under MIT.

Maybe poke around the source there and see if it helps you find the solution to your problem.

6 years ago by ansimuz

@ITyl

Thanks I tried your script but i coulnd figure out how to intregate it to Impact.


Do you an example on how to bind it or call it from impactj? :D

However i would love something more native and simple as the Dominic approach and not have to call an external script.

6 years ago by dominic

Sorry for the delay. I updated the code above.

As far as I can tell, it works fine now. For Firefox, you currently have to set dom.gamepad.enabled in your about:config to true.

6 years ago by ansimuz

@Dominic

Its working like a charm! Thanks for this.

6 years ago by paleozoic

Can't wait to try this out.

6 years ago by Ash_Blue

This is perfect timing. Wasn't too happy with any of the plugins out there and thought I was going to have to write this over the weekend.

5 years ago by zachstronaut

Local multiplayer is so popular right now that it seemed silly to only support one gamepad when you can just as easily support four. Let me know if anybody has any problems with this code!

https://gist.github.com/zachstronaut/d2bf6db425bfc169e4e1

5 years ago by FelipeBudinich

Amazing Zachstronaut, I'll give it a try! (my gamepad code feels inadequate with all the better implementations on this thread!)

5 years ago by ansimuz

Everything works perfect.

But how do i bind the stick axes events?

5 years ago by Ash_Blue

I think you'll want something like this. Index 0 for x, and 1 for y

this.gamepad.axes[axisIndex];

5 years ago by ansimuz

mm for reason the gamepad.js is not detecting any gamepad anymore do you know if chrome made some changes to the api?

5 years ago by Joncom

@ansimuz: Perhaps Chrome now conforms to the "W3C Standard", instead of doing it's own thing. Just a guess. Looking at line 70 in Dominic's plugin.

5 years ago by ansimuz

@Jocom

You were right leave only the w3c option and now works:

currentState = this.gamepad.buttons[button].pressed; // W3C Standard

Thanks

5 years ago by ansimuz

Quote from Ash_Blue
I think you'll want something like this. Index 0 for x, and 1 for y

this.gamepad.axes[axisIndex];


Yeah that works, however i was looking if possible to attatch it the same way the buttons are attached, for example:

 if(ig.input.pressed('left')){

}

5 years ago by Joncom

Quote from ansimuz
leave only the w3c option and now works
If this is true, and Chrome only supports the W3C standard now, then Dominic should update his code.

I wonder if this plugin should be put on Github or something...

Is this pretty much the best gamepad plugin we have right now?

5 years ago by Krisjet

Did you find a solution ansimuz? Would love to able to poll the axis and treat them as buttons using pressed and state as usual.

5 years ago by ansimuz

No, i haven't found an elegant solution yet. Let me know if you do. I would love to have it implemented as events like press and state.

Quote from Krisjet
Did you find a solution ansimuz? Would love to able to poll the axis and treat them as buttons using pressed and state as usual.
Page 1 of 1
« first « previous next › last »