• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

[ RESOLVED] - Drag Object With Mouse - Advanced Options ??

D

Diveyoc

Guest
Is it possible to write a code into a persistent controller object to perform drag and move operations on certain objects, without having to put code in every object's step event?

Let's say each draggable object has a variable in the create event like can_drag = true;

So if the mouse is hovering within a range over any object that has this variable in it's create event, you can left click to drag and move the object around?

I'm not concerned with the extra work entering the code. I'm just wondering if this would help use less memory by doing it this way.

Is this possible?
 

Carolusclen

Member
this can be done yes

what you need to do is have a controller object that manages the code for everything

then, when the mouse intercepts the object, store its ID in a variable on the controller

for example, i have an object for my mouse

Code:
object_id = instance_position(mouse_x,mouse_y,obj_mouse) // this will return the ID of the object that collides with the mouse at the mouses position
i dont have gm with me so my code may be a little wrong but hopefully this gives you an idea

once you have the ID, then you can say

Code:
if (mouse_check_button(mb_left))
{
    with (object_id) {drag code here or change the objects variable so that it follows the mouse or something}
}
if no one has answered this better than that by the time i get home later, i can do some scripts for you :)


EDIT: in saying all this, as long as you can get the ID of the object at the mouse, then you can use the WITH (ID) code to manipulate that objects code :)
 
D

Diveyoc

Guest
Cool thanks. I've never used the instance_position command. I'll check it out and see what I can string together.
 

Carolusclen

Member
Cool thanks. I've never used the instance_position command. I'll check it out and see what I can string together.
not a prob, there is also the instance_place code, but they arnt bad. Off the top of my head though I am not sure of another way to pull the ID of an object at the mouse
 
D

Diveyoc

Guest
I'm trying to think this through. For now I just tried something simple to see if I can move the object.
It doesn't really work. The object moved a couple times, but doesn't stay with the mouse.
This is all in my controller object step event.

Code:
object_id = instance_position(mouse_x,mouse_y,all)

if (mouse_check_button(mb_left))
{
    with (object_id)
        {
        x = mouse_x;
        y = mouse_y;
        } 
}
 
D

Diveyoc

Guest
Any other thoughts on this? It kind of works, but not very well. The object slips away from the mouse and doesn't really stay locked onto it.
I have a create event with grab = false;

and Step Event is this:
Code:
object_id = instance_position(mouse_x,mouse_y,all)

if (mouse_check_button_pressed(mb_left))
    {
    grab = true;
    }

if (mouse_check_button_released(mb_left))
    {
    grab = false;
    }

if (grab == false)
    {
    exit;
    }
    
else
    with (object_id)
    {
    x = mouse_x;
    y = mouse_y;
    }
 
A

Aura

Guest
Create:
Code:
dragging = false;
inst = noone;
mdx = -1;
mdy = -1;
Step:
Code:
if (dragging) {
   with (inst) {
      x = mouse_x + other.mdx;
      y = mouse_y + other.mdy;
   }
   if (!mouse_check_button(mb_left)) {
      dragging = false;
      inst = noone;
   }
}
else {
   if (mouse_check_button_pressed(mb_left)) {
      inst = instance_position(mouse_x, mouse_y, all);
      if (inst != noone) {
         dragging = true;
         mdx = inst.x - mouse_x;
         mdy = inst.y - mouse_y;
      }
   }
}
 
Keep in mind too that the mouse cursor runs at a faster fps then your typical Studio game, so there is going to be some visible lag unless you disable the main cursor and program your own.
 
D

Diveyoc

Guest
Thanks Aura, I'll give this a try later today. One other question. Obviously I don't want the player to be able to drag and move every object in the game.
So, within the create event of my objects, is there a way I could use a variable to flag moveable objects like can_drag = true/false.
Then have this controller code also make reference to it? Something like this:
If can_drag = true (pick-up and move the object)
If can_drag = false (do nothing, or show message)
Is this doable?
 
D

Diveyoc

Guest
Keep in mind too that the mouse cursor runs at a faster fps then your typical Studio game, so there is going to be some visible lag unless you disable the main cursor and program your own.
Yes, I do have a custom cursor. I had an issue that I'm yet to solve because the custom cursor went behind my gui layers and gui buttons, where as I wanted it to show on top of everything. I tried changing depth and everything else, but could not get it to show on top of the gui layers.
In the short term, I have both the standard cursor and the custom cursor enabled so that I can see what I'm clicking on the gui layer.
But I did notice the lag in the custom cursor compared to the standard one.
 

Hyomoto

Member
The simplest way, typically, to get anything to draw on top of everything ( in my case I use it for a developer console ) is during either the draw_end step, or if that is used, the post-draw step. The mouse lag, however, won't likely be an issue if you turn off the other cursor since you'll be watching the one you are using instead. You can turn up your game speed however to combat that, as 60 fps should be a smooth enough experience, but it's one of those things you think is an issue when you can see it but will likely find it isn't since we're not talking waiting minutes here for the mouse, we just don't see it as smoothly follow it's path.
 
A

Aura

Guest
Since you're trying to make this as simple as possible, you can try using a list.

http://docs.yoyogames.com/source/dadiospice/002_reference/data structures/ds lists/index.html

Add all the object indexes that you want to take into account to the list in the Create event. Before dragging the instance, make sure that its object index exists in the list using ds_list_find_index().

Code:
if (ds_list_find_index(list, inst.object_index) != -1) {
   //Drag the instance
}
Edit: It would be better if you use that to set the dragging variable to true and mdx and mdy to their values instead of running the check every step while dragging an instance. But that's your choice.
 
D

Diveyoc

Guest
Still trying to sort this out.
One problem that I encountered is that this command doesn't seem to work like I thought it would:
inst = instance_position(mouse_x, mouse_y, all);
Using (all) or (other) just doesn't seem to work however, if I address an object directly like this:
inst = instance_position(mouse_x, mouse_y, obj_solar_panel);
The code works flawlessly. So, this is holding me up from trying to implement the ds_list.
I've entered the code like you stated, just in my own format that's easier for me to understand when I look at it.

Code:
if dragging = true
    {
    with (inst)
        {
        x = mouse_x + other.mdx;
        y = mouse_y + other.mdy;
        }
        if (!mouse_check_button(mb_left))
            {
            dragging = false;
            inst = noone;
            }
    }
else
    {
    if (mouse_check_button_pressed(mb_left))
        {
        inst = instance_position(mouse_x, mouse_y, obj_solar_panel);
        if (inst != noone)
            {
            dragging = true;
            mdx = inst.x - mouse_x;
            mdy = inst.y - mouse_y;
            }
        }
    }
I do have all of the variables drawing to the screen to help see what is going on. Here's what happens:

with - inst = instance_position(mouse_x, mouse_y, obj_solar_panel);
dragging = false; (Dragging turns from 0 to 1, so True/False is working)
inst = noone; (An instance # gets assigned 100124)
mdx = -1; (A value gets assigned, changes depending on cursor position)
mdy = -1; (A value gets assigned, changes depending on cursor position)

with - inst = instance_position(mouse_x, mouse_y, all);
dragging = false; (Dragging turns from 0 to 1, so True/False is working)
inst = noone; (An instance # gets assigned 100102)
mdx = -1; (A value does not get assigned, no change.)
mdy = -1; (A value does not get assigned, no change.)
 
D

Diveyoc

Guest
Ok, during some trial and error, I'm not sure what variation I was using, but I got an error on obj_cursor.
This made me realize that the problem with using inst = instance_position(mouse_x, mouse_y, all); was that my custom cursor "is" an object as well (easily forgotten)
So likely whenever I left clicked, it would always detect my custom cursor instead of the object beneath it.
For now, I removed my custom cursor and I can drag and move every object in the room, so I just need to figure out the ds_list portion to limit the objects that can be dragged around.
 
D

Diveyoc

Guest
Ok, so this works now. Do you think this code is good? Or would you change anything?

Code:
if dragging = true
    {
    with (inst)
        {
        x = mouse_x + other.mdx;
        y = mouse_y + other.mdy;
        }
        if (!mouse_check_button(mb_left))
            {
            dragging = false;
            inst = noone;
            }
    }
else
    {
    if (mouse_check_button_pressed(mb_left))
        {
        inst = instance_position(mouse_x, mouse_y, all);
        if (inst != noone) &&
        ds_list_find_index(drag_list, inst.object_index) != -1
            {
            dragging = true;
            mdx = inst.x - mouse_x;
            mdy = inst.y - mouse_y;
            }
        }
    }
 
M

montiedragon

Guest
I see that this is resolved but I figured I'd give an alternative method. You could create a parent object (par_dragable). Any draggable object would have that as a parent. Then in a control object, do something like this:

Create:

Code:
drag = noone;
Step

Code:
if (mouse_check_button_pressed(mb_left)){

    drag = instance_position( mouse_x, mouse_y, par_dragable );
    }
if (mouse_check_button_released(mb_left)){
    drag = noone;
    }
if (drag != noone){
    with (drag) {
        x = mouse_x;
        y = mouse_y;
        }
    }
 
Top