GML Help with right-stick in twin-stick shooter

B

Buttonsinker

Guest
Hi everybody, I'm having a bit of trouble with the behaviour of my right stick, which aims in my twin-stick shooter. It work great with keyboard & mouse, where the mouse points the direction to shoot. But I've been starting to implement gamepad controls instead and so far everything works except for the right-stick for aiming as replacement to the mouse.

I have two main issues:

1. Once I stop pushing the right-stick on a specific direction, the aim goes back to aiming right. I want it to stay in the direction I last pushed my right-stick to.

2. There is no smooth diagonal movement on the right-stick. It feels like it always snaps to 90, 180, 270 or 360. It can do diagonals but it's clunky .

The first issue is the one that is the most annoying so far. I'm trying to make my weapon aim like in Geometry Wars or Awesomenauts.

Do you have any suggestions on this matter?

So far this is my controls for the right-stick on my gamepad
Code:
var hraxis = gamepad_axis_value(0, gp_axisrh);
var vraxis = gamepad_axis_value(0, gp_axisrv);
image_angle = point_direction(0, 0, hraxis,vraxis);
 
Last edited by a moderator:
B

Bridget7298

Guest
Wouldn't the point direction code be like this instead?
Code:
image_angle = point_direction(x , y, hraxis,vraxis);
 
Wouldn't the point direction code be like this instead?
No, it's the values are already relative to 0.

@Buttonsinker Have you set a deadzone for your gamepad?

You need to put a check in your code before you set the image_angle.

You should only be updating the image_angle if the absolute value of either axis is greater than 0.

As you have it now, if the player is not moving the stick, your point_direction() code is still being executed, thereby resetting the image_angle even if the player is not moving the stick.
 

obscene

Member
If I were doing this I think I'd get the point_distance() from 0,0 to the axis coordinate (1,-1 for top right for example). If that distance was less than .75 I wouldn't update the aim position. Possibly even higher.

To smooth the movement out you might just use lerp(), example... aim=lerp(aim,aim_value_from_stick,0.25); You'll also need to work angle_difference() in there, you'll see when when you try it.
 
B

Buttonsinker

Guest
@IndianaBones Thank you very much mate, your suggestion of "putting a check before setting my image angle" gave me the idea for a new line of code which follows.

Code:
var hraxis = gamepad_axis_value(0, gp_axisrh);
var vraxis = gamepad_axis_value(0, gp_axisrv);

if gamepad_axis_value(0, gp_axisrh) != 0
{
image_angle = point_direction(0, 0, hraxis,vraxis);
}
That if statement made the whole difference. Now my image_angle only updates if my right-stick is moved.
And yes I did put a 0.3 deadzone value on the create event of my player object. But is there a way to set a different deadzone value per joystck. Because gamepad_set_axis_deadzone() seems to affect both sticks.

Now I just need to make that angle change more smoothly. I'm guessing the answer to that problem lies in the line "point_direction(0, 0, hraxis,vraxis)".

I still have a few other problems but I'm making quite good progress for somebody who got a GMS licence from Humble Bundle last friday and never coded anything before. Youtube tutorials help a lot but real knowledge is definitely here. Thanks so much for the help, it is greatly appreciated.
 

obscene

Member
@IndianaBones Thank you very much mate, your suggestion of "putting a check before setting my image angle" gave me the idea for a new line of code which follows.

Code:
var hraxis = gamepad_axis_value(0, gp_axisrh);
var vraxis = gamepad_axis_value(0, gp_axisrv);

if gamepad_axis_value(0, gp_axisrh) != 0
{
image_angle = point_direction(0, 0, hraxis,vraxis);
}
That if statement made the whole difference. Now my image_angle only updates if my right-stick is moved.
And yes I did put a 0.3 deadzone value on the create event of my player object. But is there a way to set a different deadzone value per joystck. Because gamepad_set_axis_deadzone() seems to affect both sticks.

Now I just need to make that angle change more smoothly. I'm guessing the answer to that problem lies in the line "point_direction(0, 0, hraxis,vraxis)".

I still have a few other problems but I'm making quite good progress for somebody who got a GMS licence from Humble Bundle last friday and never coded anything before. Youtube tutorials help a lot but real knowledge is definitely here. Thanks so much for the help, it is greatly appreciated.
You can use the method I described with point_distance to make your own deadzone. Of course any value under the actual deadzone will be cut off, but you can create a larger one easily by just checking for a larger distance.
 
B

Buttonsinker

Guest
@obscene I'm still trial and error that method, hopefully I'll make it work the way I want it too. Thanks
 
B

Buttonsinker

Guest
@obscene I've been trying to understand how I could implement that lerp() function today, which seems pretty interesting. But I've not manage to understand how I could use it. Since I have no background in coding, I have a harder time connecting the dots, and this one is one that is still puzzling me. If you have some time, could you explain to me a bit more how I could use lerp(). Thanks.
 
lerp stands for Linear Interpolation.

Take any two numeric values. Lets say 10 and 100.

Linear Interpolation "maps" these values from 10-100 to the range 0-1

So if I specify a "lerp" value of 1, this will return the maximum value (100)

If I specify a "lerp" value of 0, this will return the minimum value (10)

A "lerp" value of 0.5 would be halfway between the two, which is (55)

Say I wanted to move an object from position (45, 45) to (166, 273) over the time of 3 seconds

I could do it manually which would take a bit of maths to add the correct amount of x and y per game step.

Or I could use lerp, I increase the lerp value from 0 to 1 over the time of 3 seconds, and lerp will give me the correct x and y values every step without me having to worry about it.

Create Event
Code:
x_start = 45
x_end = 166
y_start = 45
y_end = 273

lerp_value = 0
// lerp_speed calulates how much to increase the lerp_value each step
// so that it goes from 0 to 1 over the time of 3 seconds
lerp_speed = 1 / (room_speed * 3)
Step Event
Code:
lerp_value += lerp_speed
if ( lerp_value > 1 )
{
    lerp_value = 1 //(this stops the x and y values from increasing once I've reached the target value)
}
x = lerp(x_start, x_end, lerp_value)
y = lerp(y_start, y_end, lerp_value)
 

obscene

Member
Basically, lerp will allow you to smoothly transition one value to another. It works like this...

x = lerp(x,100,.1);

That would take x 1/10 of the way from whatever value it is to 100 each step. The first step it would move 10 pixels, the second step it would move 9 pixels (90 * .1), the second step it would move 8.9 pixels (89*.1) etc. So basically the closer it gets to the destination the slower and smoother it moves.

You could use it by getting the angle from the gun to the mouse or stick, but instead of just aiming there you would lerp to it.

gun_angle = lerp (gun_angle , destination_angle, .1) ;

So if the gun was pointing at 0 and you quickly pointed the stick up, the gun would transition frame by frame like this.... 0, 10, 19, 27,34, etc until it finally get to 89.99 and then rounds to 90. It would take about a second, so you could change .1 to something higher to make the transition faster until you think it feels right.

This is an old test video I did when I put the same effect into my aiming.

This is my code.

aim=lerp(aim,set_aim,.35);

There is more to it, but I use Spine so mine will be different from yours no doubt. The big problem you will run into is if you transition across the 0 line. For instance if you are aiming down right (315) and then aim up right (45). Instead of transitioning straight up it would want to lerp clockwise from 315 to 45. So you have to do some figuring, for example converting values like 315 to -45 ( 360-315) *-1

EDIT: Ninja'd!!
 
Last edited:
Top