Ren'Py cardgame click vs. doubleclick

Playstorepers

Member
May 24, 2020
160
79
Hey there everyone,


A few months ago, I made a cardgame with the provided framework:


Today, I tried to expand the cardgame only to be met with bad news:

Whenever you try to start a doubleclick event, the click event always happens first.


I tried to find solutions online and tinkered 2 hours with it to no avail.


Thanks in advance.





Below is a more detailled explanation of the problem:


To illustrate the problem, I altered the klondike.rpy, by adding a Hello World notification on the click event.


Python:
def interact(self):


            evt = ui.interact()

            rv = False


            # Check the various events, and dispatch them to the methods

            # that handle them.

            if evt.type == "drag":

                if evt.drop_stack in self.tableau:

                    rv = self.tableau_drag(evt)


                elif evt.drop_stack in self.foundations:

                    rv = self.foundation_drag(evt)


            elif evt.type == "click":



                renpy.notify("HELLO WORLD")


                if evt.stack == self.stock:

                    rv = self.stock_click(evt)


            elif evt.type == "doubleclick":

                if (evt.stack in self.tableau) or (evt.stack is self.waste):

                    rv = self.tableau_doubleclick(evt)


            # Ensure that the bottom card in each tableau is faceup.

            for i in range(0, 7):

                if self.tableau[i]:

                    self.table.set_faceup(self.tableau[i][-1], True)


            # Check to see if any of the foundations has less than

            # 13 cards in it. If it does, return False. Otherwise,

            # return True.

            for i in self.foundations:

                if len(i) != 13:

                    return rv


            return "win"

Now, whenever you try to double-click something, you can see, that it still runs the click event first, before the doubleclick event.



The most likely solution would be to alter something in the cardgame.rpy. In the def event(self, ev, x, y, st): section ( especially in the click portion of that event):



Python:
if self.dragging:

                    if dststack is not None and self.drag_cards:


                        evt = CardEvent()

                        evt.type = "drag"

                        evt.table = self

                        evt.stack = self.click_stack

                        evt.card = self.click_card.value

                        evt.drag_cards = [c.value for c in self.drag_cards]

                        evt.drop_stack = dststack

                        if dstcard:

                            evt.drop_card = dstcard.value

                        evt.time = st


                else:#Probably something below here has to be modified


                    if self.click_stack.click:


                        evt = CardEvent()

                        evt.type = "click"

                        evt.table = self

                        evt.stack = self.click_stack

                        if self.click_card:

                            evt.card = self.click_card.value

                        else:

                            evt.card = None


                        evt.time = st


                    if (evt.type == self.last_event.type

                        and evt.stack == self.last_event.stack

                        and evt.card == self.last_event.card

                        and evt.time < self.last_event.time + self.doubleclick):


                        evt.type = "doubleclick"


But I'm nowhere close to find a functional solution, let alone an elegant one.


Thanks again in advance.
 

Catapo

Member
Jun 14, 2018
257
463
From what I see in the code when 2 consecutive click events happen in the same place and in a certain amount of time it will consider the second click event as a doubleclick but it will still do the first one.

While I was thinking of a solution to this I stopped and asked myself why would you even need to change this behaviour ? Isn't it normal ?
Think about opening a file: the first click event highlights it and the second event the doubleclick opens it but it will still highlight the file.
I can't think of an example when doubleclick does things unrelated to click.
 
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
Well...

There is one problem:
If you click the card, it moves the card to another position.
And if you doubleclick the card, it should open a zoom-in screen with details about the card.

That's the idea, at least.
Doesn't work in practice, because of that problem.

Feel free to add your idea, how to implement it otherwise, there might be design-solutions for my problem, instead of a programming solution.

As for the programming solutions: I was thinking about a delay-based if-clause, while I was taking a nap:

In the event click, I want to implement a delay, before asking for another variable to check:
That variable becomes true, in the double-click event and if it's true, then the click event gets cancelled.

But the problem is, that the click event becomes slightly delayed, which is fine, I guess.
And another problem is, that I'm not sure, whether such a delay feature exists.

renpy.pause stops everything, but I think a delay is something, that must exist in Python, which is why I'll continue searching on the web for such a feature.

EDIT: Nevermind, I'm retarded.
That doesn't work, since RenPy has to finish one event, before starting another.
So I guess, it's back to the drawing board.

Thanks for your answer, though. I really appreciate it.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,959
16,192
A few months ago, I made a cardgame with the provided framework:
It's another issue, but it's really over complicated code that PyTom made here. I guess it was more intended as example of how to make custom displayable than an effective way to do a card game with Ren'Py.
Plus, it's really outdated, more than 40 versions of Ren'py have been released since this framework was updated for the last time. It's definitively possible to do the same by using the native support and way less Python behind it.


Whenever you try to start a doubleclick event, the click event always happens first.
There is one problem:
If you click the card, it moves the card to another position.
And if you doubleclick the card, it should open a zoom-in screen with details about the card.
Then don't use a doubleclick, but change the mouse button. Left to drag, right for the information.
 

Playstorepers

Member
May 24, 2020
160
79
It's another issue, but it's really over complicated code that PyTom made here. I guess it was more intended as example of how to make custom displayable than an effective way to do a card game with Ren'Py.
Plus, it's really outdated, more than 40 versions of Ren'py have been released since this framework was updated for the last time. It's definitively possible to do the same by using the native support and way less Python behind it.





Then don't use a doubleclick, but change the mouse button. Left to drag, right for the information.

Damn... Just use the rightclick.

Didn't thought about that.

Seriously thank you,
Now I feel stupid.

I will try it with the right button click, thanks again.

EDIT:

While implementing your solution, I wanted to deactivate entering the game_menu via rightclick, at least for as long as the cardgame is in play.
Any idea, how to do that.

According to the documentation:

It should be: $ config.keymap['game_menu'].remove('mouseup_3')
and append, once I want to reestablish the rightclick as access to the gamemenu.
But on further inspection and trial it only seems to work, when I put the lines into an init block.

So there must be another way, right?
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,959
16,192
While implementing your solution, I wanted to deactivate entering the game_menu via rightclick, at least for as long as the cardgame is in play.
Any idea, how to do that.

According to the documentation:

It should be: $ config.keymap['game_menu'].remove('mouseup_3')
and append, once I want to reestablish the rightclick as access to the gamemenu.
But on further inspection and trial it only seems to work, when I put the lines into an init block.

So there must be another way, right?
Hmmm, it should works even outside of the init block.

But in the end it's yet another reason to implement this directly in the screen without relying on a custom displayable. Then you'll just have to define the cards as imagebutton, what will give you access to left and right clicks through the action and alternate properties, and put them inside a drag block to move them.

The link I gave in my previous comment include example codes that should help you.
 
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
Hmmm, it should works even outside of the init block.

But in the end it's yet another reason to implement this directly in the screen without relying on a custom displayable. Then you'll just have to define the cards as imagebutton, what will give you access to left and right clicks through the action and alternate properties, and put them inside a drag block to move them.

The link I gave in my previous comment include example codes that should help you.
Thanks for your answers.
The rightclick was gold. It worked perfectly and I almost have implemented, what I intended to do.
I just wrote a new evt for a rightclick on each cardpile.

The last thing, that I'm struggling with is the rightclick disable.

My problem is quite simple on the surface, but I experimented a few hours and didn't find a solution yet:
If you rightclick on one of the stacks or cards, we get the details, however, if you rightclick next to them, the game_menu opens up.

It's kinda annoying (In like 10% of cases) and to optimize the user experience, I'd like to deactivate the rightclick only in the cardgame (Rightclick is superuseful outside of the cardgame, so I want to leave it in, outside of the cardgame).

The question, that I'm struggling with now, is how to implement the deactivation.

The problem in detail:
1) $ config.keymap['game_menu'].remove('mouseup_3')
Would be the perfect solution, however it only works in the init. I can't change in in-game.

So my workarounds, that I tried and all their problems:

2) $_game_menu_screen = None doesn't work, cuz it also disables the esc button to open up the menu - User should be able to save during the cardgame -> Probably not an option for me

3) create a screen with key ("mouseup_3") action NullAction(): Disallows rightclick on the cards -> Probably not an option

4) create a zorder -20 screen with a transparent fullscreen imagebutton and alternate action NullAction(), doesn't work either, because just like you described, my implementation of the cardgame isn't in one screen and always below the transparent fullscreen button, ergo: Rightclick doesn't work, heck even leftclick doesn't work

5) remove the original rightclick with
$ config.keymap['game_menu'].remove('mouseup_3') in the init
and then create a screen with:
key ("mouseup_3") action ShowMenu('save')
works fine, until I realized, that the ShowMenu('save') isn't the equivalent for game_menu.
Before, using the rightclick also closed all unnecessary screens (For example phone menu screens and pop-ups), which was really handy for the player.

TLDR: Two questions to everyone here:
1) What's the correct action for key ("mouseup_3") action to simulate the original game_menu action.
or even better:
2) How would any of you implement, the rightclick disable?

Thank you all in advance and sorry, if I'm bothering you with my walls of text and stupid questions.
 

Harard

Newbie
Aug 23, 2016
17
32
It's another issue, but it's really over complicated code that PyTom made here. I guess it was more intended as example of how to make custom displayable than an effective way to do a card game with Ren'Py.
Plus, it's really outdated, more than 40 versions of Ren'py have been released since this framework was updated for the last time. It's definitively possible to do the same by using the native support and way less Python behind it.
Is there a good / usable up-to-date example?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,959
16,192
Is there a good / usable up-to-date example?
Not to my knowledge. The only game currently in development that use drag and drop is Lust Hunter, but its code is too heavy for what is done.
There's surely some example in the , but most of them are either outdated or people showing off their skills. The first ones would still works, but in a too complex way, while the seconds tend to be too focused on a single task, and bugged when you try to use it for something a bit different.

But the example that come with the doc (link in the post you quoted) are relatively basic and easy to understand after few trial and error try.