image change after a limited number of repeats

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
pistach
Newbie
Posts: 22
Joined: Tue Mar 05, 2019 9:25 am
Contact:

image change after a limited number of repeats

#1 Post by pistach » Wed Jul 03, 2019 9:27 pm

Hi.

Is it possible to make an image repeat a displayable a limited number of times and then show another displayable?

I'm making the characters in my game "talk" using layered images and the "_last_say_who" variable. Something like this:

Code: Select all

init:
	image pov_talk:
        	choice:
        	    	"pov/pov_mouth_mtalk1.png"
        	choice:
        	    	"pov/pov_mouth_mtalk2.png"
        	choice:
        	    	"pov/pov_mouth_mtalk3.png"
        	choice:
            		"pov/pov_mouth_mtalk4.pn
I have a number of talking mouths, as seen above.

And a layeredimage like this:

Code: Select all

layeredimage pov:
    	always:
        	"pov_base"
        group mouth:
 	       	attribute mneu default:
            		"pov_mouth_mneu"
 
Then I change the mouth variable when the character is talking so that the sprite's mouth randomly change and appear to "talk".

Code: Select all

image pov_mouth_mtalk:
    	"pov_talk"
    	.2
    	repeat

image pov_mouth_mneu =  ConditionSwitch(
            "_last_say_who == 'pov'", "pov_mouth_mtalk",
            "not _last_say_who == 'pov'", "pov/pov_mouth_mneu.png")

So far it works wonderful (I'm pleasantly surprised I got it working!). But I don't want the sprites to go on talking forever (until the click).

I want to be able to either make them stop and show the closed neutral mouth after a number of repeats or time passed, OR - even better - have them repeat the loops depending on the length of the "_last_say_what" so that their "talking" reflect how many characters their sentence or utterance had.

I failed miserably when I tried to make that "_last_say_what" work, so I decided to (at least for now) have them all stop after a set number of loops and then show the neutral mouth after it, something like this:

Code: Select all

image pov_mouth_mtalk:
    	"pov_talk"
    	.2
    	repeat 10
    	"pov/pov_mouth_mneu.png"


But I've had no success with this one either. I tried everything I know: blocks, parallel, contains...
I'm doing something wrong or failing to understand something (perhaps basic - I don't feel like I'm doing advanced coding here...).

The closest I came to getting it right was through doing this:

Code: Select all

image atl_pov_mouth_mtalk:
    	"pov_talk"
    	.2
    	repeat 

image pov_mouth_mtalk:
    	atl_pov_mouth_mtalk
    	pause 5
    	"pov/pov_mouth_mneu.png"
This works only on the first time the sprite is shown. On subsequent sentences or talking instances only the last displayable is shown (i.e. the neutral one).

Any help / advice is hugely appreciated!
Cheers

User avatar
PyTom
Ren'Py Creator
Posts: 15893
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: image change after a limited number of repeats

#2 Post by PyTom » Thu Jul 04, 2019 3:50 pm

Repeat takes a number in conjuction with block.

Code: Select all

image pov_talk:
     block:
        	choice:
        	    	"pov/pov_mouth_mtalk1.png"
        	choice:
        	    	"pov/pov_mouth_mtalk2.png"
        	choice:
        	    	"pov/pov_mouth_mtalk3.png"
        	choice:
            		"pov/pov_mouth_mtalk4.png"

                pause .2
                repeat 10

      "pov/pov_mouth_done.png"
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
"Silly and fun things are important." - Elon Musk
Software > Drama • https://www.patreon.com/renpytom

User avatar
pistach
Newbie
Posts: 22
Joined: Tue Mar 05, 2019 9:25 am
Contact:

Re: image change after a limited number of repeats

#3 Post by pistach » Thu Jul 04, 2019 4:57 pm

Hi and thanks!

It didn't work.
When the first time the sprite is shown it goes through the repeats and then shows the final "done" image as intended. But on all next dialogue lines there is no "talking" and the whole block is ignored, causing the sprite to be stuck on it's last "done" mouth.

User avatar
PyTom
Ren'Py Creator
Posts: 15893
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: image change after a limited number of repeats

#4 Post by PyTom » Thu Jul 04, 2019 11:48 pm

You'd have to hide and re-show it for the timer to reset.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
"Silly and fun things are important." - Elon Musk
Software > Drama • https://www.patreon.com/renpytom

User avatar
pistach
Newbie
Posts: 22
Joined: Tue Mar 05, 2019 9:25 am
Contact:

Re: image change after a limited number of repeats

#5 Post by pistach » Fri Jul 05, 2019 4:54 am

Okay I think I got it!

The only question is that will hiding and re-showing the sprites before each dialogue line negatively impact the game's performance?

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: image change after a limited number of repeats

#6 Post by Remix » Fri Jul 05, 2019 9:39 am

An alternative approach using DynamicDisplayable that picks a random mouth while the tag matches the get_say_image_tag (and for N seconds from start of dialogue) and base image otherwise...
For this to work, your characters will NEED their image tag attribute set:

Code: Select all

define e = Character("Eileen", image="eileen")
The following usage just uses full sprites as I did not have an easy test area with composites or layereds...
It should be quite straight forward to use in a LayeredImage though do note that while Not talking it uses a set image (so, if you use mouth expressions, it might be best to set that default image to be a transparent png rather than a default mouth (you'd have mouth expression behind mouth talking so that when mouth talking wasn't running it would just show through to the expression if that makes sense))
Anyway:

Code: Select all

# This dictionary allows us to hold time values for characters to talk until
default talking_offsets = {} # tag : (offset, lineId)

init python:

    def talking_mouth(st, at, *args, **kwargs):

        global talking_offsets
        tag = kwargs.get('tag', None)
        current_tag = renpy.get_say_image_tag()

        if current_tag == tag and st:
            line_id = renpy.get_filename_line()
            #
            # the time that this line takes (I used 10 letters of dialogue = 1 second talk)
            #
            talk_time = float(len(_last_say_what) * 0.1)
            
            if not tag in talking_offsets \
            or line_id != talking_offsets[tag][1]:
                # our tag is either not there yet or we have moved to a new line
                # so we calculate a total st by adding the talk time
                talking_offsets[tag] = (st+talk_time, line_id)

            if st < talking_offsets[tag][0]:
                # this character is talking... random return from non first arguments
                # the 0.1 at the end is the frame duration
                return renpy.random.choice(args[1:]), 0.1

        # not talking, return the first image from the arguments
        return args[0], 0.1

    # always good to support prediction
    def predict_talking_mouth(*args, **kwargs):
        return list(args)

image eileen_mouth = DynamicDisplayable(
    talking_mouth,
    "eileen mouth normal", "eileen mouth open", "eileen mouth pursed", "eileen mouth lipbite",
    tag="eileen",
    _predict_function=predict_talking_mouth)

# image eileen_mouth = DynamicDisplayable(
    # the function to call ... always talking_mouth,
    # mouth images - first is default, then the rest are possible choices while talking
    #    You could use full image filepaths here "images/eileen_mouth_normal.png", etc
    # keyword 'tag' - set to be the same as the image="value" from the character ... tag="eileen"
    #  _predict_function=predict_talking_mouth)
Note that the mouth can always be there, you do not need to just add it while talking. It will only go into talking mode while the relevant character is talking

Yours would be something like:

Code: Select all

image pov_mouth_mneu = DynamicDisplayable(
    talking_mouth,
    "pov/pov_mouth_mneu.png",
    "pov/pov_mouth_mtalk1.png",
    "pov/pov_mouth_mtalk2.png",
    "pov/pov_mouth_mtalk3.png",
    "pov/pov_mouth_mtalk4.png",
    tag="pov",
    _predict_function=predict_talking_mouth)
Frameworks & Scriptlets:

User avatar
pistach
Newbie
Posts: 22
Joined: Tue Mar 05, 2019 9:25 am
Contact:

Re: image change after a limited number of repeats

#7 Post by pistach » Fri Jul 05, 2019 11:52 am

Hi there
Thank you very very much guys.

Your approach, Remix, worked perfect.
Now the sprites are all happy that they can have a conversation (without looking weird!).

Look:
https://i.imgur.com/b4bSIFD.gif

Post Reply

Who is online

Users browsing this forum: GetOutOfMyLab