[solved] Help needed with drag and drop if clause for specific coordinates

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
User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

[solved] Help needed with drag and drop if clause for specific coordinates

#1 Post by ComputerArt.Club » Thu Jan 24, 2019 9:12 pm

I'm working on yet another drag and drop type mini game, it is not like a jigsaw or menu where all the positions are organized and coordinates can be done with variables and formulas, but unfortunately all the example codes I have found use a formula type approach to the if clause, like:

Code: Select all

    if ([coorlistx[movedplace[0]], coorlisty[movedplace[1]]] in piecelist):
        python:
            t1 = piecelist[movedpiece]
            t2 = piecelist.index([coorlistx[movedplace[0]], coorlisty[movedplace[1]]])
            piecelist[movedpiece] = [coorlistx[movedplace[0]],coorlisty[movedplace[1]]]
            piecelist[t2] = t1
    else:
        $ piecelist[movedpiece] = [coorlistx[movedplace[0]],coorlisty[movedplace[1]]]
    if piecelist == [[coorlistx[0],coorlisty[0]],
                        [coorlistx[1],coorlisty[0]],
                        [coorlistx[2],coorlisty[0]],
                        [coorlistx[3],coorlisty[0]],
                        [coorlistx[0],coorlisty[1]],
                        [coorlistx[1],coorlisty[1]],
                        [coorlistx[2],coorlisty[1]],
                        [coorlistx[3],coorlisty[1]],
                        [coorlistx[0],coorlisty[2]],
                        [coorlistx[1],coorlisty[2]],
                        [coorlistx[2],coorlisty[2]],
                        [coorlistx[3],coorlisty[2]]]:
Instead, I specify my drop items locations and I want to have an if clause that uses absolute values specifying if a specific drag piece is in a specific drop space.
E.g.

Code: Select all

screen bridge:
    add "bridgebg" 
    add "bridge" xalign 0.5
    draggroup:
    ### pieces
        drag:
            drag_name "oval"
            child "oval"
            dragged piece_dragged
            #draggable True
            droppable False
            draggable True
            xpos 50 ypos 50
            
        drag:
            drag_name "triangle"
            child "triangle"
            dragged piece_dragged
            #draggable True
            droppable False
            draggable True
            xpos 20 ypos 400
        
        drag:
            drag_name "rectangle"
            child "rectangle"
            dragged piece_dragged
            #draggable True
            droppable False
            draggable True
            xpos 1650 ypos 50
            
        drag:
            drag_name "square"
            child "square"
            dragged piece_dragged
            #draggable True
            droppable False
            draggable True
            xpos 50 ypos 600
            
        drag:
            drag_name "circle"
            child "circle"
            dragged piece_dragged
            #draggable True
            droppable False
            draggable True
            xpos 1630 ypos 650
            
            
    ###  destinations  
        drag:        
            drag_name "rect_destination"
            child "4rectangle" 
            draggable False
            droppable True
            xpos 549 ypos 88
            
        drag:        
            drag_name "square_destination"
            child "4square" 
            draggable False
            droppable True
            xpos 830 ypos 100
            
        drag:        
            drag_name "circle_destination"
            child "4circle" 
            draggable False
            droppable True
            xpos 830 ypos 350
            
        drag:        
            drag_name "oval_destination"
            child "4oval" 
            draggable False
            droppable True
            xpos 1103 ypos 94
            
        drag:        
            drag_name "triangle_destination"
            child "4triangle" 
            draggable False
            droppable True
            xpos 1160 ypos 445
Could someone give me an example of how I can write an if clause that is specifying specific drag items and drop coordinates/a specific drop object?
Thank you for your time.
Last edited by ComputerArt.Club on Sun Jan 27, 2019 12:40 pm, edited 1 time in total.

User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#2 Post by ComputerArt.Club » Fri Jan 25, 2019 11:16 am

The other thing I had a question about was the Python definitions, both the wiki example and the jigsaw example use store actions like this:

Code: Select all

### Jigsaw code
init python:
    
    def piece_dragged(drags, drop):
        
        if not drop:
            store.piecelist[(int(drags[0].drag_name[0]) * 10 + int(drags[0].drag_name[1]))][0] = drags[0].x
            store.piecelist[(int(drags[0].drag_name[0]) * 10 + int(drags[0].drag_name[1]))][1] = drags[0].y
            return
            
        store.movedpiece = int(drags[0].drag_name[0]) * 10 + int(drags[0].drag_name[1])
        store.movedplace = [int(drop.drag_name[0]), int(drop.drag_name[1])]
        
        return True

Code: Select all

#detective code
init python:

    def detective_dragged(drags, drop):

        if not drop:
            return

        store.detective = drags[0].drag_name
        store.city = drop.drag_name

        return True
The detective code is presumably used as they want to recall where the detectives were sent, but what does the store function do for the jigsaw?

User avatar
Alex
Lemma-Class Veteran
Posts: 2981
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#3 Post by Alex » Fri Jan 25, 2019 3:39 pm

Well, in your piece_dragged function you can check the name of drop object and evaluate it (or coordinates of the drop...), like (untested code sample)

Code: Select all

if drop.drag_name == "rect_destination":
    #stuff

store.my_x=drop.x
The "store" is an object that stores (lol) all the variables, used in game. So, when you change them, like

Code: Select all

$ my_var += 1
it changes the store.my_var value.

User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#4 Post by ComputerArt.Club » Sat Jan 26, 2019 3:32 am

Thanks for your reply!
I have put it in the piece dragged definition as it wanted drop to be defined and drop is an argument of piece dragged.

First i experimented with just one if clause and it seemed to work, but then further experimentation showed it was accepting any dropped pieces, and not just the correct ones.

Code: Select all

if drop.drag_name == "rect_destination":
If the single line one has this issue, then the multiple if clause one should have it too, but I tried it anyway.
This is my code for multiple pieces:

Code: Select all

    def piece_dragged(drags, drop):
        
        if not drop:
            return
            
        if drop.drag_name == "rect_destination" and drop.drag_name == "square_destination" and drop.drag_name == "oval_destination" and drop.drag_name == "triangle_destination" and drop.drag_name == "circle_destination":
       
            return True
Unlike the single condition version, it is not returning to the story at all, not even when all the pieces are in the correct places. There is no snapping taking place after each individual piece is placed but that is a secondary issue.

Thanks again for your help!!! It is really appreciated.

User avatar
Alex
Lemma-Class Veteran
Posts: 2981
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#5 Post by Alex » Sat Jan 26, 2019 7:59 am

The problem is in comparison conditions. For now you check if player drop a puzzle piece over several objects at once(!), but the drop is registered only for the top droppable object.
So, what do you want to achieve? Check where puzzle piece was dropped or make player drop this piece over several certain drop-objects at once?

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#6 Post by Remix » Sat Jan 26, 2019 9:19 am

You maybe want:
if the drop name is equal to the drag name with _destination at the end = good

if drop.drag_name == "{}_destination".format(drags[0].drag_name):
... this item is in the right place
Frameworks & Scriptlets:

User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#7 Post by ComputerArt.Club » Sat Jan 26, 2019 1:54 pm

Thank you both for your help. I know that you two are some of the best and most active problem solvers here, thanks for taking the time to share your expertise!

The idea is that after all the pieces are in place the story would progress, that is
the main problem I have to solve, and that is enough.
Although ideally, if it is not too much work, the pieces would either snap into place when dropped or the child of the drop object would change and the dragged object would disappear (as right now the dropped objects might be a few pixels off and it doesn't feel like they have been registered).
Remix wrote:
Sat Jan 26, 2019 9:19 am
You maybe want:
if the drop name is equal to the drag name with _destination at the end = good

if drop.drag_name == "{}_destination".format(drags[0].drag_name):
... this item is in the right place
Thank you remix, for the most part that was the case, I have altered the code now so that the exceptions have been fixed. I placed that code in the definition where my last code was but no luck, I tried removing the {} and replacing it with a single shape, but no luck.
Here are some images with what I am trying to do here (rough draft, will tidy it up once the functionality is there). Drag the items to the correct place in the bridge, but I see this being useful for many other types of puzzle too.
Image

Image

User avatar
Alex
Lemma-Class Veteran
Posts: 2981
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#8 Post by Alex » Sat Jan 26, 2019 3:13 pm

Ah, ok then... You see, to run this puzzle you've called the screen, so it must Return a value to end player's interaction with it. You've made a piece_dragged function that do some stuff and acasionally return True value - that ends player's interaction with screen.
The only thing to do is to make piece_dragged function return True only when puzzle is solved...))
So, to check if puzzle is solved you need some variables (be it individual vars or a list of vars or the other fancy stuff I'm not familiar with). If you'll check SusanTheCat's puzzle game - viewtopic.php?f=51&t=16151&p=294340#p294340 you'd see that piece_dragged function checks placedlist list if there any puzzle pieces that are not at their places.

Since you have not too much pieces, try to set 5 variables to False.

Code: Select all

default rect = False
default square = False
etc.

then in piece_dragged function change them and check if all pieces are placed correct

Code: Select all

if drags[0].drag_name == "rect" and drop.drag_name == "rect_destination":
    rect = True
    drags[0].snap(drop.x,drop.y, delay=0.1)
    drags[0].draggable = False # to not let player move it elsewhere
elif drags[0].drag_name == "square" and drop.drag_name == "square_destination":
    square = True
    drags[0].snap(drop.x,drop.y, delay=0.1)
    drags[0].draggable = False
# etc.

if rect and square: # all 5 vars are True
   return True
else:
    return

Or try to make a list of drop places and a list of drag pieces. In the description of each drag object you can make a variable that will be changed if puzzle piece will be placed on the correct drop place. Then in piece_dragged function you could iterate through the drags list and check if any of them is not in place.

User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#9 Post by ComputerArt.Club » Sun Jan 27, 2019 6:39 am

wow! Thanks for this, getting closer. The snapping part is working and then they become undraggable, which is awesome, but I have been getting errors with the second part:

Code: Select all

if rectangle and square and oval and circle and triangle: # all 5 vars are True
    return True

Code: Select all

"UnboundLocalError: local variable '(any of the shapes)' referenced before assignment"  
Without that line of code, all 5 pieces will be dragged and locked down but then nothing will happen.

The error could be for any of the shapes and occurs for this line after pieces are dragged:
(Please note, I have change all instances of rect to rectangle for consistency)

Code: Select all

if oval and triangle and rectangle and square and circle: # all 5 vars are True 
            return True
also

Code: Select all

if oval == True and triangle == True and rectangle == True and square == True and circle == True: # all 5 vars are True
            return True
The variables (default circle = True) were placed at line 1, in an init, in the python block and a number of other places to see if that was the issue (I assume it is trying to say the variable needs to be defined first.
I wondered if it was my failed attempt at checking multiple conditions in one line so I changed the variables to one (default shapes = 0) and then rectangle = True, circle = True statements to shapes += 1 and then checking for
if shapes = 5:
return, but the error was the same

Code: Select all

"UnboundLocalError: local variable 'shapes' referenced before assignment"
Anyway, here is what it looks like now, I have uncommented the true false statements and commented the shapes attempt, the problem line has the == True now instead of nothing, but the route of the problem I presume is where those variables are defined or how they are defined?

Code: Select all

default oval = False # first line of code, currently no indent, no python or init block, though I have tried.
default triangle = False
default rectangle = False
default square = False
default circle = False

Code: Select all

    def piece_dragged(drags, drop):
        
        if not drop:
            
            return
            
  
   
        if drags[0].drag_name == "rectangle" and drop.drag_name == "rectangle_destination":
            #shapes +=1
            rectangle = True
            drags[0].snap(drop.x,drop.y, delay=0.1)
            drags[0].draggable = False # to not let player move it elsewhere
        elif drags[0].drag_name == "square" and drop.drag_name == "square_destination":
            #shapes +=1
            square = True
            drags[0].snap(drop.x,drop.y, delay=0.1)
            drags[0].draggable = False
        elif drags[0].drag_name == "oval" and drop.drag_name == "oval_destination":
            #shapes +=1
            oval = True
            drags[0].snap(drop.x,drop.y, delay=0.1)
            drags[0].draggable = False
        elif drags[0].drag_name == "triangle" and drop.drag_name == "triangle_destination":
            #shapes +=1
            triangle = True
            drags[0].snap(drop.x,drop.y, delay=0.1)
            drags[0].draggable = False
        elif drags[0].drag_name == "circle" and drop.drag_name == "circle_destination":
            #shapes +=1
            circle = True
            drags[0].snap(drop.x,drop.y, delay=0.1)
            drags[0].draggable = False
        # etc.

        #if shapes == 5:
        if oval == True and triangle == True and rectangle == True and square == True and circle == True: # all 5 vars are True
            return True
        else:
            return
Thanks so much for your time. It seems like it is close to being solved now. Any ideas?

User avatar
Alex
Lemma-Class Veteran
Posts: 2981
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#10 Post by Alex » Sun Jan 27, 2019 11:09 am

Khm, yes - my fault. Forgot to tell function to use global variables (not local - internaly used only for this function). Try

Code: Select all

    def piece_dragged(drags, drop):
        global oval, triangle, rectangle, square, circle
        
        if not drop:
            
            return
# rest of the code

User avatar
ComputerArt.Club
Veteran
Posts: 427
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: Help needed with drag and drop if clause for specific coordinates

#11 Post by ComputerArt.Club » Sun Jan 27, 2019 12:35 pm

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!IT WORKS!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

┏━━┓
┗┓┏┫    ┏┓
 ┃┃┗┳━┳━┫┣┳┳┳━┳┳┓
 ┃┃┓┣┛┃┓┃ ┫┃┃★┃┃┃
 ┃┃┃┃★┃┃┃┳┃┻┃ ┃┻┃
 ┗┻┻┻━┻┻┻┻╋┓┣━┻━┛
          ┗━┛

  / ̄ ̄ヽ ̄ ̄\
 ∠  レ |  ⌒ヽ
  \__ノ丶  )|
   (_と__ノ⊂ニノ

THANK YOU!!! :D :lol:

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Hojoo