[Solved] Trouble with Side Image Lip Flap / Using LayeredImageProxy with Specific Attritbutes

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
niho
Newbie
Posts: 20
Joined: Fri Apr 15, 2022 11:31 pm
itch: nihomi
Discord: niho#0953
Contact:

[Solved] Trouble with Side Image Lip Flap / Using LayeredImageProxy with Specific Attritbutes

#1 Post by niho »

I have animated sprites with lip flap and I'm trying to make a side image version of each of them using LayeredImageProxy (so I don't have to make extra assets). I brute forced a somewhat working solution, but then I ran into the issue of the side images not changing expressions properly. Here is my current setup:

Code: Select all

define cside = Character("Clover", image="cside", callback=cside_anim, color = "f0a", what_prefix='"', what_suffix='"')

init -1 python:
    def cside_anim(event, interact=True, **kwargs):
        if event == "show":
            renpy.show("side cside talk", at_list=[left], layer='sides')
            renpy.sound.play("audio/blip.mp3")
        elif event == "slow_done" or event == "end":
            renpy.hide("side cside talk", layer='sides')
            renpy.show("side cside hush", at_list=[left], layer='sides') # always shows default closed mouth even if "clover awetalk" was just shown
            renpy.sound.stop()
            renpy.restart_interaction()

init:
    layeredimage clover base:
        always "clover base.png"
        always "clover_blink"
        group mouth:
            attribute hush default:
                "clover mouth.png"
            attribute talk:
                "clover_talk"
             
    # added this because I couldn't figure out how to pass attributes to cside_anim            
    layeredimage clover basetalk:
        always "clover base.png"
        always "clover_blink"
        always "clover_talk"
    
    ##layeredimages for 'clover awe' and 'clover awetalk' go here, identical to above just with different images 
        
    # what I really want to do here is set the side images equal to the base image with a specific attribute i.e. "clover base hush" 
    # but that throws an error because its not a defined image
    image side cside talk = LayeredImageProxy("clover basetalk", Transform(crop=(15, -100, 420, 360), zoom=1.5))
    image side cside hush = LayeredImageProxy("clover base", Transform(crop=(15, -100, 420, 360), zoom=1.5))

    image side cside talk awe = LayeredImageProxy("clover awetalk", Transform(crop=(15, -100, 420, 360), zoom=1.5))
    image side cside hush awe = LayeredImageProxy("clover awe", Transform(crop=(15, -100, 420, 360), zoom=1.5))
And then a basic test script:

Code: Select all

label start:
    show clover base with dissolve
    c "I'm talking normally."
    c awe "Now I'm surprised."
    c base "Back to normal."
    show side cside hush at left onlayer sides with dissolve
    cside "Here I am on the side."
    show side cside hush awe onlayer sides with dissolve
    cside "Surprised on the side." # shows awe sprite while talking, but jumps to base sprite when done 
    c awe "Alright, you get the idea."
return
I have no idea why the sprite change works for cside talk but not cside hush. At this point even if I figure it out my code feels terribly inefficient... so any guidance would be greatly appreciated.

Also, side images are on a separate layer because they were displaying under the textbox for some reason (I didn't edit the say screen at all so add SideImage() comes after the window statement). And without the at left transform the side image isn't positioned properly.
Last edited by niho on Tue Dec 06, 2022 8:43 pm, edited 1 time in total.

User avatar
_ticlock_
Miko-Class Veteran
Posts: 910
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Trouble with Side Image Lip Flap / Using LayeredImageProxy with Specific Attritbutes

#2 Post by _ticlock_ »

niho wrote: Mon Dec 05, 2022 8:12 pm
1) It is a bad idea to use spaces in image naming:

Code: Select all

layeredimage clover base:
even if it does not result in error or conflict, it may potentially create one later and it is going to be hard to figure out where the problem comes from
Also, I recommend not to use the same names for the same reasons ( clover base, clover base.png)

2) It seems you use character callback cside_anim only to distinguish if the character speaks. You can use config.speaking_attribute instead.

3) It is not clear what the difference is between characters c and cside. Is it only to display character c on side with some transform? What is also a point of using side cside image? Are you trying to use character cside to avoid explicitly use show cside statements?

4)
niho wrote: Mon Dec 05, 2022 8:12 pm Also, side images are on a separate layer because they were displaying under the textbox for some reason
Look at the definition of the say screen, it adds the side image to the say screen at a specific location. If you use show statements for the side image, you put the image on the default layer with default transform.
Last edited by _ticlock_ on Tue Dec 06, 2022 5:59 pm, edited 1 time in total.

User avatar
_ticlock_
Miko-Class Veteran
Posts: 910
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: Trouble with Side Image Lip Flap / Using LayeredImageProxy with Specific Attritbutes

#3 Post by _ticlock_ »

niho wrote: Mon Dec 05, 2022 8:12 pm
Let me suggest the following solution:

Code: Select all

define config.speaking_attribute = "talk"

Code: Select all

define c = Character("Clover", image="clover") # without callback argument

layeredimage clover_base:
    always "clover base.png"
    always "clover_blink"
    # Add groups that all images shares
    
layeredimage clover:
    always "clover_base"
    group mouth:
        attribute hush default:
            "clover mouth.png"
        attribute talk:
            "clover_talk"
            
layeredimage clover awe:
    always "clover_base"
    group mouth:
        attribute hush default:
            "clover awe mouth.png"
        attribute talk:
            "clover_awetalk"

Code: Select all

label start:
    show clover
    "You can see clover hush"
    c "You can see clover talk"
    c awe "You can see clover awe talk"
    "You can see clover awe hush"
    c -awe "You can see clover talk again without awe"
If you want to show the image on side with some transform you can simply do this:

Code: Select all

transform side_image_tr:
    crop (15, -100, 420, 360)
    zoom 1.5

Code: Select all

label start:
    show clover at side_image_tr onlayer sides
If you want to avoid explicitly use show statements and use side image:

Code: Select all

image side clover = LayeredImageProxy("clover", Transform(crop=(15, -100, 420, 360), zoom=1.5))
image side clover awe = LayeredImageProxy("clover awe", Transform(crop=(15, -100, 420, 360), zoom=1.5))

User avatar
niho
Newbie
Posts: 20
Joined: Fri Apr 15, 2022 11:31 pm
itch: nihomi
Discord: niho#0953
Contact:

Re: Trouble with Side Image Lip Flap / Using LayeredImageProxy with Specific Attritbutes

#4 Post by niho »

Wow, thank you for such a detailed response!! I took some of your advice and it works great, though I made a few adjustments to suit my needs better. And sorry, I should've specified that c is for the full sprite and cside is for the side image (because I want them to be animated independently).

I'm sticking with character callback because I also want a text blip sound effect during dialogue and afaik callback is the only way to do that. Also it seems that with config.speaking_attribute the talking animation doesn't sync up with cps and just loops continuously.

For reference, here is what I ended up with:

Code: Select all

define c = Character("Clover", image="clover", callback=c_anim)
define cside = Character("Clover", image="clover", callback=cside_anim)

init -1 python:
    #c_anim goes here, identical to below just without side transform/layer in renpy.show()

    def cside_anim(event, interact=True, **kwargs):
        if event == "show":
            renpy.show("clover talk", at_list=[side_image_tr], layer='sides')
            renpy.sound.play("audio/blip.mp3")
        elif event == "slow_done":
            renpy.show("clover hush", at_list=[side_image_tr], layer='sides')
            renpy.sound.stop()
            renpy.restart_interaction()

init:
    layeredimage clover: 
        always "clover base.png"
        always "clover_blink"
        group mouth:
            attribute hush default:
                "clover mouth.png"
            attribute talk:
                "clover_talk"
    
    # clover awe goes here, identical to above just with different images 

    transform side_image_tr:
        crop (15, -100, 420, 360) zoom 1.5 xalign 0.0 yalign 1.0

Code: Select all

label start:
    show clover with dissolve 
    c "I'm talking normally."
    c awe "Now I'm surprised."
    c -awe "Back to normal."
    show clover at side_image_tr onlayer sides with dissolve
    cside "Here I am on the side."
    show clover awe onlayer sides with dissolve
    cside "Surprised on the side."
I might try explicitly defining the side images later but for now I'm happy with this solution, so I'll mark this as solved. Once again, thanks for the help _ticlock_! I'm a bit embarrassed I didn't think of using transforms to begin with :lol:

Post Reply

Who is online

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