Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: joystick axis  (Read 2303 times)

0 Members and 1 Guest are viewing this topic.

TooFux

  • Newbie
  • *
  • Posts: 4
    • View Profile
joystick axis
« on: June 05, 2012, 09:37:55 pm »
Hi,

When the player moves the joystick axis, we get values between [-100, 100].

Right is (100, 0) and upper right is (100, 100).

My problem is that I would like to move at constant speed in all directions.
When I use this input the length in horizontal and vertical is 100 and the length in diagonal is ((sqrt 2) * 100).

How can I convert this square area into a circle area ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: joystick axis
« Reply #1 on: June 05, 2012, 10:57:25 pm »
All you have to do is to normalize the (x, y) vector, ie. divide it by its length. Then multiply by your constant speed.
Laurent Gomila - SFML developer

TooFux

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: joystick axis
« Reply #2 on: June 06, 2012, 02:44:29 pm »
No, this is not what I want to get.

Maybe I was not precise enough in my question.

When I said "constant speed", I mean that speed in horizontal/vertical should be the same than in diagonal, but in a lot of games if we push the axis just a little the avatar moves more slowly. I want this behavior.

for exemple:
- if the input is (100, 0) I want to get (1.0, 0.0)
- if the input is (20, 0) I want to get (0.2, 0.0)
- if the input is (100, 100) I want to get (cos (pi/4), sin (pi/4))  => (0.7071, 0.7071)
- if the input is (20, 20) I want to get (cos (pi/4), sin (pi/4)) / 5  =>  (0.14142, 0.14142)
« Last Edit: June 06, 2012, 02:49:12 pm by TooFux »

thePyro_13

  • Full Member
  • ***
  • Posts: 156
    • View Profile
Re: joystick axis
« Reply #3 on: June 06, 2012, 03:19:36 pm »
You can normalise it to get it's direction, as Laurent says.

Then you can calculate the length as a percentage of the maximum magnitude. Which you can then use for your speed value.

To get around the corner issue([100, 100]) just define the magnitude of [0, 100] as the maximum value and crimp any values above that back down to [0, 100]'s magnitude.

Then you have your speed as a value between the magnitude of [0, 0] and [0, 100].

This may not be the simplest or most efficient method, but it's what came to me first.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: joystick axis
« Reply #4 on: June 06, 2012, 03:22:11 pm »
Ok I see, sorry for answering too fast.

I have no idea if there is an easy/well-known formula to apply in this situation, but here is what I'd do.

You need two things:
- the angle
- the length

The angle is very easy to compute, with std::atan2(y, x).

The length is more complicated. You need to find the ratio between the current distance (to the center) and the maximum distance (to the center) that your joystick could go in the current direction. You might have to divide the square area into 8 parts to do this correctly. Once you have this ratio, multiply it by your maximum length and you get the current length to apply.

Example: if your joystick is at (50, 20) then the max point is (100, 40) and then the ratio is 0.5 (half speed). If you move up to (50, 100) then the max point becomes (50, 100) -- you cannot go further on the Y axis -- and the ratio is 1 (max speed).
« Last Edit: June 06, 2012, 03:25:41 pm by Laurent »
Laurent Gomila - SFML developer

TooFux

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: joystick axis
« Reply #5 on: June 08, 2012, 12:46:22 am »
Thanks!

I've written this code.
Maybe someone could comment if he/she see something that could be improved.
Otherwise it will perhaps be usefull for someone else :-)

#include <math.h>

sfVector2f sfJoystick_normaliseDirectionProportional(float x, float y)
{
#define VECTOR_LENGTH(x, y) \
  sqrtf(((x) * (x)) + ((y) * (y)))

    float angle, in_len, max_len, max_x, max_y, ratio, norm_x, norm_y;
    sfVector2f res;
    if (x == 0.f && y == 0.f) {
        res.x = 0.f;
        res.y = 0.f;
        return res;
    }
    angle = atan2f(y, x);
    in_len = VECTOR_LENGTH(x, y);
    if (fabsf(x) > fabsf(y)) {
        max_x = 100.f;
        max_y = max_x * y / x;
    } else {
        max_y = 100.f;
        max_x = max_y * x / y;
    }
    max_len = VECTOR_LENGTH(max_x, max_y);
    ratio = in_len / max_len;
    norm_x = cosf(angle);
    norm_y = sinf(angle);
    res.x = norm_x * ratio;
    res.y = norm_y * ratio;
    return res;
#undef VECTOR_LENGTH
}

TooFux

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: joystick axis
« Reply #6 on: June 08, 2012, 12:05:56 pm »
Hi,
It seems that the previous code can be simpilfied, this version seems to produce the same results without needing to calculate the angle. Here we save calling atan2, cos and sin:

sfVector2f
sfJoystick_normaliseDirectionProportional(float x, float y)
{
#define VECTOR_LENGTH(x, y) \
  sqrtf(((x) * (x)) + ((y) * (y)))

    float in_len, ratio;
    sfVector2f res;
    if (x == 0.f && y == 0.f) {
        res.x = 0.f;
        res.y = 0.f;
        return res;
    }
    in_len = VECTOR_LENGTH(x, y);
    if (fabsf(x) > fabsf(y))
        ratio = fabsf(x / 100.f) / in_len;
    else
        ratio = fabsf(y / 100.f) / in_len;
    res.x = x * ratio;
    res.y = y * ratio;
    return res;
#undef VECTOR_LENGTH
}

again please comment if you can :)
« Last Edit: June 08, 2012, 12:11:56 pm by TooFux »