[Solved][chat system] how to make a message show on screen before you send it

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
xMichi
Regular
Posts: 35
Joined: Fri May 30, 2014 4:17 am
Contact:

[Solved][chat system] how to make a message show on screen before you send it

#1 Post by xMichi »

(Edit² for anyone who finds this: Problem got solved and there are lots of new features provided by m_from_space below if you're interested! Including a typing animation and automatically receiving the next text! :D)

Hi! I am using Nighten's messaging system and I have a little problem with figuring out some customization.

First of all I am using imagebuttons instead of the usual quick menu. The top part is the quickmenu, but my question is about the LOWER part:
Image

I have no clue what I am doing and I have tried all kinds of things but I can't seem to figure it out. I did not like the big yellow continue part so I wanted to change it AND I would prefer if I can show the MC's text on there before it sends as a message.

EDIT: (removed a section) I didn't know how to add that lower element on the screen and work from there. I added it to my quickmenu background because I didn't know what else to do. Later on after I already posted this I thought of the solution to add the picture to the background picture of the phone. So that has been done. It shows up not through code but through image. The code below remains unchanged.

My game is 1440 x 2560.

But then the actual issue I have, and I haven't been able to try this at all yet because I have NO CLUE where to start... is that I want the text of the MC to appear on the "messaging part" ^ so on that picture above... like how it would look in a normal chat system when you type! But instead of typing it yourself I want to show the text already there, but not yet send and then when you click it sends as a message, like how it already does with the original code.

This is only for the MC, of course.

Is there a way to implement this and how can I do such a thing?

I included the original code of that section and then what I changed until now below so you can see what I have done/tried... and maybe any mistakes I have made. :oops:

The original code:

Code: Select all

screen PhoneDialogue(dialogue, items=None):

    style_prefix "phoneFrame"

    vbox:
        spacing 0
        # Messenger screen
        frame:
            # ysize 0.85
            if len(items)>=2:
                ysize 1632-(len(items)-2)*(120+10)-20
            else:
                ymaximum 1632
            viewport:
                draggable True
                mousewheel True
                # cols 1
                yinitial 1.0
                # scrollbars "vertical"
                vbox:
                    xalign 0.5
                    null height 20
                    use nvl_phonetext(dialogue,items)
                    null height 100
        # Button to progress
        if len(items)==0: #If we don't have a menu
            button:
                padding (0,0)
                add Solid("#ffda4a")
                add Transform("continue_btn.png", align=(0.5,0.5))
                action RollForward()
        else:
            # Phone Menu Choice
            frame:
                background Solid("#ffda4a")
                foreground None

                vbox:
                    yalign 0.5
                    for i in items: #For each choices...
                        button:
                            action i.action
                            xalign 0.5
                            frame:
                                background Solid("#f1f6fe")
                                foreground None
                                xysize (1000,120)

                                text i.caption:
                                    align (0.5,0.5)
                                    text_align 0.5
                                    size 60
                            # style "nvl_button"
What I changed it to (I had no idea what I was doing so I have been trying and retrying random things):

Code: Select all

screen PhoneDialogue(dialogue, items=None):

    style_prefix "phoneFrame"

    #vbox:
    vbox:
        spacing 25
        # Messenger screen
        frame:
            ysize 0.75

            if len(items)>=2:
                ysize 1632-(len(items)-2)*(120+10)-20
            else:
                ymaximum 2300
                #yminimum 1000

            viewport:
                draggable True
                mousewheel True
                # cols 1
                yinitial 1.0
                ypos 150
                # scrollbars "vertical"
                vbox:
                    xalign 0.5
                    null height 20
                    use nvl_phonetext(dialogue,items)
                    null height 100
        # Button to progress
        if len(items)==0: #If we don't have a menu
            button:
                padding (0,0)
                #add Solid("#d79bb4")
                #ysize 100
                #ymaximum 150
                #ypos 1700
                #background "continue_btn.png"
                #add Transform("continue_btn.png", align=(0,0.5))
                action RollForward()
        else:
            # Phone Menu Choice
            frame:
                background Solid("#d79bb4")
                foreground None

                vbox:
                    yalign 0.5
                    for i in items: #For each choices...
                        button:
                            action i.action
                            xalign 0.5
                            frame:
                                background Solid("#f1f6fe")
                                foreground None
                                xysize (1000,120)

                                text i.caption:
                                    align (0.5,0.5)
                                    text_align 0.5
                                    size 60
                            # style "nvl_button"
Last edited by xMichi on Sun Jun 26, 2022 4:15 am, edited 3 times in total.

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

Re: [chat system] how to make a message show on screen before you send it

#2 Post by m_from_space »

This is a tricky thing to do, but for only text spoken by the MC, it's doable in general.

1) Show the last line of the dialogue inside the bottom of the phone (instead of showing that button image). This creates the impression the user would send the text.

Code: Select all

screen PhoneDialogue(dialogue, items=None):

     ...
        # Button to progress
        if len(items)==0: #If we don't have a menu
            button:
                action RollForward()
                padding (0,0)
                add Solid("#ffda4a")
                # show the last spoken dialogue text of the MC inside this area
                if dialogue[-1].who == MC_Name:
                    text dialogue[-1].what size 50
                #add Transform("continue_btn.png", align=(0.5,0.5))
        else:

    ...
2) Inside the main phone window just hide the last line using a simple trick:

Code: Select all

screen nvl_phonetext(dialogue,items):
    style_prefix None

    $ previous_d_who = None
    for id_d, d in enumerate(dialogue):
        # hide the last line spoken by the MC at the right of the interface
        # since it will be displayed at the bottom of the screen instead
        # (the say screen expects a line to be displayed!)
        if d.who == MC_Name and d.what == dialogue[-1].what:
            text d.what id d.what_id xpos 1.0
        elif d.who == None: # If it's the narrator talking
            null height 30
            text d.what:
    ...
Now of course this is not perfect, since it doesn't automatically "receive" the next line of the character, so the user has to click for getting it and the click for sending it. And the sound effect has to only occur on "sending". I have no more time right now, but maybe this will help you progress.

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

Re: [chat system] how to make a message show on screen before you send it

#3 Post by m_from_space »

I just improved what I suggested earlier:

The text you will put in and send will automatically show up now after 1 seconds and is also "typed in" using slow_cps. Furthermore all other messages are called in after 1 second, so you don't have to click for every one of it. It's like the other person is writing on their own. I use "Return()" for advancing by the way, don't know what RollForward() is about anyway.

Code: Select all

screen PhoneDialogue(dialogue, items=None):

    ...

        # Button to progress
        if len(items)==0: #If we don't have a menu
            # if the last dialogue was not coming from MC, just call in the next line automatically
            if dialogue[-1].who != MC_Name:
                timer 1.0 action Return()
            button:
                action Return()
                padding (0,0)
                add Solid("#ffda4a")
                # show the last spoken dialogue text of the MC inside this area
                hbox:
                    yalign 0.5
                    if dialogue[-1].who == MC_Name:
                            frame:
                                background None
                                xsize 900
                                padding (5,5)
                                text dialogue[-1].what size 40 xalign 0.5 yalign 0.5 slow_cps 40
                    else:
                            null width 900
                    add "continue_btn" yalign 0.5
        else:
    ...

xMichi
Regular
Posts: 35
Joined: Fri May 30, 2014 4:17 am
Contact:

Re: [chat system] how to make a message show on screen before you send it

#4 Post by xMichi »

m_from_space wrote: Thu Jun 23, 2022 4:29 am I just improved what I suggested earlier:

The text you will put in and send will automatically show up now after 1 seconds and is also "typed in" using slow_cps. Furthermore all other messages are called in after 1 second, so you don't have to click for every one of it. It's like the other person is writing on their own. I use "Return()" for advancing by the way, don't know what RollForward() is about anyway.

Code: Select all

screen PhoneDialogue(dialogue, items=None):

    ...

        # Button to progress
        if len(items)==0: #If we don't have a menu
            # if the last dialogue was not coming from MC, just call in the next line automatically
            if dialogue[-1].who != MC_Name:
                timer 1.0 action Return()
            button:
                action Return()
                padding (0,0)
                add Solid("#ffda4a")
                # show the last spoken dialogue text of the MC inside this area
                hbox:
                    yalign 0.5
                    if dialogue[-1].who == MC_Name:
                            frame:
                                background None
                                xsize 900
                                padding (5,5)
                                text dialogue[-1].what size 40 xalign 0.5 yalign 0.5 slow_cps 40
                    else:
                            null width 900
                    add "continue_btn" yalign 0.5
        else:
    ...
Oh, wow! I already was really happy with what you gave me before but this improvement is so much better still! Thank you so, so much! It looks amazing now! :)
And you already helped me with some items I still wanted to figure out, too! :D

I have been trying to figure out how to do that
the sound effect has to only occur on "sending".
thingy, but no luck so far.
I tried to do something with the d.who == MC

Code: Select all

def Phone_SendSound(event, interact=True, **kwargs):
        if event == "show_done":
            if dialogue[-1].who == MC_Name:
                Return()
            else:
                renpy.sound.play("audio/SendText.ogg")
and

Code: Select all

def Phone_SendSound(event, interact=True, **kwargs):
            if id who == MC_Name and id what == dialogue[-1].what:
                pass
            else:
                renpy.sound.play("audio/SendText.ogg")
which gives me

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 35, in script
    mc_nvl "oops sorry min', I forgot {image=emoji/sweat.png}"
  File "renpy/common/00nvl_mode.rpy", line 381, in do_display
    **display_args)
  File "game/PhoneTexting.rpy", line 23, in Phone_SendSound
    if dialogue[-1].who == MC_Name:
NameError: global name 'dialogue' is not defined
I suppose I can't use things like that? I just don't fully understand why. Is it because it's in init -1 python and because it reads it before the game starts? or...?
I'm also not sure what I should be looking into instead. Would you have any idea what I should be looking into? Or what kind of function might be helpful? even if it's just some documentation that could possibly be useful.

anyway regardless thanks again you've been a HUGE help!

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

Re: [Solved][chat system] how to make a message show on screen before you send it

#5 Post by m_from_space »

Glad you like it.

The sending sound is played using a callback at the moment. That means whenever the MC is done talking, the sound plays. That worked for the original phone, but not for this mod. But we can easily fix it I think. We just play the sound whenever we hit the button instead of using the callback. The problem then is, that the other party is instantly replying and playing their own sound. That sucks. So we would have the other party wait for a second and then reply, which feels more natural anyway.

So it took me quite some time finding a good solution for that delay to be honest. But I like it.

1) Replace the character callbacks with the following lines:

Code: Select all

default delay_receive = False
default last_char = None

init -1 python:

    # Character callback ; Play a sound when a message is received
    def Phone_ReceiveSound(event, interact=True, **kwargs):
        global delay_receive, last_char, MC_Name
        if event == "begin" and last_char == MC_Name:
            delay_receive = True
            renpy.pause(1.0)
            delay_receive = False
        if event == "show_done":
            last_char = None
            renpy.sound.play("audio/ReceiveText.ogg")
    def Phone_SendSound(event, interact=True, **kwargs):
        global last_char, MC_Name
        if event == "show_done":
            last_char = MC_Name
2) Add an activation sound to the button that sends text:

Code: Select all

screen PhoneDialogue(dialogue, items=None):
    ...
            button:
                action Return()
                activate_sound "audio/SendText.ogg"
                padding (0,0)
                add Solid("#ffda4a")
    ...
3) Add magical stuff to the nvl_phonetext screen (I just post the whole thing here). - I added a "user is typing" animation consisting of 3 dots when the delay is happening, which I like.

Code: Select all

# The actual messenger screen
screen nvl_phonetext(dialogue,items):
    style_prefix None

    $ previous_d_who = None
    for id_d, d in enumerate(dialogue):
        # if the other party is delaying their text, hide the original one first
        if d.current and delay_receive:
            text d.what id d.what_id xpos 1.0
        # hide the last line spoken by the MC at the right of the interface
        # since it will be displayed at the bottom of the screen instead
        # (the say screen expects a line to be displayed!)
        if d.current and d.who == MC_Name:
            text d.what id d.what_id xpos 1.0
        elif d.who == None: # If it's the narrator talking
            null height 30
            text d.what:
                    xalign 0.5
                    ypos 0.0
                    xsize 650
                    text_align 0.5
                    italic True
                    size 40
                    slow_cps False
                    id d.what_id
                    if d.current and len(items)==0:
                        at message_narrator
            null height 30
        else:
            if d.who == MC_Name:
                $ message_frame = "phone_send_frame.png"
            else:
                $ message_frame = "phone_received_frame.png"

            hbox:
                spacing 10
                if d.who == MC_Name:
                    box_reverse True
                    xalign 1.0

                #If this is the first message of the character, show an icon
                if previous_d_who != d.who:
                    if d.who == MC_Name:
                        $ message_icon = "phone_send_icon.png"
                    else:
                        $ message_icon = "phone_received_icon.png"

                    add message_icon:
                        if d.current  and len(items)==0:
                            at message_appear_icon()

                else:
                    null width 107

                vbox:
                    yalign 1.0
                    if d.who != MC_Name and previous_d_who != d.who:
                        text d.who:
                            size 30

                    frame:
                        padding (20,20)


                        background Frame(message_frame, 23,23,23,23)
                        # xsize 750

                        if d.current and len(items)==0:
                            if d.who == MC_Name:
                                at message_appear(1)
                            else:
                                at message_appear(-1)

                        # add a typical "i'm typing" animation
                        if d.current and delay_receive:
                            text "..." size 45 slow_cps 4 pos (0,0) color "#000"
                        else:
                            text d.what:
                                pos (0,0)
                                # xsize 750
                                slow_cps False
                                size 45


                                if d.who == MC_Name :
                                    color "#FFF"
                                    text_align 1.0
                                    xanchor 1.0
                                    xpos 1.0
                                else:
                                    color "#000"

                                id d.what_id

        $ previous_d_who = d.who

xMichi
Regular
Posts: 35
Joined: Fri May 30, 2014 4:17 am
Contact:

Re: [Solved][chat system] how to make a message show on screen before you send it

#6 Post by xMichi »

m_from_space wrote: Fri Jun 24, 2022 4:37 am Glad you like it.

The sending sound is played using a callback at the moment. That means whenever the MC is done talking, the sound plays. That worked for the original phone, but not for this mod. But we can easily fix it I think. We just play the sound whenever we hit the button instead of using the callback. The problem then is, that the other party is instantly replying and playing their own sound. That sucks. So we would have the other party wait for a second and then reply, which feels more natural anyway.

So it took me quite some time finding a good solution for that delay to be honest. But I like it.
Hey thank you for all the energy you put into helping me! You have really cool ideas I hadn't even thought of before.

I tried the above code but it doesn't seem to work for me.
First of all the renpy.pause makes my screen go solid black for 1 second and there ends up being no sound at all, even if I take it out. When it comes to the MC that is.
I also cannot see the dots.

But perhaps I just didn't put the code in correctly, or there is an instruction I missed?

Also where do the dots need to appear exactly? perhaps I have something in front of it? since I am using a quickmenu at the top of my screen.

I will put my entire code I have right now below:

Code: Select all

# Here's the code for the phone!

define nvl_mode = "phone"  ##Allow the NVL mode to become a phone conversation
define MC_Name = "MC" ##The name of the main character, used to place them on the screen
define Min = "Minerva"'
define Fer = "Fernys"

default delay_receive = False
default last_char = None

init -1 python:

    # Character callback ; Play a sound when a message is received
    def Phone_ReceiveSound(event, interact=True, **kwargs):
        global delay_receive, last_char, MC_Name
        if event == "begin" and last_char == MC_Name:
            delay_receive = True
            renpy.pause(1.0)
            delay_receive = False
        if event == "show_done":
            last_char = None
            renpy.sound.play("audio/ReceiveText.ogg")
    def Phone_SendSound(event, interact=True, **kwargs):
        global last_char, MC_Name
        if event == "show_done":
            last_char = MC_Name

screen PhoneDialogue(dialogue, items=None):

    style_prefix "phoneFrame"

    #vbox:
    vbox:
        spacing 25
        # Messenger screen
        frame:
            ysize 0.75

            if len(items)>=2:
                ysize 1632-(len(items)-2)*(120+10)-20

            else:
                ymaximum 2200


            viewport:
                draggable True
                mousewheel True
                # cols 1
                yinitial 1.0
                ypos 150
                # scrollbars "vertical"
                vbox:
                    xalign 0.5
                    null height 20
                    use nvl_phonetext(dialogue,items)
                    null height 100
        # Button to progress
        if len(items)==0: #If we don't have a menu
            # if the last dialogue was not coming from MC, just call in the next line automatically
            if dialogue[-1].who != MC_Name:
                timer 2.0 action Return()
            button:
                action Return()
                activate_sound "audio/SendText.ogg"
                padding (0,0)
                # show the last spoken dialogue text of the MC inside this area
                hbox:
                    yalign 0.5
                    if dialogue[-1].who == MC_Name:
                        frame:
                            background None
                            xsize 1200
                            padding (5,5)
                            text dialogue[-1].what size 50 ypos 75 xpos 30 color "#FFF" slow_cps 40

                    else:
                        null width 900
                        add "continue_btn" yalign 0.5
                        timer 2.0 action Return()

                    
        else:
            # Phone Menu Choice
            frame:
                background Solid("#d79bb4")
                foreground None

                vbox:
                    yalign 0.5
                    for i in items: #For each choices...
                        button:
                            action i.action
                            xalign 0.5
                            frame:
                                background Solid("#f1f6fe")
                                foreground None
                                xysize (1000,120)

                                text i.caption:
                                    align (0.5,0.5)
                                    text_align 0.5
                                    size 60
                            # style "nvl_button"


# The actual messenger screen
screen nvl_phonetext(dialogue,items):
    style_prefix None

    $ previous_d_who = None
    for id_d, d in enumerate(dialogue):
        # if the other party is delaying their text, hide the original one first
        if d.current and delay_receive:
            text d.what id d.what_id xpos 1.0
        # hide the last line spoken by the MC at the right of the interface
        # since it will be displayed at the bottom of the screen instead
        # (the say screen expects a line to be displayed!)
        if d.current and d.who == MC_Name:
            text d.what id d.what_id xpos 1.0
        elif d.who == None: # If it's the narrator talking
            null height 30
            text d.what:
                    xalign 0.5
                    ypos 0.0
                    xsize 650
                    text_align 0.5
                    italic True
                    size 40
                    slow_cps False
                    id d.what_id
                    if d.current and len(items)==0:
                        at message_narrator
            null height 30
        else:
            if d.who == MC_Name:
                $ message_frame = "phone_send_frame.png"
            else:
                $ message_frame = "phone_received_frame.png"

            hbox:
                spacing 10
                if d.who == MC_Name:
                    box_reverse True
                    xalign 1.0

                #If this is the first message of the character, show an icon
                if previous_d_who != d.who:
                    if d.who == MC_Name:
                        $ message_icon = "phone_send_icon.png"
                    
                    elif d.who == Min:
                        $ message_icon = "phone_Minerva_icon.png"
                    elif d.who == Fer:
                        $ message_icon = "phone_Fernys_icon.png"

                    else:
                        $ message_icon = "phone_received_icon.png"

                    add message_icon:
                        if d.current  and len(items)==0:
                            at message_appear_icon()

                else:
                    null width 107

                vbox:
                    yalign 1.0
                    if d.who != MC_Name and previous_d_who != d.who:
                        text d.who:
                            size 30

                    frame:
                        padding (20,20)
                        background Frame(message_frame, 23,23,23,23)
                        # xsize 750

                        if d.current and len(items)==0:
                            if d.who == MC_Name:
                                at message_appear(1)
                            else:
                                at message_appear(-1)

                        # add a typical "i'm typing" animation
                        if d.current and delay_receive:
                            text "..." size 45 slow_cps 4 pos (0,0) color "#000"
                        else:
                            text d.what:
                                pos (0,0)
                                # xsize 750
                                slow_cps False
                                size 45


                                if d.who == MC_Name :
                                    color "#FFF"
                                    text_align 1.0
                                    xanchor 1.0
                                    xpos 1.0
                                else:
                                    color "#000"

                                id d.what_id

        $ previous_d_who = d.who

style phoneFrame is default

style phoneFrame_frame:
    background "phone_background.png"
    #foreground "phone_foreground.png"

    yfill True
    xfill True
    # ysize 815
    # xsize 495

    padding (20,0)


style phoneFrame_viewport:
    yfill True
    xfill True

    # yoffset -20

style phoneFrame_vbox:
    spacing 10
    xfill True

transform phone_transform(pXalign=0.5, pYalign=0.5):
    xcenter pXalign
    yalign pYalign

transform phone_appear(pXalign=0.5, pYalign=0.5): #Used only when the dialogue have one element
    xcenter pXalign
    yalign pYalign

    on show:
        yoffset 1080
        easein_back 1.0 yoffset 0


transform message_appear(pDirection):
    alpha 0.0
    xoffset 50 * pDirection
    parallel:
        ease 0.5 alpha 1.0
    parallel:
        easein_back 0.5 xoffset 0

transform message_appear_icon():
    zoom 0.0
    easein_back 0.5 zoom 1.0


transform message_narrator:
    alpha 0.0
    yoffset -50

    parallel:
        ease 0.5 alpha 1.0
    parallel:
        easein_back 0.5 yoffset 0

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

Re: [Solved][chat system] how to make a message show on screen before you send it

#7 Post by m_from_space »

xMichi wrote: Fri Jun 24, 2022 9:21 amFirst of all the renpy.pause makes my screen go solid black for 1 second and there ends up being no sound at all, even if I take it out. When it comes to the MC that is.
I forgot to mention that: At the start of the label "start" replace "window hide" with "window show", so renpy keeps showing the say screen all the time (at pauses it would hide the screen). Don't know why Nighten decided to use window hide, since the phone is probably visible all the time.

For me your code looks fine atm. I made a slight change, since I realized that the animation for our own sent texts is not working anymore (that little popping effect of the message when the sound plays). Just replace inside screen nvl_phonetext:

Code: Select all

                        if d.current and len(items)==0:
                            if d.who == MC_Name:
                                at message_appear(1)
                            else:
                                at message_appear(-1)
with:

Code: Select all

                        if d.current and not items and d.who != MC_Name:
                            at message_appear(-1)
                        # only animate the second to last text message of MC, since the current one is still at the bottom before we "send" it.
                        elif len(dialogue) > 1 and dialogue[-2].who == MC_Name and dialogue[-2].what == d.what and (delay_receive or dialogue[-1].who == MC_Name):
                            at message_appear(1)
I also slightly updated the button, so the user can rush by clicking, but not produce unnecessary sound effects doing it:

Code: Select all

screen PhoneDialogue(dialogue, items=None):
    ...
            button:
                action If(not delay_receive, [Play("sound", "audio/SendText.ogg"),Return()])
                padding (0,0)
    ...
Optional: if you want the three dots to show whenever the other person is typing something (atm it's for their first message after our own), then use:

Code: Select all

    def Phone_ReceiveSound(event, interact=True, **kwargs):
        global delay_receive, last_char, MC_Name
        # uncomment if you only want the dots to appear for the first message after our own
        if event == "begin":# and last_char == MC_Name:
            delay_receive = True
            renpy.pause(1.0)
            delay_receive = False
        if event == "show_done":
            last_char = None
            renpy.sound.play("audio/ReceiveText.ogg")
Just tell me if something still doesn't work.

xMichi
Regular
Posts: 35
Joined: Fri May 30, 2014 4:17 am
Contact:

Re: [Solved][chat system] how to make a message show on screen before you send it

#8 Post by xMichi »

m_from_space wrote: Fri Jun 24, 2022 1:04 pm
Just tell me if something still doesn't work.
Works like a charm! It looks amazing! Thank you so much, once again!

The only thing that happens now when the game starts is that it shows the ADV dialogue box for a split second before the phonescreen appears. Could that have something to do with the window show statement?

Edit: Actually somehow the MC's sound doesn't seem to work still. I somehow overlooked that because I was so excited lol!
Wait I am testing a few things because when I let it play out slowly and naturally then there is no sound when the MC sends something
Yet when I click manually there is sound, even when it's the other people in the chat talking?
So I have to click for there to be sound and then it can be at any point really that it produces a sound.

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

Re: [Solved][chat system] how to make a message show on screen before you send it

#9 Post by m_from_space »

Yeah, and now I also know why "window hide" was used now. Just put "window hide" back there! :D

We will delay the text in a different manner using a timer inside the screen instead of renpy.pause(). It's more elegant anyway.

1) Change callback, we removed renpy.pause and also only play the sound if the message isn't delayed.

Code: Select all

    # Character callback ; Play a sound when a message is received
    def Phone_ReceiveSound(event, interact=True, **kwargs):
        global delay_receive, last_char, MC_Name
        if event == "begin":# and last_char == MC_Name:
            delay_receive = True
        if event == "show_done":
            if not delay_receive:
                renpy.sound.play("audio/ReceiveText.ogg")
            last_char = None
2) Change PhoneDialogue (slight fix to prevent bugs if dialogue length is zero. Also make sure to receive the next text only after the delay_receive is done)

Code: Select all

        # Button to progress
        if not items: #If we don't have a menu
            # if the last dialogue was not coming from MC, just call in the next line
            if not delay_receive and dialogue and dialogue[-1].who != MC_Name:
                timer 1.0 action Return()
            button:
                action If(not delay_receive, [Play("sound", "audio/SendText.ogg"),Return()])
                padding (0,0)
                add Solid("#ffda4a")
                # show the last spoken dialogue text of the MC inside this area
                hbox:
                    yalign 0.5
                    if dialogue and dialogue[-1].who == MC_Name:
                            frame:
                                background None
                                xsize 900
                                padding (5,5)
                                text dialogue[-1].what size 40 xalign 0.5 yalign 0.5 slow_cps 40
3) The nvl_phonetext screen. I put the whole thing here, note that I put the timer and the hidden receiving text at the bottom, that's better if a picture is going to get shown. I also delayed the receiving text by the amount of words the other party is going to say, which is neat. :D

Feel free to change it to whatever you like of course. Just a suggestion.

Code: Select all

screen nvl_phonetext(dialogue,items):
    style_prefix None

    default previous_d_who = None
    for id_d, d in enumerate(dialogue):
        # hide the last line spoken by the MC at the right of the interface
        # since it will be displayed at the bottom of the screen instead
        # (the say screen expects a line to be displayed!)
        if d.current and d.who == MC_Name:
            text d.what id d.what_id xpos 1.0
        elif d.who == None: # If it's the narrator talking
            null height 30
            text d.what:
                    xalign 0.5
                    ypos 0.0
                    xsize 650
                    text_align 0.5
                    italic True
                    size 40
                    slow_cps False
                    id d.what_id
                    if d.current and len(items)==0:
                        at message_narrator
            null height 30
        else:
            if d.who == MC_Name:
                $ message_frame = "phone_send_frame.png"
            else:
                $ message_frame = "phone_received_frame.png"

            hbox:
                spacing 10
                if d.who == MC_Name:
                    box_reverse True
                    xalign 1.0

                #If this is the first message of the character, show an icon
                if previous_d_who != d.who:
                    if d.who == MC_Name:
                        $ message_icon = "phone_send_icon.png"
                    else:
                        $ message_icon = "phone_received_icon.png"

                    add message_icon:
                        if d.current  and len(items)==0:
                            at message_appear_icon()

                else:
                    null width 107

                vbox:
                    yalign 1.0
                    if d.who != MC_Name and previous_d_who != d.who:
                        text d.who:
                            size 30

                    frame:
                        padding (20,20)


                        background Frame(message_frame, 23,23,23,23)
                        # xsize 750

                        if d.current and not items and d.who != MC_Name:
                            at message_appear(-1)
                        # only animate the second to last text message of MC, since the current one is still at the bottom before we "send" it.
                        elif len(dialogue) > 1 and dialogue[-2].who == MC_Name and dialogue[-2].what == d.what and (delay_receive or dialogue[-1].who == MC_Name):
                            at message_appear(1)

                        # add a typical "i'm typing" animation
                        if d.current and delay_receive:
                            text "..." size 45 slow_cps 4 pos (0,0) color "#000"
                        else:
                            text d.what:
                                pos (0,0)
                                # xsize 750
                                slow_cps False
                                size 45


                                if d.who == MC_Name :
                                    color "#FFF"
                                    text_align 1.0
                                    xanchor 1.0
                                    xpos 1.0
                                else:
                                    color "#000"

                                id d.what_id
            # if the other party is delaying their text, hide the original one
            if d.current and delay_receive:
                text d.what id d.what_id xpos 1.0
                # delay receiving text depending on amount of words
                $ wait = 0.5 + len(d.what.split()) * 0.05
                timer wait action Play("sound", "audio/ReceiveText.ogg"),SetVariable("delay_receive", False)
        $ previous_d_who = d.who
Last edited by m_from_space on Sat Jun 25, 2022 1:06 am, edited 1 time in total.

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

Re: [Solved][chat system] how to make a message show on screen before you send it

#10 Post by m_from_space »

xMichi wrote: Sat Jun 25, 2022 12:02 amWait I am testing a few things because when I let it play out slowly and naturally then there is no sound when the MC sends something
I assumed the MC doesn't speak automatically. So of course sound is only played if we hit the button. I didn't think of any auto-forward mode. You can just put the sound effect back inside of the character callback for MC and remove the button sound effect. We have a delay now anyway, so no overlapping will occur.

I already forgot that we don't want it to be played immediatly. But we can just let it play automatically if the second to last text of MC is shown, so at the same time the animation is playing.

Just remove the button sound effect and put this nvl_phonetext inside:

Code: Select all

# The actual messenger screen
screen nvl_phonetext(dialogue,items):
    style_prefix None

    default previous_d_who = None
    default play_sound = False

    for id_d, d in enumerate(dialogue):
        # hide the last line spoken by the MC at the right of the interface
        # since it will be displayed at the bottom of the screen instead
        # (the say screen expects a line to be displayed!)
        if d.current and d.who == MC_Name:
            text d.what id d.what_id xpos 1.0
        elif d.who == None: # If it's the narrator talking
            null height 30
            text d.what:
                    xalign 0.5
                    ypos 0.0
                    xsize 650
                    text_align 0.5
                    italic True
                    size 40
                    slow_cps False
                    id d.what_id
                    if d.current and len(items)==0:
                        at message_narrator
            null height 30
        else:
            if d.who == MC_Name:
                $ message_frame = "phone_send_frame.png"
            else:
                $ message_frame = "phone_received_frame.png"

            hbox:
                spacing 10
                if d.who == MC_Name:
                    box_reverse True
                    xalign 1.0

                #If this is the first message of the character, show an icon
                if previous_d_who != d.who:
                    if d.who == MC_Name:
                        $ message_icon = "phone_send_icon.png"
                    else:
                        $ message_icon = "phone_received_icon.png"

                    add message_icon:
                        if d.current  and len(items)==0:
                            at message_appear_icon()
                else:
                    null width 107

                vbox:
                    yalign 1.0
                    if d.who != MC_Name and previous_d_who != d.who:
                        text d.who:
                            size 30

                    frame:
                        padding (20,20)
                        background Frame(message_frame, 23,23,23,23)
                        # xsize 750

                        if d.current and not items and d.who != MC_Name:
                            at message_appear(-1)
                        # only animate the second to last text message of MC, since the current one is still at the bottom before we "send" it.
                        elif len(dialogue) > 1 and dialogue[-2].who == MC_Name and dialogue[-2].what == d.what and (delay_receive or dialogue[-1].who == MC_Name):
                            at message_appear(1)
                            $ play_sound = True

                        # add a typical "i'm typing" animation
                        if d.current and delay_receive:
                            text "..." size 45 slow_cps 4 pos (0,0) color "#000"
                        else:
                            text d.what:
                                pos (0,0)
                                # xsize 750
                                slow_cps False
                                size 45

                                if d.who == MC_Name :
                                    color "#FFF"
                                    text_align 1.0
                                    xanchor 1.0
                                    xpos 1.0
                                else:
                                    color "#000"

                                id d.what_id
            # if the other party is delaying their text, hide the original one
            if d.current and delay_receive:
                text d.what id d.what_id xpos 1.0
                # delay receiving text depending on amount of words
                $ wait = 0.5 + len(d.what.split()) * 0.05
                timer wait action Play("sound", "audio/ReceiveText.ogg"),SetVariable("delay_receive", False)
            elif play_sound:
                $ play_sound = False
                timer 0.01 action Play("sound", "audio/SendText.ogg")

        $ previous_d_who = d.who

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

Re: [Solved][chat system] how to make a message show on screen before you send it

#11 Post by m_from_space »

I will stop working on it now, but want to provide the current version to others, just as a motivational tool for using it. It's not perfect and many things could added or changed. Feel free to use it. (No extra stuff needed, it's Nightens demo version, but modified.)
Attachments
phone_messenger_fullscreen_mod_by_m_from_space.zip
(28.41 MiB) Downloaded 21 times

Post Reply

Who is online

Users browsing this forum: Google [Bot]