Move Character to the Front when Speaking?

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
lking22
Regular
Posts: 50
Joined: Sun Dec 03, 2017 3:33 am
Projects: Grey Feather
itch: freefall-games
Contact:

Move Character to the Front when Speaking?

#1 Post by lking22 »

I'm having a bit of trouble with dialog scenes involving a lot of characters, since their images overlap a little too much. To solve that I was planning to move them to the front of the scene, above all other characters, whenever they talk, but I can't figure out how to do that. I have figured out how to make it focus on the character using this code:

Code: Select all

def active_doc(event, interact=True, **kwargs):
        global current_speaker
        if not interact:
            return
        if event == "begin":
            current_speaker = 'doc'

define d = DynamicCharacter("doc_name", color='#2a3d45', image='doc', callback=active_doc, ctc="ctc_blink", ctc_position="nestled")

image doc Normal = ConditionSwitch(
    "current_speaker == 'doc'", "portraits/avery/normal.png",
    "current_speaker != 'doc'", im.MatrixColor("portraits/avery/normal.png", im.matrix.saturation(0.8) * im.matrix.brightness(-0.2)))
(That's just a small selection as an example, I've obviously got a lot more characters and images than this)

I was wondering if there was a way I could add to this code in order to make it move the image above other characters when they talk? I'm likely missing something obvious here, tbh.
Releases:
Image

Current projects:
In the Ashes of Dawn
Split Psyche
Savestate Gambit

kivik
Miko-Class Veteran
Posts: 786
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Move Character to the Front when Speaking?

#2 Post by kivik »

Renpy images are ordered by the last shown on top - so you can just add a renpy.show() statement in your callback to show your speaking character again and it should now be on top?

https://www.renpy.org/doc/html/statemen ... renpy.show

User avatar
lking22
Regular
Posts: 50
Joined: Sun Dec 03, 2017 3:33 am
Projects: Grey Feather
itch: freefall-games
Contact:

Re: Move Character to the Front when Speaking?

#3 Post by lking22 »

I just tried that and it sort of works? I'm not sure why or how, but when I do this:

Code: Select all

def active_doc(event, interact=True, **kwargs):
        global current_speaker
        if not interact:
            if renpy.showing('doc'): #detects if the character's image is on screen to move
                renpy.show('doc', zorder=1)
            return
        if event == "begin":
            if renpy.showing('doc'):
                renpy.show('doc', zorder=99)
            current_speaker = 'doc'
Then sometimes it will move a character to the front, other times it won't. If I don't include the zorder part then it won't move them at all.
Releases:
Image

Current projects:
In the Ashes of Dawn
Split Psyche
Savestate Gambit

kivik
Miko-Class Veteran
Posts: 786
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Move Character to the Front when Speaking?

#4 Post by kivik »

Interesting, it must mean that when it's triggered by a callback it doesn't get treated as shown in order...

I've been googling some more but can't seem to find any hits, but there must be an easier way without using callbacks, maybe someone else will be able to help. I'll keep looking out for the answer meanwhile

User avatar
gas
Miko-Class Veteran
Posts: 842
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: Move Character to the Front when Speaking?

#5 Post by gas »

In DDLC they solve the problem creating transforms for each position, one with normal zorder, and one with an higher zorder. It's a lil contrived solution, but chara callbacks don't work.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
lking22
Regular
Posts: 50
Joined: Sun Dec 03, 2017 3:33 am
Projects: Grey Feather
itch: freefall-games
Contact:

Re: Move Character to the Front when Speaking?

#6 Post by lking22 »

I'm not opposed to spaghetti code, so even if it's contrived as long as it works it's fine. I'll see if I still have DDLC files around to dig into and find how they do that.

EDIT: Okay so I just looked and it requires declaring the zorder every time, which I... REALLY don't want to have to do since that would require combing through the whole script again. I will if I have to, but I'm going to look for a less brute-force method first so I know how to do it for next time.
Releases:
Image

Current projects:
In the Ashes of Dawn
Split Psyche
Savestate Gambit

User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: Move Character to the Front when Speaking?

#7 Post by xavimat »

It's not pretty but, maybe it can work: To put a character in front of the others, hide it and immediately show it.
Or maybe, in your callback function (that I don't full y understand), use renpy.hide before renpy.show.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

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: Move Character to the Front when Speaking?

#8 Post by Remix »

Excuse the messy code:

Code: Select all


define nin = Character("Ninja Girl", image="nin_pic")

define myu = Character("Myu", image="myu_pic")

image nin_pic = "images/454.png"
image myu_pic = "images/546.png"


init -1 python:

    def char_callback(event, **kwargs):

        showing_tags = renpy.get_showing_tags()

        current_tag = renpy.get_say_image_tag()

        character_tags = [ 
            t for t in 
            ['nin_pic', 'myu_pic'] ### <----------- change this to list all character image tags in order
            if t in showing_tags 
            and t != current_tag ]

        if current_tag and event == "begin":

            for tag in character_tags:

                renpy.show( tag, zorder = 0 )

            renpy.show( current_tag, zorder = 100 )

        return (), kwargs

    config.all_character_callbacks.append( char_callback )

label start:

    show nin_pic at left 

    show myu_pic at left  

    nin "Hello There. Let me show you some of my ninjutsu"

    myu "Yes please"

    nin "Hello There. Let me show you some of my ninjutsu"

    myu "Yes please"

    nin "Hello There. Let me show you some of my ninjutsu"

    myu "Yes please"
Very basic test seemed to work ok.
It just does a renpy.show for all the showing characters leaving current speaker until last (just does it on the 'begin' event in callback)
Not fully sure if zorder is needed unless you set config.preserve_zorder (sp?) to True
Frameworks & Scriptlets:

User avatar
lking22
Regular
Posts: 50
Joined: Sun Dec 03, 2017 3:33 am
Projects: Grey Feather
itch: freefall-games
Contact:

Re: Move Character to the Front when Speaking?

#9 Post by lking22 »

Okay, I tried doing exactly what Remix suggested, and it only seems to work some of the time? But there doesn't seem to be any consistent pattern as to why it doesn't work the rest of the time. The code I'm testing it with is this:

Code: Select all

    show lat at left with ease
    show mid Normal at right2
    show thi Normal at right
    with easeinright
    m "Hello, Doctor Avery!"
    d "Hello, Midriel. And this is...?"
    t "Thisriel. It's a pleasure to meet you."
    $ thi_name = "Thisriel"
    jump fammeeting

label fammeeting:
    $ met_fam = True
    d "And you as well. Now, Midriel, Latael tells me you can clear his wings of grief?"
    m Grin "Spreading joy and countering grief is my job, so of course I can! Should I get started right away, Lattie?" #Doesn't move to front
    l Normal "Yes, please. The sooner we get rid of this grief, the better."
    m Normal "Okay then! Thisriel, Doctor Avery, stand back!" #Doesn't move to front
    show lat PainedWF
    nvl_narrator "Midriel spreads her wings wide and holds her hands out toward Latael. Almost immediately, a strange, uncomfortable feeling fills the air. It
                  fills me with restless energy, and I have to hold in a manic laugh. My damaged soul begins to ache at the strength of the feeling. It's as if
                  half of my mind is scattered and spinning off to the far corners of the earth, while the other half is all too present, bound so tightly to
                  my body that it becomes hard to even breathe."
    nvl_narrator "I don't understand how this is supposed to help anyone. But Latael and Thisriel don't seem to be affected in the same way. Thisriel's
                  expression hasn't changed, and Latael looks more peaceful than he's seemed in days. So why does it affect me so badly?"
    nvl_narrator "After what could have been either seconds or hours, Midriel stops. I have to lean on a nearby counter to keep myself from collapsing as I
                  gasp for breath."
    $ wings_cleared = True
    scene AsBreakRoom
    show lat ConcernedWF at left
    show mid Frown at right2
    show thi Concerned at right
    with dissolve
    l "Dad? Are you alright?"
    d "I'll be fine. That was just... a bit too much for me, I think..."
    m "Oh no... I knew that my magic could be jarring to people who aren't used to being happy, but I didn't think it would ever be that bad!"
    t Serious "Midriel, you still need to check Latael over for any lingering effects."
    m "But the doctor-!" #Doesn't move to front
    t "I'll look after him. We'll be just a few rooms away."
    m "Okay then..." #Doesn't move to front
Of course, it's possible that it's not working on other layers and I just can't see it because they're already in front or their image isn't overlapping anyone. Another problem is that whenever 'd' talks (the main character, who doesn't have his image shown for most of the game), it brings up a placeholder image.
Releases:
Image

Current projects:
In the Ashes of Dawn
Split Psyche
Savestate Gambit

User avatar
lking22
Regular
Posts: 50
Joined: Sun Dec 03, 2017 3:33 am
Projects: Grey Feather
itch: freefall-games
Contact:

Re: Move Character to the Front when Speaking?

#10 Post by lking22 »

Oh, thank goodness! I figured out what I was doing wrong. Remix's code did work, I was juts using it wrong. I entered in every image rather than every image tag, woops.
Oh, and I solved the issue of it trying to display images that weren't supposed to be in the scene, too. Edited code here (though it's basically Remix's with one line added):

Code: Select all

init -1 python:
    def char_callback(event, **kwargs):
        showing_tags = renpy.get_showing_tags()
        current_tag = renpy.get_say_image_tag()
        character_tags = [ 
            t for t in 
            [ 'doc ', 'dan', 'lat', 'mid', 'thi', 'sep', 'ret', 'mic', 'rap', 'azr', 'ari', 'jop', 'gab', 'cha', 'hun', 'imp', 'ext', 'ex2'] ### <----------- change this to list all character image tags in order
            if t in showing_tags 
            and t != current_tag ]
        if current_tag and event == "begin":
            for tag in character_tags:
                renpy.show( tag, zorder = 0 )
            if renpy.showing(current_tag):
                renpy.show( current_tag, zorder = 100 )
        return (), kwargs
    config.all_character_callbacks.append( char_callback )
Releases:
Image

Current projects:
In the Ashes of Dawn
Split Psyche
Savestate Gambit

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: Move Character to the Front when Speaking?

#11 Post by Remix »

lking22 wrote: Thu May 17, 2018 11:17 pm Okay, I tried doing exactly what Remix suggested, and it only seems to work some of the time? But there doesn't seem to be any consistent pattern as to why it doesn't work the rest of the time.
Glad you got it running nicely and working as you wanted.

While playing around with some possibilities I also kept getting inconsistent results.
Could not get anything using [ config.tag_zorder ] dictionaries to work nicely - most would have needed to use the "slow_done" event to reset the zorder and I found that event fires at odd times or sometimes not at all. Oddly, a [ show doc at left zorder 7 ] does not even use that dict (it just relies on setting a screen list order instead) so that approach maybe not hugely useful anyway.
Had a play with [ config.preserve_zorder ] with mixed results. Maybe more useful for other game aspects
Of course, it's possible that it's not working on other layers and I just can't see it because they're already in front or their image isn't overlapping anyone. Another problem is that whenever 'd' talks (the main character, who doesn't have his image shown for most of the game), it brings up a placeholder image.
Just for info:
Unless you use [ show doc onlayer overlay ] or similar, all show images just go on the master layer.

Once again, glad you got it working.

Not perfect, easy though and means not having to edit every line.
Frameworks & Scriptlets:

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: Move Character to the Front when Speaking?

#12 Post by Remix »

BTW:

Ren'Py 7+ (the pre-release and future versions) will support [ showing_tags = renpy.get_showing_tags( sort=True ) ] which should return them in a more consistent order (back to front). *** untested ***

You would need to alter the list comprehension though:

Code: Select all

        showing_tags = renpy.get_showing_tags( sort=True )
        current_tag = renpy.get_say_image_tag()
        all_character_tags =  [ 'doc ', 'dan', 'lat', 'mid', 'thi', 'sep', 'ret', 'mic', 'rap', 'azr', 'ari', 'jop', 'gab', 'cha', 'hun', 'imp', 'ext', 'ex2'] 
        character_tags = [ 
            t for t in showing_tags
            if t in all_character_tags 
            and t != current_tag ]
Frameworks & Scriptlets:

trajano
Regular
Posts: 60
Joined: Sun Jun 16, 2019 7:59 pm
Github: trajano
Contact:

Re: Move Character to the Front when Speaking?

#13 Post by trajano »

@Remix do you have the full script? I had this

Code: Select all

init python:
    def char_callback(event, **kwargs):
        showing_tags = renpy.get_showing_tags( sort=True )
        current_tag = renpy.get_say_image_tag()
        all_character_tags =  [ 'z', 'l', 'zelda', 'link' ] 
        character_tags = [ 
            t for t in showing_tags
            if t in all_character_tags 
            and t != current_tag ]
        if current_tag and event == "begin":
            for tag in character_tags:
                renpy.show( tag, zorder = 0 )
            if renpy.showing(current_tag):
                renpy.show( current_tag, zorder = 100 )
        return (), kwargs
    config.all_character_callbacks.append( char_callback )
And I am invoking this

Code: Select all

    show zelda thinking
    show link thinking
    l "..."
    show zelda casual talking
    z "Sounds like a plan.  We'll see you two later!"
but
But Link still shows in front.

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: Move Character to the Front when Speaking?

#14 Post by Remix »

An updated version (no need to tell it your sprite tags as it adds them as needed)...

Code: Select all

default all_character_tags = []

init python:

    def char_callback(event, **kwargs):

        global all_character_tags 

        if event == "show": # or "begin"... both should be fine

            current_tag = renpy.get_say_image_tag()

            if current_tag not in all_character_tags:
                all_character_tags.append(current_tag)

            sprite_tags = [ k for k in renpy.get_showing_tags() 
                            if k in all_character_tags ]

            for z,k in enumerate(sprite_tags):
                zorder = z if k != current_tag else len(sprite_tags)
                renpy.show(k, zorder=zorder )

        return (), kwargs

    config.all_character_callbacks.append( char_callback )
If you use config.tag_zorder, you might need to include that in the zorder calculation though...
Frameworks & Scriptlets:

turdl3
Newbie
Posts: 1
Joined: Sun Aug 25, 2019 1:54 pm
Contact:

Re: Move Character to the Front when Speaking?

#15 Post by turdl3 »

Hey, I stumbled upon this thread when trying to do this myself, and Remix's post helped a lot (thank you!). However, it doesn't really accommodate for image attributes (I had a character going angry while saying something, but the Python code showed their neutral sprite instead). I wrote something quick to fix that, and it works fine for me so far, though I'm very new to Renpy so I'm unsure if it'll cause any problems later on.

Code: Select all

init python:
    default all_character_tags = []
    def char_callback(event, **kwargs):
        global all_character_tags
        if event == "begin": 
            current_tag = renpy.get_say_image_tag()
            if current_tag not in all_character_tags:
                all_character_tags.append(current_tag)
            sprite_tags = [ k for k in renpy.get_showing_tags()
                            if k in all_character_tags ]
            for z,k in enumerate(sprite_tags):
                att = renpy.get_attributes(k)
                zorder = z if k != current_tag else len(sprite_tags)
                if str(att) == "()":
                    renpy.show(k, zorder=zorder)
                else:
                    renpy.show(str(k) + " " + str(att[0]), zorder=zorder )
        return (), kwargs

    config.all_character_callbacks.append( char_callback )
Just wanted to share in case it helps anyone.

Post Reply

Who is online

Users browsing this forum: No registered users