[SOLVED] Drag and Drop and multiple variables

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
Gigan
Regular
Posts: 28
Joined: Mon Jan 10, 2022 7:02 pm
Contact:

[SOLVED] Drag and Drop and multiple variables

#1 Post by Gigan »

Hello everyone ! I have a small problem with a drag and drop mini-game.

I have a screen where the player can put runes into different sockets. If they put those runes in the correct order, something happens.

Drag works and the pieces snaps correctly when dragged into a socket. Problem is, I can only get 1 variable working at the time. If I drag another rune to its correct socket, the first rune's variable gets back to False. :(

Code is a mash-up of several threads, so sorry about that. >__>

Right now, I'm trying to make it work with 2 runes.

Code: Select all

init python:
    def piece_dragged(drags, drop):
        global correct_position_1, correct_position_2
        correct_position_1 = False
        correct_position_2 = False
        global rune_1, rune_2, rune_3, rune_4, rune_5
        if not drop:
            return
        drag_name = drags[0].drag_name
        drop_name = drop.drag_name
        store.draggable = drag_name
        store.droppable = drop_name
        if drag_name == "rune_1" and (drop_name == "socle_1" or drop_name == "socle_2" or drop_name == "socle_3" or drop_name == "socle_4" or drop_name == "socle_5"):
            drags[0].snap(drop.x, drop.y, delay=0.1)
        elif drag_name == "rune_2" and (drop_name == "socle_1" or drop_name == "socle_2" or drop_name == "socle_3" or drop_name == "socle_4" or drop_name == "socle_5"):
            drags[0].snap(drop.x, drop.y, delay=0.1)
        if drag_name == "rune_1" and drop_name == "socle_1":
            correct_position_1 = True
        if drag_name == "rune_2" and drop_name == "socle_2":
            correct_position_2 = True
        if correct_position_1 and correct_position_2:
            return True

Code: Select all

screen forest_chaumiere_armoire():
    imagebutton: #Bouton retour
        focus_mask True
        xpos 20
        ypos 20
        idle "imagebutton_retour.png"
        action Jump("ruben_chaumière_int_2")
    draggroup:
        drag:
            drag_name "socle_1"
            xpos 0.15
            ypos 0.22
            child "imagebuttons/socle_rune.png"
            draggable False
            droppable True
        drag:
            drag_name "socle_2"
            xpos 0.29
            ypos 0.22
            child "imagebuttons/socle_rune.png"
            draggable False
            droppable True
        drag:
            drag_name "socle_3"
            xpos 0.43
            ypos 0.22
            child "imagebuttons/socle_rune.png"
            draggable False
            droppable True
        drag:
            drag_name "socle_4"
            xpos 0.57
            ypos 0.22
            child "imagebuttons/socle_rune.png"
            draggable False
            droppable True
        drag:
            drag_name "socle_5"
            xpos 0.71
            ypos 0.22
            child "imagebuttons/socle_rune.png"
            draggable False
            droppable True
        drag:
            drag_name "rune_1"
            xpos 300
            ypos 400
            child "imagebuttons/rune_1.png"
            draggable True
            droppable False
            dragged piece_dragged
            drag_raise True
        drag:
            drag_name "rune_2"
            xpos 500
            ypos 500
            child "imagebuttons/rune_2.png"
            draggable True
            droppable False
            dragged piece_dragged
            drag_raise True
Help plz 8__8
Last edited by Gigan on Sun Jul 30, 2023 5:13 am, edited 1 time in total.

philat
Eileen-Class Veteran
Posts: 1926
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Drag and Drop and multiple variables

#2 Post by philat »

Conceptually, the way I've handled this in the past is using a list or other data structure for setting the order + handling whether that order is correct separately.

Code: Select all

init python:
    runes_list = [None] * 5

    def piece_dragged(drags, drop):
        global runes_list
        drag_name = drags[0].drag_name
        drop_name = drop.drag_name

        if not drop:
            return

        runes_list[drop.name] = drag_name 
        # this particular implementation assumes your drops have drag_names as integers (which can be used as indices) for the sake of iterability, but you can always write it out long-hand if this confuses you 

        # Example:
        # drag:
        #     drag_name 0 # rather than "socle_1"
        #     xpos 0.15
        #     ypos 0.22
        #     child "imagebuttons/socle_rune.png"
        #     draggable False
        #     droppable True
Using the above, after dragging two runes to sockets 1 and 2, runes_list would be ["rune_1", "rune_2", None, None, None] - which could then be checked against an answer list (e.g., if runes_list == ["rune_2", "rune_1", None, None, None] then do something, otherwise ignore, etc.)

Further details you will likely need to implement: What happens if the socket is already full? Can the player drag a rune out of a socket to another socket - how will you handle resetting the previous socket to empty?

User avatar
m_from_space
Eileen-Class Veteran
Posts: 1012
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Drag and Drop and multiple variables

#3 Post by m_from_space »

Gigan wrote: Sat Jul 29, 2023 7:14 pm Drag works and the pieces snaps correctly when dragged into a socket. Problem is, I can only get 1 variable working at the time. If I drag another rune to its correct socket, the first rune's variable gets back to False. :(
Yes, you reset positions every time the player drops something and the function is called:

Code: Select all

init python:
    def piece_dragged(drags, drop):
        global correct_position_1, correct_position_2
        correct_position_1 = False
        correct_position_2 = False
My suggestion for the code:

Code: Select all

init python:
    def piece_dragged(drags, drop):
        global correct_position_1, correct_position_2, correct_position_3
        
        # variables with that name are never used inside this function, so what's that about?
        # global rune_1, rune_2, rune_3, rune_4, rune_5
        
        if not drop:
            return
        drag_name = drags[0].drag_name
        drop_name = drop.drag_name
        
        # what is this about ???
        # store.draggable = drag_name
        # store.droppable = drop_name
        
        # the player dropped a rune into some socket
        if "rune" in drag_name and "socle" in drop_name:
            drags[0].snap(drop.x, drop.y, delay=0.1)

        if drag_name == "rune_1":
            if drop_name == "socle_1":
                correct_position_1 = True
            else:
                correct_position_1 = False
        elif drag_name == "rune_2":
            if drop_name == "socle_2":
                correct_position_2 = True
            else:
                correct_position_2 = False
        elif drag_name == "rune_3":
            # a fancy way
            correct_position_3 = True if drop_name == "socle_3" else False

        if correct_position_1 and correct_position_2 and correct_position_3:
            return True
        else:
            return

Gigan
Regular
Posts: 28
Joined: Mon Jan 10, 2022 7:02 pm
Contact:

Re: Drag and Drop and multiple variables

#4 Post by Gigan »

Thanx to both of you !! Works perfectly now ! :D Used m_from_space's solution since I'm dumb as a brick and can't understand lists. >_>

For people looking for the final code, here's what it looks like :

Code: Select all

init python:
    def piece_dragged(drags, drop):
        global correct_position_1, correct_position_2, correct_position_3

        if not drop: #added this so the variable go back to False when the player unknowingly remove a rune from his correct position. Wasnt the case before.
            correct_position_1 = False
            correct_position_2 = False
            correct_position_3 = False
            return

        drag_name = drags[0].drag_name
        drop_name = drop.drag_name
        
        if "rune" in drag_name and "socle" in drop_name:
            drags[0].snap(drop.x, drop.y, delay=0.1)

        if drop_name == "socle_1": #switched the drop_name and drag_name position so variable goes back to False is the player tries to put a rune in an incorrect socket after putting it in the right one.
            correct_position_1 = True if drag_name == "rune_1" else False
        if drop_name == "socle_2":
            correct_position_2 = True if drag_name == "rune_2" else False
        if drop_name == "socle_3":
            correct_position_3 = True if drag_name == "rune_3" else False

        if correct_position_1 and correct_position_2 and correct_position_3:
            return True
        else:
            return
philat wrote: Sat Jul 29, 2023 10:08 pm Further details you will likely need to implement: What happens if the socket is already full? (1) Can the player drag a rune out of a socket to another socket (2) - how will you handle resetting the previous socket to empty? (3)
(1) Currently, nothing happens if the right runes are not in the right sockets, even if everything is full, so it's all good.
(2) Yep ! I want them to try till they get it right ! o/
(3) Done above !

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot]