Legacy GM Drag only one object at a time

D

danny2014

Guest
Hello,

I am developing a game where you have to drag objects around, So in a room i have multiple objects (obj_1, obj_2, obj_3) with this events :

Create Event:
execute code:

selected = false;
global.canSelect = true;

Step Event:
execute code:

if (selected) {
global.canSelect = false;
x = mouse_x;
y = mouse_y;
}

Mouse Event for Left Button:
execute code:

if (global.canSelect)
selected = true;

Mouse Event for Glob Left Released:
execute code:

selected=false;
global.canSelect = true;

I have to say, i didn't write this code, i saw it in a tutorial, the problem is when i drag obj_1 and i drop this object on top of obj_2 then when i try to drag again obj_1 it will also drag obj_2, i want to be able to drag only obj_1, any help will be appreciated.

Thank you.
 
J

Joey2bost

Guest
try
if mouse click and if mouse realse coding to move it. also have it when mouse click say x = mouse_x along with y
 

jazzzar

Member
So, there's a thing called depth, if you use depths, you can easily pick up the one with the lowest depth as it will show in top of every other object
 
D

danny2014

Guest
Well, i was being honest, the code is not mine, i tried to understand the code and changed it a little bit but nothing worked.
Thank you Joey2bost and jazzzar for the help, the depth solution didn't worked, i put different depth values for obj_1, obj_2 and obj_3 in left button event and a depth value of zero in left released event. Let's see if i can make it work using if mouse click and if mouse released coding.

Thank you.
 

jazzzar

Member
Well, i was being honest, the code is not mine, i tried to understand the code and changed it a little bit but nothing worked.
Thank you Joey2bost and jazzzar for the help, the depth solution didn't worked, i put different depth values for obj_1, obj_2 and obj_3 in left button event and a depth value of zero in left released event. Let's see if i can make it work using if mouse click and if mouse released coding.

Thank you.
Changing depths isn't the only thing you need to do, you need to code things!!!
First when you click you need to check if there's two or more instances overlapping, if there is, pick the one with the lower depth, you can refer to an object'd depth like so : obj1.depth, obj2.depth, if you want upload the project somewhere and i'll do it for you tomorrow
 
D

danny2014

Guest
I tried to use your idea but i guess i have a lot to learn, i am a beginner. You can download the project here

Thank you for helping me!
 

Yal

šŸ§ *penguin noises*
GMC Elder
Wouldn't say that telling others to fix it is the best way to learn things.

One idea from the top of my head: have a global 'is dragging something' state (a true/false variable, for instance), and only allow starting a drag when it's false; set the variable to true when a drag starts and to false again when it ends.
 

FrostyCat

Redemption Seeker
You need to set global.canSelect to false right away in the Left Button event. If you don't do this, it's possible for multiple instances to satisfy the condition, and the Step event won't come around soon enough to stop all of them from being selected.

Let this be a lesson to you that tutorials should not be trusted with blind faith, especially when way too many of them are written by crappy wannabes who bother more with YouTube publicity than proper code.
 
D

danny2014

Guest
You need to set global.canSelect to false right away in the Left Button event. If you don't do this, it's possible for multiple instances to satisfy the condition, and the Step event won't come around soon enough to stop all of them from being selected.
I did it and now you can only drag an object once, if you place it somewhere in the room and then try to drag it again it won't move. I hope i didn't make any mistakes. Thank you anyway. Good advice.
 
D

danny2014

Guest
For those who will read my post in the future, i still don't know how to drag only one object at a time but to prevent obj_1 to be placed on top of obj_2 or obj_3 i use a collision event between obj_1 and obj_2 for example and i put jump to position action or jump to start action for the object dragged. Jump to position action creates a little bit of lag
 
S

salanmh3

Guest
Hi danny2014, I know it is too late but I was working on something in GM and ended to same situation as yours. So after some tweaks, here is solution I made that worked for me. Hope it will help.

Like you, I have multiple different objects but they all belong to same parent (named 'oBlock') as they behave similarly in regards to drag and selection functions.

In main 'Room' Creation event, we define some global variables:
Code:
global.CanGrab = true;
global.LastDepth = 0;

In 'oBlock' Creation event:
Code:
depth = 1; //At the beginning, all 'oBlock' objects have depth 1
Selected = false;
Grabbed = false;

In 'oBlock' Begin_Step event, we monitor if the left mouse button is pressed and select the lowest depth oBlock objects in case there are multiple oBlock(s) at mouse position:
Code:
if mouse_check_button_pressed(mb_left) { //Monitor if mouse left button is pressed
    var LowestDepthID = instance_position(mouse_x,mouse_y,oBlock); //Get any oBlock object at mouse position
    if(LowestDepthID != noone) { //If there is no oBlock object at mouse position, we do nothing, so we keep our previous selected oBlock active. Otherwise, we execute below code.
        with(oBlock) { //This 'with' block will go through all oBlock objects
            if(position_meeting(mouse_x,mouse_y,id)) { //Check if any other oBlock object is also at mouse position               
                if(depth < LowestDepthID.depth) { //If so, check its depth so that LowestDepthID will be the lowest depth oBlcok object.
                    LowestDepthID = id;
                }
            }
            
            id.Selected = false; //This will ensure that all oBlock objects are not selected because we already found one from above
        }   
    
        LowestDepthID.Selected = true; //Here we make the lowest depth oBlock object to be Selected
        LowestDepthID.depth = global.LastDepth; //We lower the depth of that object even further, so it will be the selected one next time if the object is overlapped with others.
        global.LastDepth -= 0.1; //Here we lower the global LastDepth for next time an oBlock object is selected. Note: To consider in the future to fix when 'depth' reaches -1000 (min limit for 'depth').
    }
}

In 'oBlock' Left_Mouse_Button_Pressed event:
Code:
if (global.CanGrab and Selected) { //We set here the oBlock object to be Grabbed only in case if it is Selected and global CanGrab is true
    Grabbed = true;
    
    //This is to setup coordinates for the drag function
    mx = x - mouse_x;
    my = y - mouse_y;
}

In 'oBlock' Step event:
Code:
if (Grabbed and Selected) { //We allow the object to be dragged only in case if it is Selected and Grabbed, so only one object can be dragged at one time.
    global.CanGrab = false; //Here we won't allow any other object to be grabbed since we have one already being grabbed

    //This is for the drag function so that the object will follow the mouse
    x = mouse_x + mx;
    y = mouse_y + my;
}

Finally, in the 'oBlock' End_Step event:
Code:
if mouse_check_button_released(mb_left) { //Monitor if the mouse left button is released
    Grabbed = false; //The object will not be Grabbed anymore
    global.CanGrab = true; //Global CanGrab is back to true so we can allow the next selected object to be grabbed
}

PS: I am new to GM, so perhaps my code is not optimized.
 
Top