Drag and drop system with objects replacement

Hello everyone,
I’m quite new to gdevelop and am playing around with its great functionnalities, creating a drag and drop puzzle game.

I’ve been struggling for a few days now trying to create a drag and drop system with objects interacting between them depending on their position. It is quite easy to illustrate with a well known game: A little to the left, and more precisely this level:

As you see in this exemple, when a jar is dragged and interacts with another jar, the other jar moves automatically left or right depending on where is the dragged jar being dragged.

I’ve been playing around with object variables, tween positions, target objects and many other potential solutions, also tried the AI tool, but I cannot find anything working properly.

Would you guys have any idea of what would be the best way to code that?

Thanks a lot :slight_smile:

1 Like

im a bit tired - but i think you only really need one jar object with different animations and an object number var ‘id’. Create a coll box object same size as the jar and number that with same id and put it on the right jar and hide it.
then do something like this …
use a repeat for each jar event
pick all coll box
point jarX(),jarY() inside object coll box
id of jar not equal to id coll box = swap them over using the position of the coll box where it was dragged from and swap the animations. you can have an animation no var and swap it that way. when swapping you’ll need to copy the animation number to a scene var.
sorry that’s garbled but it might work

Hi Davedorkmouse,
thanks a lot for taking the time to answer!
Not sure I understand 100% this part: “you can have an animation no var and swap it that way” / when swapping you’ll need to copy the animation number to a scene var.

Also, given that I’d like to create similar levels with objects of different size, I’d like being able to manage it with different objects packed in group objects.

sorry - it was a bit tired and garbled that!
there’s no need for’repeat for each object’ or pick all’ up there within my rambling response.
“you can have an animation no var and swap it that way” / when swapping you’ll need to copy the animation number to a scene var .
what a ridiculous sentence to throw at someone! - i think what i meant was that you can just change the animation rather swap the jars over - store the ani number of jar1 in a scene var, give it the ani number of the jar2, and then change the ani of jar2 to the scene var.
i think id create them at the start with a repeat event. - easy to number them that way.
you can have different sizes if using ‘point inside object’ just change the scale or width/height of the collision box object.
yes you could use an object group - i think id need to actually do it to wrap my head around it any further
all the best with it …and sorry to have muddied the water

Hi again and thanks for taking the time to complete and reexplain your first answer !
I still don’t quite understand how animations are supposed to help or be swapped. In the example given, jars being dragged can be placed at the spot of other jars and shouldn’t change animation or sprite. Or maybe I’m missing something ?
I will try playing around with the repeat event, and maybe arrays?
This is typically the kind of mechanism that looks quite easy to implement at first glance, but happen to be muuuuch more complicated (at least for begninners like my self :face_with_peeking_eye:)

there’s a few different ways to do it. you can literally move the jars about or just change the animation. Yes write their ids or animation index to an array and compare that to the desired outcome once one has been dragged.
have a go and post your events - You tend to get more assistance on here if you post a pic of your events as there’s always more than one way to do things as the forum users generally like to look for inconsistencies in logic rather than think about the many ways that things can be done.

1 Like


i was thinking along these lines - it kinda works but needs more work - but id best get on with the things im supposed to be doing!

2 Likes

btw - i had the origin and center of box jar and coll box at the bottom and point “ch” in the middle

1 Like

Hi again mate. You’re a true hero!
I’m not home and cannot try this yet but it seems quite promising. Just to be sure about one thing: the origin and center points were positioned at the bottom center, right?
Thanks again for taking the time to help me on this, gdevelop hero :grin:

1 Like

And yeah I’ll try things out based on what you suggested and post it here anyway, should it be for asking for help again or for proposing a fully working and polished solution. :v:

1 Like

Don’t feel that you have to do it as i did it as there’s a few other ways but that’s what came to my mind. The points are at the bottom apart from the check point so that you can have animations that are different sizes within the same object and they stay on the table. I twiddled it after posting an turned the draggable behaviour off when you switch and tweened the jar back into position instead of changing its position - when the tween ends turn draggable object back on.

I got this solution:

TileShuffle


using these events:

[edit] - ha! I just realised it’s along the same lines as @Davedorkmouse’s solution

Please note, changing the tint of the Target object as part of my debugging process to indicate which targets are free. You’d be better off hiding the Target objects after they’ve been created.

And the 108 in the raycast is because there’s a gap of 108 pixels between the draggables.


Draggable object group:


One of the draggable objects collision mask:

The draggable object behaviours:


I’m bound to have omitted some details. Ask if there’s anything you’re not sure about.

3 Likes

Hi Mrmen, thanks a lot for the very extensive solution and for taking the time to create and share the events. Can’t wait to be back home to try this out and share my results !

Hi Mrmen,

I finally managed to work on my project and took the opportunity to basically copy-paste your code and adapt it to my scene :slight_smile: .



Unfortunately, it is currently not working as intended. When dragging a can to another position, 1) the other cans don’t move and 2) the TargetX position remains 120, which is equal to the position of the first Can (Draggable).

After quite a while debugging, it seems that the issue comes from the raycast line.
image
When removing it, the cans tween correctly, but are always moved towards X=120, targetX being stuck to Can1 X position.

I really don’t understand why the targetX position doesn’t adapt to the Can being dragged… also, I have no idea why the raycast line doesn’t enable the tween to activate properly…

Lots of questions :grin:

I’ll try recreating everything from scratch to try to understand where the issue comes from.

I’ll keep you posted!

Hi again,
I finally created the scene again and removed everything that wasn’t coming from your events proposition. Unfortunately, the problems remain :frowning:



I still think the issue is located here:

But have no idea how to solve it and quite surprised it works for you and not for me :melting_face:

Aaaaaand me again. Should be sleeping already but cannot stop trying to solve this issue :smiley:

I got rid of the raycast line and things seem to be working almost fine now.

Some issues: if dragging a can a bit too fast over other cans, swap won’t happen… also, for some reasons, after a while cans stop swapping and teleport to X=120 (first can’s position). Which makes sense, target.X remaining 120 for some reasons…

Gonna go sleep before going crazy :slight_smile:

Your issue is that I forgot to mention I moved the origin point of Cans to the centre of the object :person_facepalming: - a small but very significant oversight, sorry. This will make a huge difference to the raycast, because raycasting from the top left of the Cans object will not hit a Target object.


Put back the raycast and change the origin point. It should fix the original issue.


Your TargetX text is always 120 because in there is no condition specifying which Target to use, so GDevelop will use the first one created on the scene. It so happens to be the one at X=120

Idealy if you want to debug it, set the text when you select the text object - like when the Target.isFilled is set to false.

1 Like

Oh god, obviously… it’s working now, thank you so much! Now I understand better how raycasts work.

The only remaining “issue” is that when dragging cans too quickly over other cans, the “move” tween has not time to play until the end and causes other swap animations to not trigger. This could be sort of solved by setting up the move tween to be much quicker, but I’d ideally like to keep it smooth and not less than 0.2 seconds.

Maybe I’ll find some inspiration on how to fix that in Davedorkmouse answers - that will be my task for tonight :slight_smile:

If you guys have any hint or idea, feel free to share.

Once again thank you so much for your help. Being new to gdev, it feels good to know that there’s a community of great people ready to help newcomers.

1 Like

Hi guys,
coming back to you after a few hours of try and error. I’ve tried to simplify the code and this version seems to work quite fine.

The only remaining issue is the mouse speed : when draggables are moved too quickly and colide with multiple draggables one after the other, the swap will not happen. I thought first it came from the tween playing and the associated boolean variables set as conditions, but removing them didn’t actually help (or just a bit).

Are quick mouse moves difficult to detect for the engine, leading to collisions being ignored?

I’ve tried to create a custom drag and drop system to slower the cursor speed, but it came out to be a little bit to complex for me.

If you have any tip on how to overcome this issue, either by slowing down the mouse or by making sure actions happen even in case of quick move, please let me know !

Bye and enjoy the weekend :v:

My thoughts on how to deal with the mouse moving too fast is to keep track of the last position of the dragged can, and move any cans that have no active tween between that position and the current position.


To get the cans moving in the right order, select cans that have no "Move" tween and raycast from the previous point to the current point. It'll give the can closest to the drag start that meets the conditions. You'll probably have to repeat this until the only can hit is the one being dragged.

If you do implement this, you’ll have to add an event that removes the “Move” tween when it’s finished.