"brightness pulse" when a character starts talking?

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.
Message
Author
User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

"brightness pulse" when a character starts talking?

#1 Post by Rainvillain »

Hi there,

I'm trying to make my character portrait briefly "pulse" when that character first has a line of dialogue. This would be a brief indicator as to who's talking without having to look at the character's name (in my game there are many instances in which two characters are on screen and talking to each other). It wouldn't pulse every time the character speaks consecutively, just the first time. It's basically just to say "this is the character that is talking now".

The "pulse" would be a very very slight boost in the brightness of the character portrait for a few milliseconds before returning to normal. Unfortunately I have very little experience with manipulating displayables in ren'py.
From reading through the documentation I think https://www.renpy.org/doc/html/displaya ... brightness is what I'm supposed to be using, but I'm not too sure how to call upon it, and also to have the brightness boost last only for a few milliseconds.

This is example code of what I would want it to look like:

Code: Select all

define e = Character("Eileen")
define c = Character("Carl")


# The game starts here.

label start:

    scene bg kitchen

    show eileen at left
    show carl at right

    e "Hi I'm Eileen." #e pulse
    c "And I'm Carl." #c pulse
    e "I'm pulsing..." #e pulse
    c "...and now I'M pulsing!" #c pulse
    c "But now I'm not pulsing, since I'm the same person who spoke on the last line of dialogue." #c DOESN'T pulse
    e "Oh I see. But now I'm pulsing!" #e pulse
    e "...but not anymore." #e DOESN'T pulse
    c "This is wild." #c pulse


    # This ends the game.

    return
I would prefer not have to include a "with character pulse" tag at the end of every appropriate sentence... ideally the code would simply know that since the character talking is different from the last person talking have their portrait pulse, but is that part a little too much to ask?

Thanks!

User avatar
Lord Hisu
Regular
Posts: 58
Joined: Sun Feb 11, 2018 2:31 am
Contact:

Re: "brightness pulse" when a character starts talking?

#2 Post by Lord Hisu »

Maybe you could use a Character Callback.
docs wrote:Ren'Py includes the ability to execute callbacks when various events occur during dialogue. This is done by giving the callback argument to Character(), or setting the config.character_callback or config.all_character_callbacks variables.

"begin"
Called at the start of a say statement.
You could bind your own method to all_character_callbacks. This method should check the last character who spoke, and if it's a different character, change the brightness.

DannX
Regular
Posts: 99
Joined: Mon Mar 12, 2018 11:15 am
Contact:

Re: "brightness pulse" when a character starts talking?

#3 Post by DannX »

To use im.matrix.brightness you have to create a new image object. Something like this:

Code: Select all

image eileen bright = im.MatrixColor("eileen.png",im.matrix.brightness(.2)) 
To have it just blink for a few seconds, you could make the image an ATL block:

Code: Select all

 
 image eileen pulse:
    "eileen.png"
    pause .2
    im.MatrixColor("eileen.png",im.matrix.brightness(.2))
    pause .2
    "eileen.png"


And show it. The problem with this method is that you'll likely have to make a pulse image for every character in your game, and you'll have to constantly show it whenever a new character speaks, unless you combine it somehow with Lord Hisu's suggestion above.

User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

Re: "brightness pulse" when a character starts talking?

#4 Post by Rainvillain »

Thank you very much Lord Hisu and DannX!

So I now have the pulse working on a per character basis...

Code: Select all

image eileen pulse:
    "eileen.png"
    pause .001
    im.MatrixColor("eileen.png",im.matrix.brightness(.2))
    pause .05
    im.MatrixColor("eileen.png",im.matrix.brightness(.1))
    pause .05
    im.MatrixColor("eileen.png",im.matrix.brightness(.05))
    pause .1
    "eileen.png"
image carl pulse:
    "carl.png"
    pause .001
    im.MatrixColor("carl.png",im.matrix.brightness(.2))
    pause .05
    im.MatrixColor("carl.png",im.matrix.brightness(.1))
    pause .05
    im.MatrixColor("carl.png",im.matrix.brightness(.05))
    pause .1
    "carl.png"

label start:

    scene bg kitchen

    show eileen pulse at left
    show carl at right
    e "I'm pulsing..."
    show carl pulse
    c "...and now I'M pulsing!" 
    c "But now I'm not pulsing, since I'm the same person who spoke on the last line of dialogue."
    show eileen pulse
    e "Oh I see. But now I'm pulsing!"

    # This ends the game.

    return
...but now I'm trying to figure out how to use the character callback function since this would take forever to manually implement.
Specifically, I'm not too sure how to make renpy check if the current person speaking is the same as the person who spoke on the previous line. I've started an init based on the example in the documentation Lord Hisu linked but it's missing the glue to make it work:

Code: Select all

init python:
    def char_pulse(??): #<- this part is a question mark to me, and I assume I'm trying to make it check if the current speaker is the same as the last person to speak
        if not interact: #if not, then make current speaker's portrait pulse
            show character pulse 

        if event == (??) #if current speaker IS the same speaker as the last line of dialogue, then nothing happens
            return 
           

define e = Character("Eileen", callback=char_pulse)
define c = Character("Carl", callback=char_pulse)
So obviously this doesn't work, but I'm hoping someone might be able to gently nudge me in the right direction here haha. I know Lord Hisu said I should specifically use the all_character_callbacks function but even that I'm not sure how to use... if I use that function does that mean I don't need to include "callback=" while defining my characters?

User avatar
Lord Hisu
Regular
Posts: 58
Joined: Sun Feb 11, 2018 2:31 am
Contact:

Re: "brightness pulse" when a character starts talking?

#5 Post by Lord Hisu »

Okay, so... I really liked your idea and decided to code it (I should be sleeping, but I couldn't resist).

Code: Select all

init:
    default speaking_char = None
    image eileen pulse:
        "eileen.png"
        pause .001
        im.MatrixColor("eileen.png", im.matrix.brightness(.2))
        pause .05
        im.MatrixColor("eileen.png", im.matrix.brightness(.1))
        pause .05
        im.MatrixColor("eileen.png", im.matrix.brightness(.05))
        pause .1
        
    image someone pulse:
        "someone.png"
        pause .001
        im.MatrixColor("someone.png", im.matrix.brightness(.2))
        pause .05
        im.MatrixColor("someone.png", im.matrix.brightness(.1))
        pause .05
        im.MatrixColor("someone.png", im.matrix.brightness(.05))
        pause .1
        
    python:
        from functools import partial
        def char_pulse(char, event_name, *args, **kwargs):
            if event_name == "begin" and char != store.speaking_char:
                renpy.show(char + " pulse")
                store.speaking_char = char
                
    define e = Character("Eileen", callback=partial(char_pulse, "eileen"))
    define s = Character("Someone", callback=partial(char_pulse, "someone"))
    

label start:
    show eileen at left
    show someone at right
    
label talk:
    s "Hello~"
    e "Hello!"
    e "Hey, I just pulsed."
    e "Uuuh, not anymore, I guess..."
    s "I didn't see anything."
    s "Woah, I pulsed too... but not this time."
    e "It seems we pulse everytime we talk."
    s "That's sooooo cool."
    jump talk
I hope you make good use of it. :mrgreen:

User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

Re: "brightness pulse" when a character starts talking?

#6 Post by Rainvillain »

Wow! Thanks Lord Hisu, this is incredible! I'll be sure to give you a big thank you in the credits of my game :)

User avatar
Lord Hisu
Regular
Posts: 58
Joined: Sun Feb 11, 2018 2:31 am
Contact:

Re: "brightness pulse" when a character starts talking?

#7 Post by Lord Hisu »

I'm pretty sure you don't need to declare one pulse for each character. You can probably define one generic pulse using Python that receives the character name and state as an argument... something like this.
This way, the pulse works for just one image, and you need to declare one for each character. It's not very practical.

I appreciate your big thanks. :mrgreen:
Looking forward to play your game!

User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

Re: "brightness pulse" when a character starts talking?

#8 Post by Rainvillain »

Hi again,

So I've hit a bit of a snag. Whenever I'm displaying a character whose show statement includes an additional piece of information (such as show eileen sad), then my pulsing brightness reverts to the neutral eileen.png for the actual flash, instead of using the sad looking eileen (eileen sad.png) which was being displayed.

I understand why it's showing the default eileen flashing, but I'm wondering if there's a way to have the code know to flash not just any eileen portrait but specifically the one currently on screen? I don't mind having to write out the pulsing code in init (that Lord Hisu so generously wrote) for each of my characters, but it wouldn't be feasible to write out a new pulsing code for every single character's various facial expressions.

User avatar
Lord Hisu
Regular
Posts: 58
Joined: Sun Feb 11, 2018 2:31 am
Contact:

Re: "brightness pulse" when a character starts talking?

#9 Post by Lord Hisu »

I can't help you with this one... it's more a Renpy thing than Python. As I said on my last post, I'm sure there must be a way to define a single pulse and use it for all images, but I don't know ATL that much (I'll get there soon), so I don't know how to write an ATL block with a variable image name (it is probably simple, but I couldn't find it on the docs).

I'll be following the topic, though, because I want to know the answer too.

philat
Eileen-Class Veteran
Posts: 1912
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: "brightness pulse" when a character starts talking?

#10 Post by philat »

The problem is there's no easy way to use ATL to change the brightness of an image. Image manipulators aren't the same thing. (For the record, PyTom, we all miss the old alpha exceeding 1.0!! ;) )

If you don't mind compromising, a very simple workaround would be use a little zoom instead of a brightness pulse. If you really want to stick to brightness, that'll take way more fiddling.

Code: Select all

transform pulse:
    linear 0.1 zoom 1.01
    pause 0.1
    linear 0.1 zoom 1.0

default speaking_char = None

init -1 python:
    def char_pulse(char, event_name, *args, **kwargs):
        if event_name == "begin" and char != store.speaking_char:
            if char != None:
                tags = renpy.get_attributes(char)
                str_tags = " ".join(tags)
                renpy.show(char + " " + str_tags, at_list=[pulse])
            store.speaking_char = char
Last edited by philat on Thu Apr 12, 2018 10:52 am, edited 2 times in total.

philat
Eileen-Class Veteran
Posts: 1912
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: "brightness pulse" when a character starts talking?

#11 Post by philat »

Additional thoughts:

An image using additive over the original image appears to approximate what used to happen with old alpha > 1.0. (As a sidenote, this is not quite the same as using MatrixColor and adjusting the brightness -- more like upping brightness and contrast at the same time resulting in some extra saturation -- however, it's usually passable as a 'brighter' version.) The issue is that the only way to have two overlapping images in a transform, as far as I can tell, is using contains, which places everything in a Fixed (which is basically a full screen box), throwing off position properties (like align or pos). You can specify the size of the Fixed, but I don't know how you would do that based on the transform's child image, as there's no easy way of getting the size of an image from disk.

If, however, all character images are the same size (which could be achieved by having extra blank space around a character that is smaller than the standard), then you can just hardcode the size of the Fixed. So if it isn't already the case that all your images are the same size, this could involve some extra work editing images, but it would work, as far as I've tested. If anybody else has a better idea on getting the size of the image, happy to hear it.

Code: Select all

transform pulse_additive(child):
    size (500, 652) # this happened to be the size of the image I was testing on.
    contains:
        child
        alpha 1.0
    contains:
        child
        linear 0.2 additive 0.2
        pause 0.2
        linear 0.2 additive 0.0

User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

Re: "brightness pulse" when a character starts talking?

#12 Post by Rainvillain »

Hi philat thanks for your suggestions!
Both those ideas seem great, but I'm struggling to input your pieces of code into my game (sorry, my coding prowess is extremely lacking..).
Specifically, I don't know how to make either of those pieces of code mesh with the existing code that Lord Hisu wrote.

If you would be able to walk me through how to implementing it I would very appreciative, since I think both your suggestions sound really good! No rush :)

philat
Eileen-Class Veteran
Posts: 1912
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: "brightness pulse" when a character starts talking?

#13 Post by philat »

Well, replace the char_pulse function (I named it the same...) and use either pulse or pulse_additive in at_list, whichever you prefer. The example above uses pulse (at_list=[pulse]).

User avatar
Rainvillain
Regular
Posts: 76
Joined: Thu Mar 05, 2015 11:27 am
Contact:

Re: "brightness pulse" when a character starts talking?

#14 Post by Rainvillain »

So for the time being I'm just trying to sort out the zooming pulse. This is how I've implemented into the script:

Code: Select all

transform pulse:
    linear 0.1 zoom 1.01
    pause 0.1
    linear 0.1 zoom 1.0

default speaking_char = None

init -1 python:
    def char_pulse(char, event_name, *args, **kwargs):
        if event_name == "begin" and char != store.speaking_char:
            if char != None:
                tags = renpy.get_attributes(char)
                str_tags = " ".join(tags)
                renpy.show(char + " " + str_tags, at_list=[pulse])
            store.speaking_char = char

    define e = Character("Eileen", callback=partial(char_pulse, "eileen"))
    define s = Character("Someone", callback=partial(char_pulse, "someone"))


label start:
    show eileen at left
    show someone at right

label talk:
    s "Hello~"
    e "Hello!"
    e "Hey, I just pulsed."
    e "Uuuh, not anymore, I guess..."
    s "I didn't see anything."
    s "Woah, I pulsed too... but not this time."
    e "It seems we pulse everytime we talk."
    s "That's sooooo cool."
    jump talk
and got the following error:

Code: Select all

[code]
I'm sorry, but errors were detected in your script. Please correct the
errors listed below, and try again.


File "game/script.rpy", line 17: invalid syntax
    define e = Character("Eileen", callback=partial(char_pulse, "eileen"))
            ^
    

Ren'Py Version: Ren'Py 6.99.14.1.3218
Thu Apr 12 14:07:39 2018
[/code]

I assume I've taken too much or not enough of Lord Hisu's initial code, but can't tell which one...

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: "brightness pulse" when a character starts talking?

#15 Post by trooper6 »

This is how I did it for one of my projects. This is tested and it works. This is also complete code.
I recommend creating a new project with just this code (names changed for your images of course), and trying it out.

Code: Select all

define j = Character("Jack", image="jack")
define p = Character("Perry", image="perry")

image jack speaking= At("images/jack.png", pulse)
image perry speaking= At("images/perry.png", pulse)
define config.speaking_attribute = "speaking"

transform pulse:
    zoom 1.0
    easein 0.2 zoom 1.02
    easeout 0.2 zoom 1.0

# The game starts here.

label start():
    scene underpass
    show jack at left
    show perry at right
    j "Game starts"
    j "Here I am."
    p "I'm here, too!"
    p "Hanging out."
    j "We're just hanging out."
    p "Now the game is over."

    return

In this thread xela game me some code that would allow me to automate lots and lots of speaking image declarations:
viewtopic.php?f=8&t=38083&p=412115&hili ... te#p412115
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot], piinkpuddiin, snotwurm