• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!

GMS 2 How to Move Object Using Virtual Joystick

Hello, I have a D-Pad style Object I made to move the Player Object around in top down style movement, but I noticed that it's not really efficient, seeing it's made of 4 objects with collision masks overlapping each other and causing some odd movement.

How could I make it where I can move the object using a "virtual joystick"? Example, where there's a smaller circle you "touch" and a bigger circle restricts it's movement to that circle's boundaries and that moves the Player Object around and depending on how far the small circle is from the center of the big circle the Player Object's speed changes?
 
Howdy!

I just whipped up a little example to build what you want. I'll explain everything here and then link to the original example. I'll just walk through exactly what I did.

STEP 1: CREATE A SPRITE FOR THE BASE OF THE VIRTUAL STICK AND THE ACTUAL STICK
(Or however you want to make the sticks.)
Here's what I did for the purposes of this tutorial:
spr_stickBase_0.png spr_Stick_0.png
The bigger is the base, the smaller is the actual stick.

STEP 2: CREATE AN OBJECT FOR THE STICK
Make it visible and make its depth greater than everything in the game.

STEP 3: CODE IT
Now for some code. Make a create event. Make a code block. In here we need to initialize some stuff.
Code:
xx = 0; //The X anchor point for the stick (We will reset this in STEP)
yy = 0; //The Y anchor point for the stick (We will reset this in STEP)
max_dist = 75; //The distance of the range of circular motion on the stick
was_clicked = true; //A simple variable where you store input
globalvar gamepad_stick_value_x; //The final X-axis output
gamepad_stick_value_x = 0;
globalvar gamepad_stick_value_y; //The final Y-axis output
gamepad_stick_value_y = 0;
Make a begin step event. Make a code block. In here is our whole stick code:
Code:
dist = point_distance(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)); //Get the distance from the mouse to the anchor
xx = 100; //The X anchor point for the stick
yy = 100; //The Y anchor point for the stick
if (device_mouse_check_button(0,mb_left)) //Test for a click
{
    if (dist < max_dist) //Test if the click happened inside the range of the stick
    was_clicked = true; //Set input to true
}
else //Click released
{
    was_clicked = false; //Set input to false
}
if (was_clicked == true) //Test input
{
    if (dist < max_dist) //If the mouse is inside the max distance assign it to the mouse position
    {
    x = device_mouse_x_to_gui(0);
    y = device_mouse_y_to_gui(0);
    }
    else //If the mouse is outside the max distance assign the stick position pointing to the mouse but to the max distance from the center of the axis
    {
    x = xx + lengthdir_x(max_dist,point_direction(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)));
    y = yy + lengthdir_y(max_dist,point_direction(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)));
    }
}
else //If no input set the stick's position to the anchor point
{
    x = xx;
    y = yy;
}
//Output the position the same way Gamemaker outputs a joystick's input
gamepad_stick_value_x = -1*(xx - x)/(max_dist); //This gives you the hor position of the stick from -1 to 1;
gamepad_stick_value_y = -1*(yy - y)/(max_dist); //This gives you the ver position of the stick from -1 to 1;
Make a Draw GUI Begin event. Make a code block. In here is our draw stick code:
Code:
draw_sprite(spr_stickBase,0,xx,yy); //Draw the base to the anchor point
draw_sprite(spr_Stick,0,x,y); //Draw the stick to the position
draw_text(10,10,gamepad_stick_value_x); //Draw the x output for testing purposes
draw_text(10,20,gamepad_stick_value_y); //Draw the y output for testing purposes
Finally to keep the stick from doing its automatic Draw Self (since we only want it to draw to the GUI layer) add a draw event. In that draw event, make a code block. In the code block put a random comment to indicate why you have an empty code block:
Code:
///OVERRIDE
The triple slash will make that comment appear on the code block in the DnD list.

And we're done! Now you have a working stick! Now to...
STEP 4: MAKE THE PLAYER MOVE ACCORDING TO THE STICK
For the purposes of this tutorial, I made a very basic player.

In the create event:
Code:
spd = 5;
In the step event:
Code:
x += gamepad_stick_value_x*spd; //Take the x axis value and multiply it by the speed
y += gamepad_stick_value_y*spd; //Take the y axis value and multiply it by the speed
Boom! Done. There is your basic idea. You'll need to tweak it to make the drawing and positioning of the stick work for your game.

Hope this helps!
~Gravityhamster

LINK TO PROJECT: https://www.dropbox.com/s/g0p2rg1pes5jwwh/V-Stick.gmz?dl=0 (My project is for GMS1, but you should be able to import it)

EDIT: UPDATED FOR GUI LAYER

EDIT: FIXED DRAWING TO THE ROOM AND THE GUI
 
Last edited:
Howdy!

I just whipped up a little example to build what you want. I'll explain everything here and then link to the original example. I'll just walk through exactly what I did.

STEP 1: CREATE A SPRITE FOR THE BASE OF THE VIRTUAL STICK AND THE ACTUAL STICK
(Or however you want to make the sticks.)
Here's what I did for the purposes of this tutorial:
View attachment 25976 View attachment 25977
The bigger is the base, the smaller is the actual stick.

STEP 2: CREATE AN OBJECT FOR THE STICK
Make it visible and make its depth greater than everything in the game.

STEP 3: CODE IT
Now for some code. Make a create event. Make a code block. In here we need to initialize some stuff.
Code:
xx = 0; //The X anchor point for the stick (We will reset this in STEP)
yy = 0; //The Y anchor point for the stick (We will reset this in STEP)
max_dist = 75; //The distance of the range of circular motion on the stick
was_clicked = true; //A simple variable where you store input
globalvar gamepad_stick_value_x; //The final X-axis output
gamepad_stick_value_x = 0;
globalvar gamepad_stick_value_y; //The final Y-axis output
gamepad_stick_value_y = 0;
Make a begin step event. Make a code block. In here is our whole stick code:
Code:
dist = point_distance(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)); //Get the distance from the mouse to the anchor
xx = 100; //The X anchor point for the stick
yy = 100; //The Y anchor point for the stick
if (device_mouse_check_button(0,mb_left)) //Test for a click
{
    if (dist < max_dist) //Test if the click happened inside the range of the stick
    was_clicked = true; //Set input to true
}
else //Click released
{
    was_clicked = false; //Set input to false
}
if (was_clicked == true) //Test input
{
    if (dist < max_dist) //If the mouse is inside the max distance assign it to the mouse position
    {
    x = device_mouse_x_to_gui(0);
    y = device_mouse_y_to_gui(0);
    }
    else //If the mouse is outside the max distance assign the stick position pointing to the mouse but to the max distance from the center of the axis
    {
    x = xx + lengthdir_x(max_dist,point_direction(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)));
    y = yy + lengthdir_y(max_dist,point_direction(xx,yy,device_mouse_x_to_gui(0),device_mouse_y_to_gui(0)));
    }
}
else //If no input set the stick's position to the anchor point
{
    x = xx;
    y = yy;
}
//Output the position the same way Gamemaker outputs a joystick's input
gamepad_stick_value_x = -1*(xx - x)/(max_dist); //This gives you the hor position of the stick from -1 to 1;
gamepad_stick_value_y = -1*(yy - y)/(max_dist); //This gives you the ver position of the stick from -1 to 1;
Make a Draw GUI Begin event. Make a code block. In here is our draw stick code:
Code:
draw_sprite(spr_stickBase,0,xx,yy); //Draw the base to the anchor point
draw_sprite(spr_Stick,0,x,y); //Draw the stick to the position
draw_text(10,10,gamepad_stick_value_x); //Draw the x output for testing purposes
draw_text(10,20,gamepad_stick_value_y); //Draw the y output for testing purposes
And we're done! Now you have a working stick! Now to...
STEP 4: MAKE THE PLAYER MOVE ACCORDING TO THE STICK
For the purposes of this tutorial, I made a very basic player.

In the create event:
Code:
spd = 5;
In the step event:
Code:
x += gamepad_stick_value_x*spd; //Take the x axis value and multiply it by the speed
y += gamepad_stick_value_y*spd; //Take the y axis value and multiply it by the speed
Boom! Done. There is your basic idea. You'll need to tweak it to make the drawing and positioning of the stick work for your game.

Hope this helps!
~Gravityhamster

LINK TO PROJECT: https://www.dropbox.com/s/g0p2rg1pes5jwwh/V-Stick.gmz?dl=0 (My project is for GMS1, but you should be able to import it)

EDIT: UPDATED FOR GUI LAYER
Thanks for taking the time to reply, but since these are two different versions of GameMaker, I think there's some incompatibility.
By following your code, I can create the joystick and move it, but when I add the movement code to the player object the movement is a little jerky and sometimes cuts out until I click the joystick again.

Also, with this code I changed it to match GameMaker Studio 2
In the step event:
Code:
x += o_small_circle.gamepad_stick_value_x*speed_; //Take the x axis value and multiply it by the speed
y += o_small_circle.gamepad_stick_value_y*speed_; //Take the y axis value and multiply it by the speed
and I put the joystick code in a Step event instead of a Begin Step Event.

Any ideas what could be causing the jerky movement? or Does anyone with GameMaker Studio 2 know what's going on?
 
Last edited:
Thanks for taking the time to reply, but since these are two different versions of GameMaker, I think there's some incompatibility.
By following your code, I can create the joystick and move it, but when I add the movement code to the player object the movement is a little jerky and sometimes cuts out until I click the joystick again.

Also, with this code I changed it to match GameMaker Studio 2
In the step event:
Code:
x += o_small_circle.gamepad_stick_value_x*speed_; //Take the x axis value and multiply it by the speed
y += o_small_circle.gamepad_stick_value_y*speed_; //Take the y axis value and multiply it by the speed
and I put the joystick code in a Step event instead of a Begin Step Event.

Any ideas what could be causing the jerky movement? or Does anyone with GameMaker Studio 2 know what's going on?
Hmm... Could you post all the code events for the stick you made?

Also, did you draw the values that the stick outputs up at the top of the screen? When you take the stick to the axis edges (all the way straight to the right, left, top, and bottom), do the values consistently go to 1 and -1? Hopefully that makes sense...
 
Last edited:
Hmm... Could you post all the code events for the stick you made?

Also, did you draw the values that the stick outputs up at the top of the screen? When you take the stick to the axis edges (all the way straight to the right, left, top, and bottom), do the values consistently go to 1 and -1? Hopefully that makes sense...
I commented out some of the movement I had made for other input methods and friction and the joystick seems to work, but not with the other code I made. And for some reason, when running the game, the joystick is drawn again further up in a room. Do you know what could be causing that?
 
I commented out some of the movement I had made for other input methods and friction and the joystick seems to work, but not with the other code I made. And for some reason, when running the game, the joystick is drawn again further up in a room. Do you know what could be causing that?
Oops. Try adding a "Draw" event and just adding a code event with a comment in it. (I usually put ///OVERRIDE in it so it's clear that I'm overriding the draw function in my code) Pretty much your just disabling the automatic Draw event for the object since you want it to draw to the GUI instead. I dunno if this hack is the best way to stop that, but it's what I've always done.

Sorry for that mistake! Please let me know if everything works out and you have any other questions.
 
Last edited:
Top