Queued Notifications

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
mtermik
Regular
Posts: 28
Joined: Fri Dec 23, 2022 2:26 pm
Contact:

Queued Notifications

#1 Post by mtermik »

I have done a bit of research around this and have not yet found example code, or an example implementation, which covers this issue so I an attempting to develop one myself but I have hit a bit of a snag. What I would like to do is to have a message queue object, which accepts messages for display in order via renpy.notify. So far I have everything working except one small portion of the code:

For the message queue object I have a very simple class:

Code: Select all

init -1 python:
    class MessageQueue:
        def __init__(self):
            self.messages = []

        def add_message(self, message):
            self.messages.append(message)

        def get_message(self):
            if self.messages:
                return self.messages.pop(0)
            else:
                return None
I also have a screen which is responsbile for passing the messages to renpy.notify:

Code: Select all

screen create_notification:
    $ print("Entering create_notification")
    if notification_queue:
        $ message = notification_queue.get_message()

    if message is not None:
        $ print("Message: " + message)
        $ renpy.notify(message)
        timer 3.0 action Function(lambda: renpy.show_screen("create_notification"))
    else:
        $ renpy.hide_screen("create_notification")
Looking at the logs after the screen is called I see the following:

Entering create_notification
Message: Test Message 1
Entering create_notification
Message: Test Message 2
Entering create_notification
Entering create_notification

The problem I find is that, despite the timer begin in place to delay the call to the screen again, I only see the second test message, as if the Function action is not being delayed at all by the timer.

Since I am unable to place a while loop in the screen (which would really be super useful to have the ability to do), and renpy.pause is not allowed either, I am at a loss as to how to delay the call to the screen aside from a timer.

Any thoughts?

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

Re: Queued Notifications

#2 Post by m_from_space »

mtermik wrote: Wed Nov 15, 2023 5:18 am Any thoughts?
Yes. Don't put python code inside screens that changes things, because it's going to get evaluated every time the screen is drawn. And Renpy does this whenever it wants and needs to. So your $ message = notification_queue.get_message() approach will called multiple times regardless of the timer. Screens are not labels, they are objects to display stuff. Always use screen objects only for that matter.

Code: Select all

screen create_notification():
    # use a screen variable for this, because it's not getting evaluated every screen draw, but only when shown
    default message = notification_queue.get_message() if notification_queue else None

    if message is None:
        timer 0.01 action Hide()
    else:
        timer 0.01 action Function(renpy.notify, message)
        timer 3.0 action [ Hide(), Show("create_notification") ]

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3808
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Queued Notifications

#3 Post by Imperf3kt »

(m_from_space posted a solution while I was typing this, but I'll post it anyway as an alternative)
Not ideal, but here is one way that works by using list indexes.
Its not the best, as the player can click through the message and it also delays the dialogue, but its a starting point.

Code: Select all

default messages = []
label Start:
    "testing multiple time delayed messages"
    python:
        messages = ["Message one", "Message two"]
        renpy.notify(messages[0])
        renpy.pause(3)
        renpy.notify(messages[1])
    "The messages should have played out."
    
    return
Heres a slightly modified version that doesn't allow the player to skip the messages.

Code: Select all

screen notify_timer():
    timer 3.0 action Return()

default messages = []
default curr_message = ""

label start:

    "testing multiple time delayed messages"
    $ messages = ["Message one", "Message two"]
label message_loop:
    if messages:
        $ curr_message = messages.pop(0)
        $ renpy.notify(curr_message)
        call screen notify_timer
        jump message_loop
    "The messages should have played out."
    
    return
Neither of these methods is ideal though and could be much better.

I found this post that may help for better control over the effect but also requires a lot more work.
viewtopic.php?p=481308#p481308
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], giorgi1111, Google [Bot]