Adventure Game Studio

AGS Development => Engine Development => Topic started by: eri0o on Fri 29/04/2022 23:57:47

Title: [EXPERIMENTAL] Joystick in AGS - AGS-3.99.106.0-Alpha3-JoystickPR
Post by: eri0o on Fri 29/04/2022 23:57:47
Experimental Editor with AGS with Gamepad support!

Download Editor Here: >>AGS-3.99.106.0-Alpha3-JoystickPR.zip (https://github.com/ericoporto/ags/releases/download/3.6.1.1/AGS-3.99.106.0-Alpha3-JoystickPR.zip)<< | installer (https://github.com/ericoporto/ags/releases/download/3.6.1.1/AGS-3.99.106.0-Alpha3-JoystickPR.exe) | Code Source (https://github.com/ericoporto/ags/tree/feature-joystick) | GitHub Issue (https://github.com/adventuregamestudio/ags/issues/1364) | GitHub PR (https://github.com/adventuregamestudio/ags/pull/1759)

First the concepts, joystick means a generic input device comprised by binary (button) and analog (axis) inputs. A Gamepad means something that is vaguely close to a Xbox360 controller.

We can expand the API later, but the basics is joystick connection and disconnection is handled inside the AGS Engine and we can skip things by pressing A,B,X,Y or the symbols in PS controller.



@Alan v.Drake made a beautiful test project!

(https://user-images.githubusercontent.com/2244442/257968714-f356e682-a848-4786-b90b-9ffad8bb2ce2.png)

Playable AgsGameGamepadV4.zip (https://github.com/adventuregamestudio/ags/files/12245665/AgsGameGamepadV4.zip) | project (https://github.com/adventuregamestudio/ags/files/12242292/Gamepadv4.zip) | Online https://ericoporto.github.io/agsjs/gamepadtest/




Joystick Static Methods

Joystick.JoystickCount
Code (ags) Select
static readonly int Joystick.JoystickCountGet the number of connected joysticks. No joysticks should return 0!


Joystick.Joysticks
Code (ags) Select
static readonly Joystick* Joystick.Joysticks[int index]Gets a joystick by index from the internal engine joystick list.


Joystick Instance Attributes and Methods

Joystick.IsConnected
Code (ags) Select
readonly bool Joystick.IsConnectedTrue if joystick is connected.


Joystick.Name
Code (ags) Select
readonly String Joystick.Namejoystick name.



Joystick.IsButtonDown
Code (ags) Select
bool Joystick.IsButtonDown(int button)checks if a joystick button is pressed, by index. DPad is usually mapped separately as a hat.


Joystick.GetAxis
Code (ags) Select
bool Joystick.GetAxis(int axis, optional float deadzone)get a joystick axis or trigger, trigger only has positive values, by axis number. Values varies from -1.0 to 1.0 for axis, and 0.0 to 1.0 for triggers.


Joystick.GetHat
Code (ags) Select
eJoystick_Hat Joystick.GetHat(int hat)returns hat value


Joystick.AxisCount
Code (ags) Select
readonly int Joystick.AxisCountget the number of axis in the joystick


Joystick.ButtonCount
Code (ags) Select
readonly int Joystick.ButtonCountget the number of buttons in the joystick


Joystick.HatCount
Code (ags) Select
readonly int Joystick.HatCountget the number of hats in the joystick



Joystick.IsGamepad
Code (ags) Select
readonly bool Joystick.IsGamepadTrue if joystick is a valid gamepad connected - this means SDL2 recognized it as a valid GameController and has successfully mapped it's buttons to an Xbox360 gamepad.


Joystick.IsGamepadButtonDown
Code (ags) Select
bool Joystick.IsGamepadButtonDown(eGamepad_Button button)checks if a gamepad button is pressed, including dpad.

Possible buttons:


Joystick.GetGamepadAxis
Code (ags) Select
float Joystick.GetGamepadAxis(eGamepad_Axis axis, optional float deadzone)get gamepad axis or trigger, trigger only has positive values. Values varies from -1.0 to 1.0 for axis, and 0.0 to 1.0 for triggers.

You can optionally pass an additional parameter to use as deadzone. If an axis absolute value is smaller than the value of deadzone, it will return 0.0. Default value is AXIS_DEFAULT_DEADZONE, which is for now 0.125, use the name if you need a number.

Possible axis and triggers:


CHANGELOG:
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v1
Post by: Mehrdad on Sat 30/04/2022 06:07:24
Wow!. Super useful. Nice job @eri0o
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v1
Post by: eri0o on Sat 30/04/2022 12:11:02
Thanks Mehrdad! I still need to figure more things, but I wanted to throw together a basic one, since with SDL2, we can roll joysticks for all platforms at the same time when support is in the engine itself. :)

Also sketching the API with users because things on the Engine are hard to change.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v2
Post by: eri0o on Sun 01/05/2022 02:37:43
Small update, just switched GetAxis to provide a float value. An example usage is added in the code of the example project as follows:

Code (ags) Select
#define DEAD_ZONE 0.125
float gamepad_mouse_x, gamepad_mouse_y;
bool update_mouse;
bool prev_button_a_pressed;

void repeatedly_execute_always()
{
  if(pad != null)
  {
    if(pad.IsButtonDown(eGamepad_ButtonA) && !prev_button_a_pressed)
    {
      mouse.Click(eMouseLeft);
    }
   
    prev_button_a_pressed = pad.IsButtonDown(eGamepad_ButtonA);
   
    float x_lstick = pad.GetAxis(eGamepad_AxisLeftX);
    float y_lstick = pad.GetAxis(eGamepad_AxisLeftY);
 
    if( x_lstick < -DEAD_ZONE || x_lstick > DEAD_ZONE ||
        y_lstick < -DEAD_ZONE || y_lstick > DEAD_ZONE )
    {
      if(update_mouse) {
        gamepad_mouse_x = IntToFloat(mouse.x);
        gamepad_mouse_y = IntToFloat(mouse.y);
        update_mouse = false;
      }
     
      gamepad_mouse_x += 10.0 * x_lstick;
      gamepad_mouse_y += 10.0 * y_lstick;
     
      mouse.SetPosition(FloatToInt(gamepad_mouse_x, eRoundDown) ,
                        FloatToInt(gamepad_mouse_y, eRoundDown));
    } else {
      update_mouse = true;
    }
  }
}
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v2
Post by: deadsuperhero on Sun 01/05/2022 06:12:43
Oh, man! This is exactly what I need right now for my projects. Very exciting to see this, would love to get my games working on SteamDeck!
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v2
Post by: AndreasBlack on Sun 01/05/2022 08:00:02
Nice! Gonna give this a try later, thanks! I knew it had something to do with the deadzone being off as i wrote in the DM, but my limited coding knowledge could only get it to stay in the middle of the screen previously!

Edit: Something really strange is going on. I get this error: Failed to save room room1.crm; details below
room1.asc(21): Error (line 21): Type mismatch: cannot convert 'int' to 'float'

The project seems to randomly work. Really odd. Say if i edit the line AGS is claiming has an error.

Code (ags) Select
    float x_lstick = pad.GetAxis(eGamepad_AxisLeftX);

Change it to say AxisLeft); leave out the X then i get an error obviously, then edit it back to the correct syntax AxisLeftX); Then still it gives me the error Line 21 again, even tho the syntax is right!

No idea what's causing this. So i can't give this a try in my main project cause i get that error no matter what in that project. Even in the example project as written above i could recreate the error line.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v2
Post by: eri0o on Sun 01/05/2022 11:17:12
I cannot reproduce... Are you sure you are using the new V2 version I provided above and not the previous V1 version that was available before? In V1 GetAxis was giving an integer, but now in V2 I changed to a float, because I felt it was easier to people understand the range available.

If someone else could try too, it would be great.  (roll)

Edit: I may implement an additional axis_deadzone parameter in GetAxis to simplify code for this.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v2
Post by: AndreasBlack on Sun 01/05/2022 12:19:09
I was blind! I didn't see you've also updated the link for the AGSbeta to a "v2". My bad! It works now! Thanks!

The mouse/controller seems stable too, fantastic!
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: eri0o on Sun 01/05/2022 14:45:07
Added a deadzone parameter in GetAxis and updated the description above to explain how it works.

This allows switching the code to a slightly simpler comparison. It will also nudge in the importance of deadzone if someone wants to modify the parameter.

Code (ags) Select
float gamepad_mouse_x, gamepad_mouse_y;
bool update_mouse;
bool prev_button_a_pressed;

void repeatedly_execute_always()
{
  if(pad != null)
  {
    if(pad.IsButtonDown(eGamepad_ButtonA) && !prev_button_a_pressed)
    {
      mouse.Click(eMouseLeft);
    }
   
    prev_button_a_pressed = pad.IsButtonDown(eGamepad_ButtonA);
   
    float x_lstick = pad.GetAxis(eGamepad_AxisLeftX);
    float y_lstick = pad.GetAxis(eGamepad_AxisLeftY);
 
    if( x_lstick != 0.0 || y_lstick != 0.0 )
    {
      if(update_mouse) {
        gamepad_mouse_x = IntToFloat(mouse.x);
        gamepad_mouse_y = IntToFloat(mouse.y);
        update_mouse = false;
      }
     
      gamepad_mouse_x += 8.0 * x_lstick;
      gamepad_mouse_y += 8.0 * y_lstick;
     
      mouse.SetPosition(FloatToInt(gamepad_mouse_x, eRoundDown) ,
                        FloatToInt(gamepad_mouse_y, eRoundDown));
    } else {
      update_mouse = true;
    }
  }
}


Note for the web port:
Edit:

I ninjad a new update to v3 itself, just a small adjustment to guarantee the float values from GetAxis are always sane.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: Crimson Wizard on Mon 02/05/2022 08:46:07
I see that the gamepad buttons are used as mouse click simulation, but I assume this is done temporary for a test.

Should the goal be to have gamepad buttons handled similar to keyboard key and mouse clicks, that is to have their own respective callback, like on_gamepad_press?

One optional idea is to have gamepad buttons merged with eKey codes. The benefit of that is that you may assign them to the same variables as keys, both in engine API properties, and script variables.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: eri0o on Mon 02/05/2022 10:54:09
QuoteOne optional idea is to have gamepad buttons merged with eKey codes. The benefit of that is that you may assign them to the same variables as keys, both in engine API properties, and script variables.

That is interesting, but I think I prefer to figure some dedicated way to do so, Gamepads have predefined buttons but joysticks don't. But I will keep that approach in mind as a fallback in case things don't work the way I hope.

Things like, multiple Gamepads/Joysticks, I must keep in mind and try to not clash parts that would be helpful to most and the full range of possibilities, like couch co-op.

About on_gamepad_press, I will at some point, but it's not very useful right now (can't skip text) so I will keep using repeatedly execute always at this time. I wonder if for gamepad -> mouse mapping there's something better we could do at this time, like click and holding isn't possible, because there's no way to force a button state in the mouse...
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: Crimson Wizard on Mon 02/05/2022 10:59:03
Quote from: eri0o on Mon 02/05/2022 10:54:09
About on_gamepad_press, I will at some point, but it's not very useful right now (can't skip text) so I will keep using repeatedly execute always at this time.

Could you elaborate how is this related to skipping text?

IMO it may be useful just as the key presses in on_key_press are useful: to react to button press without having to deal with their on/off states in the rep-exec. Right now it seems in your examples you're trying to use gamepad to simulate mouse cursor and clicks. But gamepads could be used without mouse cursors as well, similar to how keyboard is used in keyboard controlled games.

My meaning in general is not to try to simulate anything with gamepad (this was the plugin's approach, because there was no other way) but instead integrate gamepad as a part of the normal engine input and script. Have events for gamepad similar to how there are events for mouse and keys.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: eri0o on Mon 02/05/2022 11:25:19
on_ events don't happen when something is blocking. Also they are not good when you need to get something continuously, like keep the character walking.

I also think I am handling wrong the pointers in my code, I think ideally objects that represent the same index should get the same pointer - right now this is countered because you can't connect to the same joystick twice, and that is only factory function that produces gamepads. But in the engine I could theoretically pass the pointer of the pressed joystick in an on_ event so you could inspect which joystick/gamepad had the button pressed, which would be easy if the pointers were guaranteed to match. I am not sure the best approach right now to guarantee such uniqueness.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: Crimson Wizard on Mon 02/05/2022 11:29:44
Quote from: eri0o on Mon 02/05/2022 11:25:19
on_ events don't happen when something is blocking. Also they are not good when you need to get something continuously, like keep the character walking.

Ok, but so do events for mouse clicks and keys, and yet they exist and are useful.

Skipping text and skippable blocking actions should be done in the engine IMO. In other words, whenever there's an event for mouse or keys there should be a corresponding event for gamepad. If a mouse or keys are checked in the engine, so should gamepad be checked as well, and so on. Well, at least this is how I thought this will be done. Is your goal for the moment to use gamepad to simulate other inputs in rep-exec-always?
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: AndreasBlack on Mon 02/05/2022 12:11:27
Just tried the new V3 and i'd made sure i've downloaded all the links this time  :-D In V3 i've noticed the character seems to get stuck around the first or second walk frame before walking away, sorta like running on a treadmill a millisecond (Thumbleweed template). Not sure what that is about ??? works fine otherwise, to the untrained eye, at least. Have you tried adding a view with one frame and added audio into the frame and see if it stutters all over? Say forexample the player wants a fist animation view and adds the sound in the view and pushes the button or holds down the button, does it stutter? In my mind, i don't think it should, if it does! Thanks




Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: eri0o on Mon 02/05/2022 12:22:24
Quote from: AndreasBlack on Mon 02/05/2022 12:11:27
Just tried the new V3 and i'd made sure i've downloaded all the links this time  :-D In V3 i've noticed the character seems to get stuck around the first or second walk frame before walking away, sorta like running on a treadmill a millisecond (Thumbleweed template). Not sure what that is about ??? works fine otherwise, to the untrained eye, at least. Have you tried adding a view with one frame and added audio into the frame and see if it stutters all over? Say forexample the player wants a fist animation view and adds the sound in the view and pushes the button or holds down the button, does it stutter? In my mind, i don't think it should, if it does! Thanks

Sorry, but I don't think I added any handling of views here, is this something in your own code? Or is it something that happens when you click for the character to walk using the button of the gamepad to press a button on the mouse?

QuoteSkipping text and skippable blocking actions should be done in the engine IMO

Yes, but I think it needs it's own functions and place to store things. One problem is one can have two joysticks or more connected, and then they can save the game and load and have zero, there are things regarding the gamepad that seem to belong more in a config file than in an save state. But these depends on how much information is meant to be stored in these.

I will write down the bits of the problems I am trying to figure out, since, I do not have been able to figure the roadmap yet, maybe some of the problems I am thinking are just in my head and may not be that relevant for now. I revised a bit the notes on the original issue in GitHub, I will try to update there with things on my mind.

I really need people to play around with this and come up with the problems, that arise. :/
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v3
Post by: eri0o on Mon 02/05/2022 17:10:14
I will be looking in to add in the next version a way to properly skip texts for this, but it may not be the final form we endup going, but I need something materialized to think.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: eri0o on Sun 15/05/2022 15:36:59
Now you can use A,B,X or Y buttons to skip Display and Speak messages. This is still in development, I am trying to figure it out the API for being able to say which button can be used and stuff like that - for now, if keyboard can skip text, the gamepad will be able to skip too.

For now, the controller has to be connect first by using the script API before it can be used as such. I updated the top post to v4 which is the release that includes this. If you downloaded the v4 yesterday, you need to download again as I just found a mistake at that.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: AndreasBlack on Fri 20/05/2022 21:10:17
It happens when i click walk with a button on the controller, yes. Thumbleweed template with own game/sprites ofc. They never behave like that without the controller using the mouse tho. Walks normally then.
Normal walking views added with 8 frame sprites right left up down, etc. Nothing special going on, so i was a bit surprised by it tbh. But focus on solving the big picture, i should never complain anymore, not qualified. Great job so far!  (nod)
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: eri0o on Sat 21/05/2022 01:09:22
@AndreasBlack, Can you try V4 that is up and see if it still happens? I previously wrongly handled button press when the button was released too, so this may have been a problem, but I fixed in the latest version.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: AndreasBlack on Sat 21/05/2022 09:12:36
I did, the problem seems to still be there unfortunately. I can do a game capture and post. Edit: Easiest way to "semi understand" what's going on is. Keep tapping your button where the mouseclick is assigned too. It's a millisecond of "that" move that is happening. It does not happen when using the mouse.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: Dualnames on Mon 23/05/2022 02:35:30
eri0o, first off, I think this is great!

Secondly, the plugin I made uses all SDL thingies, including battery and rumble, they should also be implemented!
Once this is succesfully done, I'll make the plugin essentially deprecated!
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: eri0o on Mon 23/05/2022 13:27:41
So what I am looking into now is the GameController part of the API, this is just to go fast, later I will look into what you mentioned which is in the joystick part of the API.

But keep in mind I am looking at the intersection of this and the engine, this means I am modifying the engine, like, if a cutscene can be skipped by the controller, or a wait, or dialogues and so on, these are the things I am trying to figure out here.

Once that is taken care, then things like button configuration, what a joystick 1 or 2 have different, when this matters, and then we can go to the joystick implementation.
Title: Re: [EXPERIMENTAL] Gamepad in AGS - v4
Post by: Dualnames on Tue 24/05/2022 17:00:59
All good, I understand that, I think and again, this is great, this is the right way. MAKE ME OBSOLETE, ERIOO!
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.6.0.35-Beta15_Joystick
Post by: eri0o on Sat 03/09/2022 17:26:44
I updated the Editor, it now instead it has a Joystick struct, and the opened Joystick can be a valid Gamepad or not, I haven't yet figure the interface to say which button can skip dialog/speech, but if it's recognized as Xbox360 compatible gamepad, whatever gets the A button is the button that advances dialog. You can also get button, axis or hat by index if you want to do your own non-xbox360 mapping.
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.6.0.35-Beta15_Joystick
Post by: Crimson Wizard on Sat 05/08/2023 14:18:54
This thread should be updated, there's a slightly different API prepared for merging to AGS 4:
https://github.com/adventuregamestudio/ags/pull/1759
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.99.106.0-Alpha3-JoystickPR
Post by: eri0o on Sun 06/08/2023 15:34:29
I updated the API in the first post (https://www.adventuregamestudio.co.uk/forums/engine-development/experimental-joystick-in-ags-ags-3-6-0-35-beta15_joystick/msg636645809/#msg636645809) and added links to example project file, downloadeable test game, online test game...

There is a chance some really newer controller doesn't work in some way, but once the SDL2 version is upgraded (https://github.com/adventuregamestudio/ags/pull/2075) these will probably be fixed (some joy-con stuff, and some steam deck stuff)
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.99.106.0-Alpha3-JoystickPR
Post by: eri0o on Sun 13/08/2023 17:15:07
Hey, it would be nice if someone could test this and report their findings.  :P
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.99.106.0-Alpha3-JoystickPR
Post by: abstauber on Sat 26/08/2023 22:20:48
I just gave this a go. After updating the gamepadv4 demo with the new api changes (line 70 and 72), it worked fine. I tested it with an 8bitdo Zero 2 Controller and a PS2 Gamepad+USB adapter. Both were detected instantly and every button worked fine.
One thing I recognized was: on the 8Bitdo pad, the dpad was exclusivly detected as analog left or L3.

On the PS2 pad it was the same until I activated the analog sticks. After that the dpad was mapped to the dpad and the analog sticks were correctly recognized as L3 and R4.

So all in all for a first test I'd say, it works very well. Next I'll upgrade my agsjoy game to this new version and have a look at that.
Title: Re: [EXPERIMENTAL] Joystick in AGS - AGS-3.99.106.0-Alpha3-JoystickPR
Post by: abstauber on Mon 28/08/2023 22:53:40
Two observations so far:

GetAxis should return bool according to the first post, but returns a float.

GetAxis detects the Y-Axis of my gamepad's right analog stick two times. The testgame shows the y-values at a2 and a3, and the x-values in a4.