GML Touch screen drag (multiple) objects.

jtmx

Member
Hello I am trying to create a menu for a touch screen device where the player drags the menu form left to right and it moves multiple objects (menu buttons) accordingly.

This is my code for each button:

obj_menu_button CREATE

Code:
global.drag_col_select = false;
mouse_xx = 0;
mouse_yy = 0;
mouse_xx_last = 0;
mouse_yy_last = 0;
mouse_xx_prev = 0;
mouse_yy_prev = 0;
obj_menu_button STEP

Code:
if device_mouse_check_button(0,mb_left)
and point_in_rectangle(device_mouse_x(0),device_mouse_y(0),x,y,x + 100,y + 100)
    {
        global.drag_col_select = true;
    }

if device_mouse_check_button_released(0,mb_left)
    {
        global.drag_col_select = false;
     
        mouse_xx_last = device_mouse_x(0);
        mouse_yy_last = device_mouse_y(0);
    };

if global.drag_col_select
    {
         mouse_xx_prev = mouse_xx;
         mouse_yy_prev = mouse_yy;
             
         mouse_xx = device_mouse_x(0);
         mouse_yy = device_mouse_y(0);
             
         if mouse_xx_last < mouse_xx_prev
         or mouse_xx_last > mouse_xx_prev
         x += lengthdir_x(point_distance(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy),point_direction(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy));
    };
The problem is that sometimes after dragging them the menu buttons overlap each other like this[1] and I was wondering if anybody could help fix my code.

[1]help.png
 
Last edited:

jo-thijs

Member
Hello I am trying to create a menu for a touch screen device where the player drags the menu form left to right and it moves multiple objects (menu buttons) accordingly.

This is my code for each button:

obj_menu_button CREATE

Code:
global.drag_col_select = false;
mouse_xx = 0;
mouse_yy = 0;
mouse_xx_last = 0;
mouse_yy_last = 0;
mouse_xx_prev = 0;
mouse_yy_prev = 0;
obj_menu_button STEP

Code:
if device_mouse_check_button(0,mb_left)
and point_in_rectangle(device_mouse_x(0),device_mouse_y(0),x,y,x + 100,y + 100)
    {
        global.drag_col_select = true;
    }

if device_mouse_check_button_released(0,mb_left)
    {
        global.drag_col_select = false;
    
        mouse_xx_last = device_mouse_x(0);
        mouse_yy_last = device_mouse_y(0);
    };

if global.drag_col_select
    {
         mouse_xx_prev = mouse_xx;
         mouse_yy_prev = mouse_yy;
            
         mouse_xx = device_mouse_x(0);
         mouse_yy = device_mouse_y(0);
            
         if mouse_xx_last < mouse_xx_prev
         or mouse_xx_last > mouse_xx_prev
         x += lengthdir_x(point_distance(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy),point_direction(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy));
    };
The problem is that sometimes after dragging them the menu buttons overlap each other like this[1] and I was wondering if anybody could help fix my code.

[1]View attachment 13228
The issue seems to be twofold.
On the one hand, you seem to confusing yourself with having drag_col_select be a global variable.
You set it to true if the mouse is hovering over the button when holding the mouse button
and you set it to false if the mouse button is released.
On the other hand, you're using more variables than necessary and you seem to be confusing their meanings.

What happens is that some buttons check if the mouse is hovering over them and see it's not the case.
They keep the global variable false and don't move.
Then another button performs the same check and sees that the mouse is indeed hovering over it.
It will set the global variable to true and will update the variables mouse_xx_last and mouse_yy_last.
Then it sets the variables mouse_xx_prev and mouse_yy_prev to mouse_xx and mouse_yy respectively.
However, since these variables were not updated yet, they contain the mouse position of where the user released the mouse button before.
Clearly, this causes mouse_xx_prev and mouse_yy_prev to have the wrong values.
Then it updates mouse_xx and mouse_yy to some correct values.
Finally, it moves itself based on mouse_xx_prev and mouse_xx.
All the remaining buttons do the same.
This causes some buttons to remaing at their positions while others make a sudden jump when you press the mouse button.

Afterwards, your code will work fine (ignoring your use of mouse_xx_last in the comparison) until you release the mouse button and then press it again.

Now, I first want to point out that you wrote:
Code:
         if mouse_xx_last < mouse_xx_prev
         or mouse_xx_last > mouse_xx_prev
         x += lengthdir_x(point_distance(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy),point_direction(mouse_xx_prev,mouse_yy_prev,mouse_xx,mouse_yy));
This can be shortened to this though:
Code:
if mouse_xx_last != mouse_xx_prev
    x += mouse_xx - mouse_xx_prev;
You can then even further shorten it by leaving away the condition, as it is superfluous.

Now, as for a solution to your problem,
you should first get rid of the variables mouse_yy, mouse_yy_prev, mouse_xx_last and mouse_yy_last.
They don't serve any purpose and thus can only cause trouble (which they do).

This will leave you with as create event:
Code:
global.drag_col_select = false;
mouse_xx = 0;
mouse_xx_prev = 0;
and as step event:
Code:
if device_mouse_check_button(0,mb_left)
and point_in_rectangle(device_mouse_x(0),device_mouse_y(0),x,y,x + 100,y + 100)
    {
        global.drag_col_select = true;
    }

if device_mouse_check_button_released(0,mb_left)
    {
        global.drag_col_select = false;
    
        mouse_xx = device_mouse_x(0);
    };

if global.drag_col_select
    {
         mouse_xx_prev = mouse_xx;
        
         mouse_xx = device_mouse_x(0);
            
         x += mouse_xx - mouse_xx_prev;
    };
Now you should either manage the global variable in a different event
or even better, in a controller object.

In the former case you would cut the step event down to:
Code:
if global.drag_col_select
    {
         mouse_xx_prev = mouse_xx;
        
         mouse_xx = device_mouse_x(0);
            
         x += mouse_xx - mouse_xx_prev;
    };
and put this part in the create event:
Code:
if device_mouse_check_button(0,mb_left)
and point_in_rectangle(device_mouse_x(0),device_mouse_y(0),x,y,x + 100,y + 100)
    {
        global.drag_col_select = true;
    }

if device_mouse_check_button_released(0,mb_left)
    {
        global.drag_col_select = false;
    
        mouse_xx = device_mouse_x(0);
    };
In the latter case, you would create a controller object, which is an object with no sprite
that is put in every room with these buttons.

You would then make the controller object calculate the value of the global variable
and you would let the button objects only look at the global variable to know if they sould be moving.

That all being said, I don't quite understand why you are moving the button objects rather than just moving the view/camera.
Is it because you've got some background or title object that you're trying to keep stationary?
 
Top