[PLUGIN] Joystick / Game controller support! v1.2.0

Started by Wyz, Fri 20/08/2010 19:43:43

Previous topic - Next topic

subspark

QuoteI'm also eager to see that fighting game.
Thanks Wyz. There will be a press release soon about it.

Cheers,
Sparky.

Icey

I'm sorry but I really have no clue how to set this up and I really want to try this. Can some one show me a full code of were every thing goes and I am using 1 controller BTW.

Wyz

Well since I've had this request before a simple JustWorksâ,,¢ implementation. But still Do the tutorials!

Code: ags

// room script file

Joystick *joy;

Joystick * OpenDefaultJoystick()
{
  Joystick *j;
  
  JoystickRescan();
  int count = JoystickCount();
  
  int i = 0;
  while (i < count)
  {
    j = Joystick.Open(i);
    
    if ((j != null) && j.Valid() && !j.Unplugged())
      return (j);
    
    i++;
  }
  return (Joystick.Open(-1));
}

function ScaleAxis(int x, int min, int max)
{
  return min + ((x + JOY_RANGE) / ((JOY_RANGE * 2) / (max - min)));
}

function room_AfterFadeIn()
{
  joy = OpenDefaultJoystick();
}

function room_RepExec()
{
  mouse.SetPosition(ScaleAxis(joy.x, 0, System.ScreenWidth), 
                    ScaleAxis(joy.y, 0, System.ScreenHeight));
  
  if (joy.IsButtonDown(0))
    player.Walk(mouse.x, mouse.y, eNoBlock, eAnywhere);
}

function room_Leave()
{
  joy.Close();
  joy = null;
}
Life is like an adventure without the pixel hunts.

Khris

I've been playing around with this plugin and it's really great so far, I think I have a pretty good grasp of its capabilities.

Two things: I assume there's no way to simulate a mouse click or keypress? When I use Display("bla"); I can't get rid of the text window using the Joystick it seems which makes the plugin almost useless due to having to replace Display and Say with custom functions.

I wrote this as part of a button mapping feature:

Code: ags
int noloopcheck WaitForJoyButton(Joystick*j, int b) {
  int bc = j.ButtonCount;
  bool exit;
  int i, pressed;
  while (!exit) {
    // return button
    if (b == -1) {
      i = 0;
      while (i < bc) {
        if (j.IsButtonDown(i)) {
          pressed = i;
          i = bc;
          exit = true;
        }
        i++;
        Wait(1);
      }
    }
    // wait for specific button
    else {
      if (j.IsButtonDown(b)) exit = true;
    }
  }
  // wait for button to be no longer pressed
  exit = false;
  while (!exit) {
    if (b == -1 && !j.IsButtonDown(pressed)) exit = true;
    if (b >= 0 && !j.IsButtonDown(b)) exit = true;
    Wait(1);
  }
  return pressed;
}


Pretty simple stuff and it does work fine. The thing is just that due to the first Wait(1) sometimes a button press isn't detected when I quickly tap it. If I remove the Wait(1), the game simply hangs. Looks like the plugin interface doesn't get a chance to relay button presses anymore.
Do I have to revert to using on_joy_press? Because that doesn't work inside an additional script, only in Global.asc.

Wyz

Yes simulating mouse clicks is still an unresolved issue, but since it's really annoying you can't use Display. Well, when I have an idea how to work around it, I'll update the plugin. :)

For the button poller, hmm something that might work is using j.Update(); The function will update the button/axes state recorded by the plugin (similar to mouse.Update()). I hope it does. :)
Life is like an adventure without the pixel hunts.

Khris

It's still a great module and everything else works flawlessly. If I'm going to use it in an actual game I'm pretty sure I'm not going to use the built-in Display and Say functions anyway.

I tried using j.Update(), it didn't make much of a difference though. Then I tried setting the game speed to 200 temporarily, and that worked pretty well; it's almost impossible to make it not detect a tap now.

Thanks for a great job; I'm pretty sure there's no way to make JoyToKey transfer the analog stick's tilt.

Wyz

Hey the GameSpeed trick is very useful, thanks for the tip! :D
Life is like an adventure without the pixel hunts.

Calin Leafshade

Sorry for the bump but the file is missing.

Anyone got a mirror?

Khris



GoToHellDave

Does anybody still have access to the tutorial for this? I'd really like to check it out and the links appear to be dead.

Wyz

Oh fudge, I forgot all about this. :-[

I've updated all the links in the first post; they should work now! (Thanks goes to Peder for hosting this)
Life is like an adventure without the pixel hunts.

Crimson Wizard

BTW, in case anyone interested, I was able to test this plugin without real joystick, using this: http://headsoft.com.au/index.php?category=vjoy

Just saying ;).

Grim

Sorry for the bump.

I'm using xbox 360 wireless controller and in the tutorial demo it doesn't seem to do anything. It says in the beginning the controller has been detected and it has 10 buttons. I skip those messages (with keyboard) and change rooms with keys 1-9 but in none of them my controller is able to work. It works normally, when I play games with it, so I'm guessing there's some kind of problem with it being compatible with AGS and the Joystick plugin... Any ideas? ( I assume it is possible normally to use it in the tutorial?).

EDIT: Tried different controller. It works. It seems only wired controllers are compatible for this.

Vincent

Hi guys, I'm sorry for this dumb question.

I'm trying to find an alternative to the standard function (WaitMouseKey) since it does not react any buttons with the controller.
I'm using the fantastic function that Wyz suggested to do, since it works perfectly. (WaitMouseKeyJoy)
The only little issue that I can not understand is why if I press the Axis they are not counted as buttons pressed in the function. :-\
So I was interested to ask you if there is a way to include the Axis as Buttons pressed somehow.

Code: ags

function WaitMouseKeyJoy(int time, Joystick *j)
{
  int buttons = j.buttons;
  
  while (time)
  {
    if ((j.buttons ^ buttons) & j.buttons) 
      return (1);
    else
      buttons = j.buttons;
    
    if (WaitMouseKey(1))
      return (1);
    
    if (time > 0)
      time--;
  }
  
  return (0);
}


Any kind of help is very welcome, many thanks guys in advance.

Wyz

Hmm yes that function does not regard axes as it is. :D It is possible to do so however but it is not trivial; you need to check for movement rather than a position. I've come up with a function but I did not have time to test it so let me know if it works or not.

Code: ags

// Amount of movement that triggers it, play with this
// Find a middle ground that does not only work for your controller
#define JOY_THRESHOLD 8192

function WaitMouseKeyJoyAxes(int time, Joystick *j)
{
  int buttons = j.buttons;
  int p[] = new int [j.AxesCount];
  
  int i = j.AxesCount;
  while (i > 0)
  {
    i--;
    p[i] = j.GetAxis(i);
  }
  
  while (time)
  {
    if ((j.buttons ^ buttons) & j.buttons)
      return (1);
    else
      buttons = j.buttons;
    
    i = j.AxesCount;
    while (i > 0)
    {
      i--;
      
      int axis = j.GetAxis(i);
      int disp = axis - p[i];
      
      if (disp < 0)
        disp = 0 - disp;
      
      p[i] = axis;
      
      if (disp >= JOY_THRESHOLD)
        return (1);
    }
    
    if (WaitMouseKey(1))
      return (1);
    
    if (time > 0)
      time--;
  }
  
  return (0);
}


I hope it helps. :)
Life is like an adventure without the pixel hunts.

Vincent

Greetings Wyz, I would like to thank you very much for taking the time looking into this.
I have thoroughly enjoyed, thank you very much :)

I tried to test your new function but unfortunately it give me a persistent error.
Even change the value of our constant JOY_THRESHOLD it give the same error.
The script appears to be hung (a while loop ran 150001 times) the problem may be in a calling function.
Here is the line which generates the error :

Code: ags

#define JOY_THRESHOLD 8192

function WaitMouseKeyJoyAxes(int time, Joystick *j)
{
  int buttons = j.buttons;
  int p[] = new int [j.AxesCount];
  
  int i = j.AxesCount;
  while (i > 0)
  {
    i--;
    p[i] = j.GetAxis(i);
  }
  
  while (time)
  {
    if ((j.buttons ^ buttons) & j.buttons)
      return (1);
    else
      buttons = j.buttons;
    
    i = j.AxesCount;
    while (i > 0)
    {
      i--;
      
      int axis = j.GetAxis(i);
      int disp = axis - p[i];
      
      if (disp < 0)
        disp = 0 - disp;
      
      p[i] = axis;
      
      if (disp >= JOY_THRESHOLD)
        return (1);
      
      i++;
    }                              // <---------------------------- hung stuck
    
    if (WaitMouseKey(1))
      return (1);
    
    if (time > 0)
      time--;
  }
  
  return (0);
}



I tried it and perform the noloopcheck keyword between the function but in vain :)
I would be very glad if you can have the time to look into it.
Many thanks Wyz in advance, again. :)

Dualnames

You need to add a noloopcheck thingie on the function.
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

Vincent

Greetings Dualnames, thank you very much for your suggestion. :)
After further retested with the noloopcheck generates the same error.
It is strange because it hung even if I press a button instead of axes.
In both cases (with or without noloopcheck) the function crashes. :(

Wyz

Hah, teaches me not to post code that is untested. There is a copypasta mishap on line 38; get rid of the i++ there and it should work. :)
Life is like an adventure without the pixel hunts.

SMF spam blocked by CleanTalk