Point & Click Mouse Drag

In this forum we discuss the future of Ren'Py, both bug fixes and longer-term development. Pre-releases are announced and discussed here.
Post Reply
Message
Author
User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Point & Click Mouse Drag

#1 Post by magdalene »

Hello everyone!
I have just begun to creating my game. I have succesfully made a simple inventory system (demo) where I have set a key as the first object.
In my background there's a door. I can unlock the door with an if/else statement "if pickedupkey = True" but I want to do more than that:
I would love to grap my image with the mouse and drop it at the door. Then a sound would confirm the next dialog: "door is unlocked".
I have seen the ren'py wiki which confused me enough since I am very new to all renpy. So, any help would be grateful.
Thank you all!
P.S. Check my attachment for more details!
Attachments
Screenshot
Screenshot

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

Re: Point & Click Mouse Drag

#2 Post by Alex »


User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Re: Point & Click Mouse Drag

#3 Post by magdalene »

Hello,
To be honest I couldn't interpret the code to my game.
The wiki is missing examples and I am not good enough in coding -at least now❤️
One more this is, that the example provided on your link refers to items that being added to an inventory.
Contrariwise, my action begins from there: I want to drag the item from my inventory to a hotspot area and from there, to detonate an action.

Can you provide me with an example of how the code should be, so I can drag an item from my inventory to a hotspot area, like my door?

This is my code so far, in a very early stage:

Code: Select all

image kitchen = "kitchen.jpg"
image livingroom = "livingroom.jpg"
image Lady Default = "lady normal.png"
image Lady Asking = "lady asking.png"
image Lady Happy = "lady_happy.png"

define lady = Character("Lady", color="#eb15a0")


label start:

    call Variables

    show screen inventoryScreen

    jump kitchen

label kitchen:

    scene kitchen
    hide screen gotoKitchenArrow

    hide screen keys

if firstStart == True:

    "Good morning."

    "This is the kitchen."

    window hide

    $ firstStart = False

    show screen gotoLivingRoomArrow

    $ renpy.pause(hard=True)

else:

    "This is the kitchen."

    show screen gotoLivingRoomArrow

    $ renpy.pause(hard=True)

label LivingRoom:

    scene livingroom
    hide screen gotoLivingRoomArrow


if LadyAppeared == False:

    "This is the Living Room."

    show Lady Default with dissolve


    lady "I like to start my day with a fresh cup of coffee."

    show Lady Asking

    lady "Do you like coffee?"

    menu:
        "Yes, I love coffee.":
            call LoveCoffee

        "No, I don't like coffee.":
            jump HateCoffee

    lady "Ok then, see you around.."

    hide Lady Happy with dissolve
    show screen keys

    $ LadyAppeared = True

    show screen gotoKitchenArrow

    $ renpy.pause(hard=True)

else:

    if tookkeys == False:

        show screen keys

        show screen gotoKitchenArrow

        "This is the Living Room."

        $ renpy.pause(hard=True)

    else:

        "This is the Living Room."

        show screen gotoKitchenArrow

        $ renpy.pause(hard=True)

label LoveCoffee:

    show Lady Happy with dissolve

    lady "Oh great, I am so glad."

    return

label keys:

    "You found some keys, wonder what they unlock.."

    $ renpy.pause(hard=True)


label HateCoffee:

    hide Lady Asking
    show Lady Default

    lady "Well, no one is perfect..."

    hide Lady Default with dissolve

    "GAME OVER - You choose poorly"

    return

label Variables:

    $ firstStart = True

    $ LadyAppeared = False

    $ tookkeys = False

    $ inventory = []
Last edited by magdalene on Mon Jun 14, 2021 12:24 am, edited 2 times in total.

User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Re: Point & Click Mouse Drag

#4 Post by magdalene »

I am sending you only the screens for my inventory and item, so you won't get confused :-)

Code: Select all

screen keys():
    imagebutton:
        xalign 0.4
        yalign 0.71
        idle "keys.png"
        action [Hide("keys"), SetVariable("tookkeys", True), AddToSet(inventory, "keys")]
        at keySize

screen inventoryScreen():
    frame:
        background "transparent.png"
        xalign 0.0
        yalign 0.0
        hbox:
            for item in inventory:
                $ iname = item + "_%s.png"
                imagebutton auto iname action Call(item)

User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Re: Point & Click Mouse Drag

#5 Post by magdalene »

Hi, Alex. I have updated the code. I know, it looked a total mess before :-)
Sorry, I am just starting with Ren'Py engine!

User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Re: Point & Click Mouse Drag

#6 Post by magdalene »

Ok, thank you for your help!

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

Re: Point & Click Mouse Drag

#7 Post by Alex »

magdalene wrote: Sun Jun 13, 2021 2:40 pm ...Can you provide me with an example of how the code should be, so I can drag an item from my inventory to a hotspot area, like my door?...
I've made a kind of sample that might help you understand the drag and drop system. It's not code wise and can be used for quite simple gameplay only. So, if you plan on making fully-functional point and click/escape the room game in Ren'Py, this might be better to ask someone skilled enough to create such a framework for you.

Code: Select all

#### Images
#
image red:
    Solid("#500")
    
image slot_bg:
    Solid("#ccc5")
    size(100, 100)
    
image key_1:
    Solid("#c00")
    size (100, 100)
    
image key_2:
    Solid("#00c")
    size (100, 100)
    
image apple:
    Solid("#0c0")
    size (100, 100)
    
image door_1_close:
    Solid("#c00")
    size (200, 500)

image door_1_open:
    contains:
        Solid("#ccc")
        size (200, 500)
        xoffset 0
    contains:
        Solid("#c00")
        size (150, 500)
        xoffset 50
        
    size(200, 500)
        
image door_2_close:
    Solid("#00c")
    size (200, 500)

image door_2_open:
    contains:
        Solid("#ccc")
        size (200, 500)
        xoffset 0
    contains:
        Solid("#00c")
        size (150, 500)
        xoffset 50
        
    size(200, 500)


#### Lists to store items and interactable objects (like doors)
#

# Inventory slots (all should have indx's from 0 to ...)
default inv_slots = [
    {'indx':0, 'name':'slot', 'img':'slot_bg', 'pos':(50, 50)},
    {'indx':1, 'name':'slot', 'img':'slot_bg', 'pos':(200, 50)},
    {'indx':2, 'name':'slot', 'img':'slot_bg', 'pos':(350, 50)},
    ]

# inventory list can hold the same amount of items
# as the slots number
# by default list is filed with None values
# to let us put items in any slot
default inventory = [None] * len(inv_slots)

# lists to store objects for current location
default location_items = []
default location_places = []
default message_to_show = ''

# lists of items/objects for each location
# each item/object is described by dictionary
# (in each list items/objects must have indx's from 0 to ...)
default location_items_1 = [
    {'indx':0, 'name':'Red Key', 'img':'key_1', 'pos':(600, 350), 'description':'Red key'},
    {'indx':1, 'name':'Apple', 'img':'apple', 'pos':(500, 200), 'description':'An apple'},
    ]
default location_places_1 = [
    {'indx':0, 'name':'door', 'img':{'locked':'door_2_close', 'unlocked':'door_2_open'}, 'pos':(1000, 200), 'item_to_use':'Blue Key', 'state':'locked', 'description':'it needs Blue Key to open', 'label_to_jump_to':'exit_room'},
    {'indx':1, 'name':'door', 'img':{'locked':'door_1_close', 'unlocked':'door_1_open'}, 'pos':(200, 200), 'item_to_use':'Red Key', 'state':'locked', 'description':'it needs Red Key to open', 'label_to_jump_to':'red_room'},
    ]

default location_items_2 = [
    {'indx':0, 'name':'Blue Key', 'img':'key_2', 'pos':(300, 450), 'description':'Blue key'},
    {'indx':1, 'name':'Apple', 'img':'apple', 'pos':(600, 300), 'description':'An apple 2'},
    ]
default location_places_2 = [
    {'indx':0, 'name':'door', 'img':{'locked':'door_1_close', 'unlocked':'door_1_open'}, 'pos':(900, 200), 'item_to_use':None, 'state':'unlocked', 'description':'to first room', 'label_to_jump_to':'first_room'},
    ]


#### functions for draggable items
#
init python:
    
    # since items might be in inventory and on location
    # (stored in inventory and location_items lists)
    # we'll have different functions for them
    
    # function for items in inventory
    def inv_item_dragged(drags, drop):
        # if inventory item was dragged and dropped somewhere on screen
        # and not over droppable object - snap it back to initial position
        if not drop:
            item_indx = int(drags[0].drag_name.split('-')[1])
            x,y = inventory[item_indx]['pos']
            drags[0].snap(x, y, delay = 0.1)
            return
            
        # if inventory item dropped over dropable object
        # store the name and index of the inventory item
        # and the droppable object
        item_name = drags[0].drag_name.split('-')[0]
        item_indx = int(drags[0].drag_name.split('-')[1])
        drop_name = drop.drag_name.split('-')[0]
        drop_indx = int(drop.drag_name.split('-')[1])
        
        # if inventory item was dropped over slot
        if drop_name == 'slot':
            # if we already have an item at this slot - snap item back
            if inventory[drop_indx]:
                x,y = inventory[item_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                return
            
            # if slot is empty - move inventory item to that slot
            else:
                inventory[drop_indx] = inventory[item_indx]
                inventory[drop_indx]['indx'] = drop_indx
                inventory[drop_indx]['pos'] = inv_slots[drop_indx]['pos']
                inventory[item_indx] = None
                x,y = inventory[drop_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                renpy.retain_after_load()
                renpy.restart_interaction()
                return
        
        # if inventory item was dropped over door
        elif drop_name == 'door':
            # if this is the right item and door is 'locked' - will 'unlock' it
            # and remove item from inventory
            if location_places[drop_indx]['item_to_use'] == item_name and location_places[drop_indx]['state'] == 'locked':
                location_places[drop_indx]['state'] = 'unlocked'
                inventory[item_indx] = None
                renpy.retain_after_load()
                renpy.restart_interaction()
                return
            
            # otherwise - snap item back
            else:
                x,y = inventory[item_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                return
        
        # if inventory item was dropped over something else - snap it back
        else:
            x,y = inventory[item_indx]['pos']
            drags[0].snap(x, y, delay = 0.1)
            return
                
    # function for items on location
    def loc_item_dragged(drags, drop):
        # if item was dragged and dropped somewhere on screen
        # and not over droppable object - snap it back to initial position
        if not drop:
            item_indx = int(drags[0].drag_name.split('-')[1])
            x,y = location_items[item_indx]['pos']
            drags[0].snap(x, y, delay = 0.1)
            return
            
        # if item dropped over dropable object
        # store the name and index of the item
        # and the droppable object
        item_name = drags[0].drag_name.split('-')[0]
        item_indx = int(drags[0].drag_name.split('-')[1])
        drop_name = drop.drag_name.split('-')[0]
        drop_indx = int(drop.drag_name.split('-')[1])
        
        # if item was dropped over slot
        if drop_name == 'slot':
            # if we already have an item at this slot - snap item back
            if inventory[drop_indx]:
                x,y = location_items[item_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                return
            
            # if slot is empty - move item to that slot
            else:
                inventory[drop_indx] = location_items[item_indx]
                inventory[drop_indx]['indx'] = drop_indx
                inventory[drop_indx]['pos'] = inv_slots[drop_indx]['pos']
                location_items[item_indx] = None
                x,y = inventory[drop_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                renpy.retain_after_load()
                return
        
        # if item was dropped over door
        elif drop_name == 'door':
            # if this is the right item and door is 'locked' - will 'unlock' it
            # and remove item from inventory
            if location_places[drop_indx]['item_to_use'] == item_name and location_places[drop_indx]['state'] == 'locked':
                location_places[drop_indx]['state'] = 'unlocked'
                location_items[item_indx] = None
                renpy.retain_after_load()
                renpy.restart_interaction()
                return
            
            # otherwise - snap item back
            else:
                x,y = location_items[item_indx]['pos']
                drags[0].snap(x, y, delay = 0.1)
                return
        
        # if item was dropped over something else - snap it back
        else:
            x,y = location_items[item_indx]['pos']
            drags[0].snap(x, y, delay = 0.1)
            return
            
        
#### Screen that will show inventory slots, items and objects on location
#
screen test_game_scr():
    
    # all the items/objects should be in one draggroup
    draggroup:
        
        # create all drags from their descriptions in lists
        # the order of appearence does matter
        # (first shown items will be under the last ones)
        
        # location places
        for place in location_places:
            if place:
                drag:
                    drag_name '{}-{}'.format(place['name'], place['indx'])
                    child place['img'][place['state']]
                    draggable False
                    droppable True
                    # if door is 'locked' it will show message
                    # otherwise - send player to another location
                    if place['state'] == 'locked':
                        clicked SetVariable('message_to_show', place['description'])
                    else:
                        clicked Jump(place['label_to_jump_to'])
                    unhovered SetVariable('message_to_show', '')
                    pos place['pos']
        
        
        # location items
        for loc_item in location_items:
            if loc_item:
                drag:
                    drag_name '{}-{}'.format(loc_item['name'], loc_item['indx'])
                    child loc_item['img']
                    draggable True
                    droppable False
                    clicked SetVariable('message_to_show', loc_item['description'])
                    unhovered SetVariable('message_to_show', '')
                    dragged loc_item_dragged # function for item that was dragged
                    pos loc_item['pos']
        
        # inventory slots
        for slot in inv_slots:
            drag:
                drag_name '{}-{}'.format(slot['name'], slot['indx'])
                child slot['img']
                draggable False
                droppable True
                clicked SetVariable('message_to_show', 'Inventory slot')
                unhovered SetVariable('message_to_show', '')
                pos slot['pos']
                
        # inventory items
        for item in inventory:
            if item:
                drag:
                    drag_name '{}-{}'.format(item['name'], item['indx'])
                    child item['img']
                    draggable True
                    droppable False
                    clicked SetVariable('message_to_show', item['description'])
                    unhovered SetVariable('message_to_show', '')
                    dragged inv_item_dragged # function for inventory item that was dragged
                    pos item['pos']
                    
    # info frame
    frame:
        pos (700, 50)
        fixed:
            xysize (550, 100)
            text "[message_to_show]" xoffset 10 align (0.0, 0.5) size 25
            text "Info" align(1.0, 1.0) size 15
                
    

# The game starts here.

label start:
    # we can show and hide game screen
    show screen test_game_scr
    "Game start"
    jump first_room
    
label first_room:
    scene black
    # at first we should set
    # lists of items and objects for location
    $ location_items = location_items_1
    $ location_places = location_places_1

    "First room"
    "..."
    "... ..."
    window hide
    $ renpy.pause(hard=True)
    
label red_room:
    scene red
    $ location_items = location_items_2
    $ location_places = location_places_2

    "Red room"
    ",,,"
    ",,, ,,,"
    window hide
    $ renpy.pause(hard=True)

label exit_room:
    scene black
    hide screen test_game_scr
    "Escaped!"
    return

User avatar
magdalene
Newbie
Posts: 8
Joined: Sun Jun 06, 2021 9:50 am
Contact:

Re: Point & Click Mouse Drag

#8 Post by magdalene »

You did all this for me?
Thank you very much Alex! I will keep this as a treasure.
You 're a lifesaver :-)

Post Reply

Who is online

Users browsing this forum: No registered users